Move dili için bir başka yüksek riskli güvenlik açığı derinlik analizi
Daha önce Aptos Moveevm'de ciddi bir güvenlik açığı keşfetmiştik, derinlemesine araştırmalar sonucunda yeni bir tamsayı taşma açığı daha bulduk. Bu seferki açığın tetiklenme süreci daha ilginç, aşağıda bu açığı derinlemesine analiz edeceğiz ve aynı zamanda bazı Move diline dair arka plan bilgilerini tanıtacağız. Bu makalenin açıklamaları sayesinde, Move dili hakkında daha derin bir anlayışa sahip olacağınıza inanıyoruz.
Herkesin bildiği gibi, Move dili byte kodunu çalıştırmadan önce kod birimlerini doğrular. Doğrulama süreci 4 adıma ayrılmıştır ve bu açık reference_safety adımında ortaya çıkmıştır.
reference_safety modülü, işlem nesnesinin referans güvenliğini doğrulamak için kullanılan transfer fonksiyonlarını tanımlar. Kontrolleri, asılı referansların olmadığını doğrulamak, değişken referanslara erişimin güvenli olup olmadığını kontrol etmek ve global depolama referanslarına erişimin güvenli olup olmadığını kontrol etmek gibi unsurları içerir.
Güvenlik doğrulama çağrısının giriş fonksiyonu analyze_function'u çağıracaktır. analyze_function içinde, fonksiyon her bir temel bloğu doğrulayacaktır. Temel blok, giriş ve çıkış dışında hiçbir dal komutu içermeyen kod dizisidir.
Move dili, bayt kodunu dolaşarak, tüm dal talimatlarını ve döngü talimatı dizilerini bulup temel blokları belirler. Tipik bir Move IR kodu temel blok örneği, BrTrue, Branch ve Ret talimatlarıyla belirlenen 3 temel blok içerebilir.
Move'daki referans güvenliği
Rust dilinin felsefesinden faydalanarak, Move iki tür referansı destekler: değiştirilemez referans ( ve değiştirilebilir referans )&mut (. Değiştirilemez referanslar, yapıdan veri okumak için kullanılırken, değiştirilebilir referanslar verileri değiştirmek için kullanılır. Referans türlerinin mantıklı kullanımı, güvenliği korumaya ve okuma modülünü tanımlamaya yardımcı olur.
Move'in referans güvenliği modülü, fonksiyonları birim olarak alarak, fonksiyon içindeki temel blokların bayt kodu talimatlarını tarar ve tüm referans işlemlerinin yasallığını doğrular. Doğrulama süreci esas olarak AbstractState yapısını içerir; bu yapı, fonksiyon içindeki referansların güvenliğini sağlamak için borrow graph ve locals içerir.
Doğrulama süreci, temel blokların öncesi ve sonrası durumunu karşılaştıracak ve sonuçları blok durumunu güncellemek için birleştirecek, aynı zamanda bu bloğun son koşullarını sonraki bloklara yayacaktır. Bu süreç, V8 turbofan'daki Sea of Nodes fikrine benzer.
Ana döngü blok kodunu çalıştıracak ve ardından pre state ile post state'i birleştirmeye çalışacaktır. Eğer durum değişirse ve mevcut blok kendisine yönlendiren bir geri kenar ) varsa, bu bir döngü olduğunu gösterir. O zaman döngü başına geri dönecek ve bu temel bloğu yürütmeye devam edecektir, ta ki post state pre state'e eşit olana veya bir hata nedeniyle durana kadar.
Açık Analizi
Açık, join sonucunun değişip değişmediğini belirleme sürecinde ortaya çıkmaktadır. join_fonksiyonu yerel değişkenleri ve borç ilişkisi grafiğini güncellemek için kullanılır. Fonksiyon parametre uzunluğu ile yerel değişken uzunluğu 256'yı aştığında, local değişkenler u8 türünde olduğu için locals üzerinde dolaşırken taşma meydana gelecektir.
Move'un locals sayısını kontrol eden bir süreci olmasına rağmen, check bounds modülünde yalnızca locals kontrol edilmiştir ve parametre length dahil edilmemiştir. Geliştiricilerin, parametreler ve yerel değerlerin toplamını kontrol etmeleri gerektiğinin farkında oldukları görünmektedir, ancak kod aslında yalnızca yerel değişkenlerin sayısını kontrol etmiştir.
Tam Sayı Taşmasından DoS Saldırısına
Ana döngü, kod bloğunu tarayacak ve execute_block fonksiyonunu çağıracak, ardından önceki ve sonraki state'i birleştirecektir. Kodda döngü bulunduğunda, kod bloğunun başına geri dönecek ve tekrar çalıştıracaktır.
Eğer bir döngü kod bloğu oluşturup taşmayı kullanarak bloğun durumunu değiştirir ve yeni locals haritasının öncekinden farklı olmasını sağlarsak, execute_block'u tekrar çalıştırırken, temel bloktaki talimat dizisi yeni locals haritasına erişecektir. Bu durumda, eğer talimatların erişmesi gereken indeks yeni haritada yoksa, DoS'a neden olacaktır.
reference safety modülünde, MoveLoc/CopyLoc/FreeRef opcode'ları bu hedefe ulaşabilir. copy_loc fonksiyonu örneğiyle, yerel değeri LocalIndex üzerinden almaya çalışır, eğer LocalIndex mevcut değilse panic'e neden olur ve bu da tüm düğümün çökmesine yol açar.
PoC Gösterimi
Koşulsuz dal talimatları içeren bir temel blok oluşturabiliriz ve bunu execute_block ve join işlevlerini birden fazla kez çağıracak şekilde yapılandırabiliriz. Uygun parametreler ve yerel değişken sayısı ayarlanarak, ilk çalıştırmadan sonra yeni locals haritasının uzunluğu 8'e düşürülebilir.
İkinci kez çalıştırıldığında, var olmayan bir ofset erişimi panik oluşturacak ve böylece DoS'u tetikleyecektir.
Özet
Bu güvenlik açığı, sıkı statik doğrulama sürecinden geçmiş olsa bile Move dilinin güvenlik riskleri barındırdığını göstermektedir. Taşma açığı, sınır denetimlerini aşabilir ve kod denetiminin önemini vurgulamaktadır.
Move dilinin güvenlik araştırmalarında lider olarak, dil tasarımcılarının Move çalışma zamanında daha fazla kontrol kodu eklemelerini öneriyoruz, böylece beklenmedik durumların önüne geçilebilir. Şu anda Move, güvenlik kontrollerini esas olarak doğrulama aşamasında gerçekleştiriyor, ancak çalışma aşamasında yeterli güvenlik güçlendirmesi yok, bu da daha ciddi sorunlara yol açabilir.
Move dilinde başka bir güvenlik açığı daha bulduk, bunu ilerleyen günlerde sizinle paylaşacağız.
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
Move dilindeki yeni tam sayı taşma açığı analizi: Referans güvenliğinden DoS saldırısına
Move dili için bir başka yüksek riskli güvenlik açığı derinlik analizi
Daha önce Aptos Moveevm'de ciddi bir güvenlik açığı keşfetmiştik, derinlemesine araştırmalar sonucunda yeni bir tamsayı taşma açığı daha bulduk. Bu seferki açığın tetiklenme süreci daha ilginç, aşağıda bu açığı derinlemesine analiz edeceğiz ve aynı zamanda bazı Move diline dair arka plan bilgilerini tanıtacağız. Bu makalenin açıklamaları sayesinde, Move dili hakkında daha derin bir anlayışa sahip olacağınıza inanıyoruz.
Herkesin bildiği gibi, Move dili byte kodunu çalıştırmadan önce kod birimlerini doğrular. Doğrulama süreci 4 adıma ayrılmıştır ve bu açık reference_safety adımında ortaya çıkmıştır.
reference_safety modülü, işlem nesnesinin referans güvenliğini doğrulamak için kullanılan transfer fonksiyonlarını tanımlar. Kontrolleri, asılı referansların olmadığını doğrulamak, değişken referanslara erişimin güvenli olup olmadığını kontrol etmek ve global depolama referanslarına erişimin güvenli olup olmadığını kontrol etmek gibi unsurları içerir.
Güvenlik doğrulama çağrısının giriş fonksiyonu analyze_function'u çağıracaktır. analyze_function içinde, fonksiyon her bir temel bloğu doğrulayacaktır. Temel blok, giriş ve çıkış dışında hiçbir dal komutu içermeyen kod dizisidir.
Move dili, bayt kodunu dolaşarak, tüm dal talimatlarını ve döngü talimatı dizilerini bulup temel blokları belirler. Tipik bir Move IR kodu temel blok örneği, BrTrue, Branch ve Ret talimatlarıyla belirlenen 3 temel blok içerebilir.
Move'daki referans güvenliği
Rust dilinin felsefesinden faydalanarak, Move iki tür referansı destekler: değiştirilemez referans ( ve değiştirilebilir referans )&mut (. Değiştirilemez referanslar, yapıdan veri okumak için kullanılırken, değiştirilebilir referanslar verileri değiştirmek için kullanılır. Referans türlerinin mantıklı kullanımı, güvenliği korumaya ve okuma modülünü tanımlamaya yardımcı olur.
Move'in referans güvenliği modülü, fonksiyonları birim olarak alarak, fonksiyon içindeki temel blokların bayt kodu talimatlarını tarar ve tüm referans işlemlerinin yasallığını doğrular. Doğrulama süreci esas olarak AbstractState yapısını içerir; bu yapı, fonksiyon içindeki referansların güvenliğini sağlamak için borrow graph ve locals içerir.
Doğrulama süreci, temel blokların öncesi ve sonrası durumunu karşılaştıracak ve sonuçları blok durumunu güncellemek için birleştirecek, aynı zamanda bu bloğun son koşullarını sonraki bloklara yayacaktır. Bu süreç, V8 turbofan'daki Sea of Nodes fikrine benzer.
Ana döngü blok kodunu çalıştıracak ve ardından pre state ile post state'i birleştirmeye çalışacaktır. Eğer durum değişirse ve mevcut blok kendisine yönlendiren bir geri kenar ) varsa, bu bir döngü olduğunu gösterir. O zaman döngü başına geri dönecek ve bu temel bloğu yürütmeye devam edecektir, ta ki post state pre state'e eşit olana veya bir hata nedeniyle durana kadar.
Açık Analizi
Açık, join sonucunun değişip değişmediğini belirleme sürecinde ortaya çıkmaktadır. join_fonksiyonu yerel değişkenleri ve borç ilişkisi grafiğini güncellemek için kullanılır. Fonksiyon parametre uzunluğu ile yerel değişken uzunluğu 256'yı aştığında, local değişkenler u8 türünde olduğu için locals üzerinde dolaşırken taşma meydana gelecektir.
Move'un locals sayısını kontrol eden bir süreci olmasına rağmen, check bounds modülünde yalnızca locals kontrol edilmiştir ve parametre length dahil edilmemiştir. Geliştiricilerin, parametreler ve yerel değerlerin toplamını kontrol etmeleri gerektiğinin farkında oldukları görünmektedir, ancak kod aslında yalnızca yerel değişkenlerin sayısını kontrol etmiştir.
Tam Sayı Taşmasından DoS Saldırısına
Ana döngü, kod bloğunu tarayacak ve execute_block fonksiyonunu çağıracak, ardından önceki ve sonraki state'i birleştirecektir. Kodda döngü bulunduğunda, kod bloğunun başına geri dönecek ve tekrar çalıştıracaktır.
Eğer bir döngü kod bloğu oluşturup taşmayı kullanarak bloğun durumunu değiştirir ve yeni locals haritasının öncekinden farklı olmasını sağlarsak, execute_block'u tekrar çalıştırırken, temel bloktaki talimat dizisi yeni locals haritasına erişecektir. Bu durumda, eğer talimatların erişmesi gereken indeks yeni haritada yoksa, DoS'a neden olacaktır.
reference safety modülünde, MoveLoc/CopyLoc/FreeRef opcode'ları bu hedefe ulaşabilir. copy_loc fonksiyonu örneğiyle, yerel değeri LocalIndex üzerinden almaya çalışır, eğer LocalIndex mevcut değilse panic'e neden olur ve bu da tüm düğümün çökmesine yol açar.
PoC Gösterimi
Koşulsuz dal talimatları içeren bir temel blok oluşturabiliriz ve bunu execute_block ve join işlevlerini birden fazla kez çağıracak şekilde yapılandırabiliriz. Uygun parametreler ve yerel değişken sayısı ayarlanarak, ilk çalıştırmadan sonra yeni locals haritasının uzunluğu 8'e düşürülebilir.
İkinci kez çalıştırıldığında, var olmayan bir ofset erişimi panik oluşturacak ve böylece DoS'u tetikleyecektir.
Özet
Bu güvenlik açığı, sıkı statik doğrulama sürecinden geçmiş olsa bile Move dilinin güvenlik riskleri barındırdığını göstermektedir. Taşma açığı, sınır denetimlerini aşabilir ve kod denetiminin önemini vurgulamaktadır.
Move dilinin güvenlik araştırmalarında lider olarak, dil tasarımcılarının Move çalışma zamanında daha fazla kontrol kodu eklemelerini öneriyoruz, böylece beklenmedik durumların önüne geçilebilir. Şu anda Move, güvenlik kontrollerini esas olarak doğrulama aşamasında gerçekleştiriyor, ancak çalışma aşamasında yeterli güvenlik güçlendirmesi yok, bu da daha ciddi sorunlara yol açabilir.
Move dilinde başka bir güvenlik açığı daha bulduk, bunu ilerleyen günlerde sizinle paylaşacağız.