Nisan ayında, güvenlik açığı tespit sistemimiz Solana'nın rBPF'sinde (yani, tüm Solana dApp'lerinin üzerinde çalıştığı sanal makine: https://github.com/solana-labs/rbpf) bir sorun keşfetti. Dikkatli bir incelemenin ardından, bunun bir sözleşmenin yanlış yürütme yoluna yol açabilecek bir güvenlik açığı olduğunu tespit ettik. Hatayı Solana güvenlik ekibine bildirdik ve ekip, güvenlik açığını derhal onaylayıp düzeltti. Ayrıca ekibimize 800.000 USD değerinde SoL token ödülü verdiler.

Güvenlik açığı, rBPF'nin daha yeni sürümlerinde (0.2.26 ile 0.2.27) mevcuttur. Sorunu bildirdiğimizde, ana ağda kullanılan doğrulayıcılar etkilenen sürüm(ler)e yükseltilmemişti. Sistemimiz, etkilenen sürüm birleştirilmeden önce sorunu tespit etti ve bu sayede ana ağın doğrulayıcısı bu güvenlik açığından etkilenmedi.
Bu güvenlik açığının ayrıntılarını aşağıda açıklıyoruz.
1. eBPF ve rBPF
eBPF (Genişletilmiş Berkeley Paket Filtresi), başlangıçta çekirdekteki paketleri filtrelemek amacıyla geliştirilmiştir. eBPF'nin güvenliği, verimliliği ve ölçeklenebilirliği sayesinde artık ağ iletişimi, izleme, profil oluşturma gibi çeşitli alanlarda kullanılmaktadır. eBPF'nin zengin yetenekleri göz önünde bulundurularak Solana, akıllı sözleşme için yürütme motoru olarak eBPF'yi kullanmaktadır. Solana üzerinde dApp geliştirmek için geliştiriciler akıllı sözleşmelerini Rust ile geliştirir ve sözleşmeyi eBPF bayt koduna derler.
Solana, derlenmiş BPF bayt kodunu çalıştırmak için Rust ile yazılmış bir sanal makine olan rBPF'yi kullanmaktadır. Ancak önerilen sanal makinenin (yani rBPF'nin) sağlam, güvenli ve doğru olup olmadığı bilinmemektedir. rBPF içinde güvenlik sorunları mevcutsa, rBPF içeren tüm doğrulayıcılar etkilenebilir ve bu durum tüm Solana ağında büyük kayıplara (örn. Fon Kaybı) yol açabilir.
2. Temel Neden
rBPF'nin uygulama hatalarını otomatik olarak tespit edebilen ve rBPF kodunu periyodik olarak tarayan bir araç geliştirdik. Tarama sürecinde rBPF'de (sürüm 0.2.26) ciddi bir sorun tespit edildi; bu sorun, bir sözleşmenin yanlış yürütme yoluna yol açabilir.
Özellikle, sdiv talimatı işaretli bölme talimatı olarak kullanılmakta olup rbpf 0.2.26'da varsayılan olarak etkin bir özellik olarak tanıtılmıştır. sdiv, hem 32 bit (yani sdiv32) hem de 64 bit (sdiv64) işlenenler için bölme işlemini desteklemektedir. sdiv32 talimatında hesaplama sonucu, 64 bit olan bpf kaydedicisinde saklanır. Ancak sdiv32'den sonraki talimatlar hesaplama sonucunu 64 bit olarak okursa sonuç farklılaşabilir. Bunun nedeni, rBPF'nin JIT derlemesi sırasında sdiv32'nin hesaplama sonucunu 64 bit'teki doğru değere genişletmemesidir.

Örneğin, sdiv32 ile pozitif bir sayı (yani 12) negatif bir sayıya (yani -4) bölündüğünde, doğru sonuç hem 32 bit hem de 64 bit'te -3 olmalıdır. Aşağıda bir örnek kod verilmiştir.

Hem JIT hem de Yorumlanan modlarda çalıştırıp izledikten sonra, ikisi arasındaki farkları gözlemleyebildik:
2.1 Yorumlanan Mod
0 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000] 29: lddw r5, 0x10000000c
1 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 000000010000000C, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000] 31: sdiv32 r5, -4
2 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, FFFFFFFFFFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000] 32: jslt r5, 0, lbb_7
3 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, FFFFFFFFFFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000] 36: exit
2.2 JIT Modu
0 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000] 29: lddw r5, 0x10000000c
1 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 000000010000000C, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000] 31: sdiv32 r5, -4
2 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 00000000FFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000] 32: jslt r5, 0, lbb_7
3 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 00000000FFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000] 33: lddw r0, 0x1
4 [0000000000000001, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 00000000FFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000] 35: exit
Yorumlanan modda, r5 kaydedicisi 0xFFFFFFFFFFFFFFFD değerine (hem 32 bit hem de 64 bit modda -3) ayarlanırken, JIT modunda r5 değeri 0x00000000FFFFFFFD olarak ayarlanmaktadır. Bu durumda, 64 bitlik bir değer alan jslt talimatı için r5, pozitif bir sayı (yani 0x00000000FFFFFFFD) olarak tanınacaktır. Bunun ardından yürütme yolu tamamen yanlış olacaktır.
3. Etki
Bu hatalı uygulama, bir sözleşmenin yanlış yürütme yoluna yol açabilir ve ciddi sorunlara neden olabilir.
Örneğin, bir akıllı sözleşmedeki temel bir işlem sdiv32 talimatının sonucuna bağlıysa, bu durum yanlış yürütme sonuçlarına yol açabilir ve saldırganlar tarafından kötüye kullanılabilir.
Bu sorun https://github.com/solana-labs/rbpf/pull/283 adresinde tanıtılmış olup rBPF'nin 0.2.26 sürümünden itibaren güvenlik açığı içerdiği anlamına gelmektedir. Sorunu tespit ettik ve 28 Nisan 2022'de Solana güvenlik ekibine bildirdik. Ekip, raporumuza hızlıca yanıt vererek sdiv32 talimatı için işaret genişletme işlemi ekleyerek sorunu birkaç saat içinde düzeltti. Düzeltme https://github.com/solana-labs/rbpf/pull/310 adresindedir. Ekibimizin zamanında tespiti ve bildirimi sayesinde ana ağın doğrulayıcıları bu güvenlik açığından etkilenmedi.
Bu sorun, protokol canlılık hatası olarak sınıflandırılmış ve Solana tarafından 800.000 dolarlık hata ödülü verilmiştir.
Zaman Çizelgesi
- 2022/04/28: Sorunu Solana güvenlik ekibine bildirdik
- 2022/04/29: Güvenlik açığı düzeltildi
- 2022/05/09: CVE-2022-23066 atandı
- 2022/06/01: Hata ödülü verildi
BlockSec Hakkında
BlockSec Ekibi, blockchain ekosisteminin güvenliğine odaklanmakta ve önde gelen DeFi projeleriyle iş birliği yaparak ürünlerini güvence altına almaktadır. Ekip, hem akademik hem de endüstri alanında üst düzey güvenlik araştırmacıları ve deneyimli uzmanlar tarafından kurulmuştur. Prestijli konferanslarda birden fazla blockchain güvenlik makalesi yayımladılar, DeFi uygulamalarına yönelik çeşitli sıfır gün saldırılarını raporladılar ve yüksek etkili güvenlik olaylarının ayrıntılı analiz raporlarını yayımladılar.
Twitter: [BlockSecTeam]
Medium: https://blocksecteam.medium.com
Website: https://www.blocksec.com



