PHP Bytecode Koruma Mekanizmasının Güvenlik Analizi 2

Bu döküman PHP Bytecode Koruma Mekanizmasının Güvenlik Analizi ((( 1 )))’in devamı olan PHP Bytecode Koruma Mekanizmasının Güvenlik Analizi (((2))) başlığı altında yazılmıştır 1’i okumadıysanız lütfen BURAYA tıklayıp ilk dökümandan başlayınız.

Yaklaşımımız iki adımdan oluşur. Öncelikle, expressionv(ifade) ve statementları (komut) yeniden oluşturmak için tüm opcodeları tekrarlarız. Bu işlem sırasında, üçlü operatörler ve arrayler yeniden oluşturulur ve tutarlı koşullar birleştirilir. Daha sonra, PHP kaynak kodu ve atlama talimatlarıyla devam edeceğiz. Son olarak, kontrol akışını yeniden birleştirmek için yaygın olarak kullanılan atlama ve döngü yapılarının modellerini bulmaya çalışıyoruz.

Tablo 3’deki kod, PHP bayt koduna bir örnek sağlar. Burada, önce TMP:1’de saklanan ADD ifadesinin PHP sözdizimini arabelleğe alırız (op1+op2). Ardından, TMP:1 operandında $test değişkeninin atamasının çözümüyle kodun ilk satırı kurtarıldı. Daha sonra $test değişkenine bir büyüktür 500 diyerek bir kısıtlama getiriyoruz (op1>op2). Ardından, TMP: 2 işleneni 4. satırda çözülebilir. Bir sonraki satırda, echo komutunu oluşturuyoruz. Şimdilik JMP’yi görmezden geliyoruz ve dönüş statement’ın dönüşümüyle bitiriyoruz. Tüm ifade ve komutlar işlendiğinde, atlama operandlarını işleyerek paternler bulmaya başlarız. Örneğimizde, 4. satırdaki JMPZ’yi, bir if yapısı olarak 6. satırdaki aşağıdaki JMP ile aynı yere atlıyoruz.

Benzer şekilde, daha karmaşık if / else yapılarını tanıyabiliriz. Daha önce gösterildiği gibi, else bloğu olmayan tek bir if bloğu, koşulun başarısız olması durumunda yaklaşan ifadeleri atlayan koşullu bir atlama talimatı tarafından tanımlanır. Optimize edilmemiş baytkodu, if bloğunun içinde, if bloğundan sonraki komutu atlayan bir JMP komutuna sahiptir. Bu durumda ikinci atlama yürütmek için gereksiz ancak paterni tanımaya yardımcı olur. Bu JMP talimatı yaklaşan ifadeleri yerine atlayacak olursa, bu ifadeler bir elseif / else bloğuna atanır.

PHP baytkodunda, döngüler için eşsiz bir patern bulunur. Genel düzen, bir döngü kısıtı, bir JMPZNZ, bir yineleme ifadesi, bir JMP, ardından da döngü body ve son bir JMP içerir. JMPZNZ işleminde kendi operandında iki atlama yeri bulunur. İlk atlama sıfır olması durumunda, ikincisi aksi taktirde. İkinci konum, dögünün body kısmının arkasına işaret eder. JMPZNZ komutunun durumu eşleşmediğinde interpreter (yorumlayıcı) bu konuma atlar. İlk konumdaki bayt kodu, döngü body kısmının başlangıcını temsil eder. Body kısmının sonundaki JMP talimatı döngünün kısıtlamasına geri dönüyor.

Benzer şekilde, döngüler algılanabilirken. Burada, bir kısıtlamanın ardından, döngünün body kısmının arkasına işaret eden bir JMPZ talimatı gelir. Ardından, döngünün body kısmı döngü kısıtına işaret eden bir JMP talimatı ile bitmesini izler.

Daha kullanışlı olanı foreach döngülerinin tanınmasıdır. Burada, nadir opcode FE_RESET bir arrayin imlecini sıfırlamak için kullanılır ve bunu o anki arrayin öğesini getirmek bir FE_FETCH opcode izler. Ardından, döngü body kısmı bir JMP talimatı ile biter. İlk FE_opcode’ların her ikisi de ikinci operandında saklanan bir atlama konumuna sahiptir. Bu konum, döngünün body kısmındaki son JMP talimatının arkasına işaret eder ve döngü tamamlandığında erişilir. JMP talimatının kendisi FE_FETCH işlem kodunu işaret eder.

İç içe geçmiş yapıları çözmek için, algoritmamız birkaç yinelemede içe doğru bir yaklaşım kullanmaktadır. Sürekli paternleri çözülmüş olarak işaretliyoruz ve patern eşleştirme algoritmamızı yeni patern tespit edilemeyene kadar tekrar ediyoruz. Bu şekilde, iç içe geçmiş bir yapıda, en içteki patern önce çözülür ve bunu takiben bir sonraki yinelemede dış patern tanımlanır.

PHP tanıma işlemini kolaylaştıran yedek opcode eklediğinden beri, patern eşleştirme yaklaşımımız, optimize edilmemiş bayt kodunda çok iyi çalışır. Maalesef bu paternler baytkod optimizasyonu etkinleştirildiğinde değişebilir. Burada, gereksiz işlemler kaldırılır, yapılar sıkıştırılır ve atlama hedefleri önceden çözülür. Bu, yapıları bulma ve geri derlemeyi zorlaştırır. Bu kısıtlamaların üstesinden gelmek için, daha ayrıntılı olarak hazırlanmış bir geri derleme tasarımı gelecekte uygulanabilir.

Komutları ve ifadeleri kaynak koda dönüştürme yaklaşımımızın parçaları, diğer kayıt tabanlı sanal makineler için de uygulanabilir. Ekleme veya birleştirme gibi basit opcode’lar diğer dillerle kıyaslanabilse de, arraylere erişim gibi karmaşık opcode’lar daha çok PHP’ye özgüdür. Java, Python veya Perl’de kullanıldığı gibi yığın tabanlı baytkodu için, işlenenlerin önce yığını çözülmesi gerekir. Kod yapılarının değerlendirilmesi için patern eşleme yaklaşımımız, PHP bayt kodunda bulunan eserler üzerine kuruludur ve dolayısıyla doğrudan diğer dillere uygulanmaz.

Değerlendirme

Geri derleyiciyi iki aşamalı olarak değerlendiriyoruz. İlk olarak, bilinen bir kaynak kod setini kodlayarak ve geri derlenmiş kodu orijinal haliyle karşılaştırarak kaynak kod derleme sonuçlarımızı nicelleştirmeye çalışıyoruz. Sonra, Geri derleyiciyi 10 korumalı aktif çalışan uygulamalara karşı test edip bilinmeyen kaynak kodunu kurtarmaya çalışıyoruz.

Kaynak Kodu Yeniden Yapılanma

Geri derlenmiş PHP kodunun kalitesini ölçmek zordur ve bildiğimiz kadarıyla PHP için hiçbir kod benzerliği algoritması mevcut değildir. Kodun anlam sembolü geri derlentikten sonra da kalırken, syntaxler PHP native ve kodlayıcıların ek bayt kodu optimizasyonu nedeniyle değişir. Kavramsal uygulama belgelerimizin sınırlamaları nedeniyle (bkz. Bölüm 5.3), prototipimiz her zaman sözdizimsel olarak (syntax olarak) doğru kodu üretmez ve geri derlenmiş bir uygulamanın başarılı birim testlerinin karşılaştırılması geçerli değildir. Dolayısıyla, PHP belirteçlerine (tokenlara) dayalı temel bir metrik geliştirdik. Tüm belirteçleri yedi gruptan birine sınıfladık:

DATA (VERİ): literal, sabitler ve değişkenlerin simgeleri (tokenları) (T_VARIABLE)

EQUAL (EŞİTLİK): atama operatörlerinin simgeleri (T_PLUS_EQUAL gibi)

COMP (KARŞILAŞTIRMA): karşılaştırma operatörlerinin simgeleri (T_EQUAL ve T_ISSET gibi)

CAST (ÇEVİRİM): çevirim tipinin simgeleri (T_INT_CAST ve T_STRING_CAST gibi)

INCL (KOMUT İÇEREN): komut içeren simgeler (T_INCLUDE and T_ EQUIRE gibi)

PROC (USUL): usul kodunun simgeleri (T_FUNCTION and T_NEW gibi)

FLOW (AKIŞ): atlama ve döngü ifadelerinin simgeleri (T_IF and T_WHILE gibi)

Bu kategorilerden birine girmeyen tokenlar yok sayıldı. Ayrıca, kapsüllenmiş değişkenleri ve sabitleri, açıklamaları, boşlukları, mantıksal operatörleri ve satır içi HTML’yi gözardı ettik. Daha sonra, en popüler üç PHP projesinin Wordpress, Drupal ve Joomla’yı varsayılan optimizasyon seviyesindeki en karmaşık enkoder ionCube ile derledik. Daha sonra korumalı kodu tekrar derlemek için prototipimizi kullandık. PHP’nin yerleşik tokenizer’ı, orijinalin ve kurtarılan kaynak kodun tüm PHP dosyalarındaki belirteçlerin sayısını toplamak için kullandı ve her bir simge için bireysel başarı oranını hesapladık. Tablo 4’te, her bir gruptaki simge popülerliği tarafından ortalaması alınan her simge kategorisinin ortalama benzerliğini listeledik. Optimizasyona dahil olmayan tokenlar için çok benzer bir miktar gözlemledik. Beklendiği gibi, en iyi duruma getirilmiş talimatlar veya döngüler (AKIM) için tokenların sayısı da değişiyor. Bulgularımıza dayanarak% 96’lık başarılı bir yeniden yapılandırma oranını tahmin ediyoruz.

DECODER PHP

Tablo 4. Üç derlenen / geri derlenen uygulama için ortalama token benzerliği (% cinsinden)

Korumalı Gerçek Dünya (Real-World) Uygulamaları

Gerçek dünyadaki uygulamalarda korunan kodu denetlemek için popüler 10 adet enkoded PHP uygulamasını seçtik (Tablo 5’de sunulmuştur). Enkoder başına değerlendirilen yazılım sayısı enkoder popülerliğine göre seçildi. Toplamda, 3 942 korumalı PHP dosyasında 1 milyondan fazla kod satırı (RELOC) kurtarabildik. En iyileştirilmiş yapıları çözerken hatalara neden olan bazı uygulamalar için, baytkodu optimizasyonu etkinleştirildi. Bu hatalar, optimize edilmiş koda özeldir ve genelleştirilemez. Burada, prototip uygulamalarımız daha kesin bir yeniden yapılandırma için iyileştirme gerektiriyor. Bununla birlikte, iç içe kod yerleştirme hataları, Ör. Süslü parantezlerin yanlış yerleştirilmesi gibi hatalar, kurtarılan kaynak kodunun tam olarak anlaşılmasını engellemez ve kriptografik anahtarlar gibi hassas bilgileri almak veya güvenlik açıklarını tespit etmek için de engellemez. Aşağıda bulgularımızı sunuyoruz. Büyük korpus nedeniyle, kodun yalnızca bir kısmı analiz edilebilir.

PHP şifreleme

Tablo 5. Bir kodlayıcı uygulayan seçili gerçek dünya uygulamaları için Korpus.

 

Lisans Sistemleri: Tüm analiz edilen 10 uygulamada, koruma öncelikle bir lisans sistemini gizlemek için kullanılır. Uygulamanın kullanımını belirli bir zamana (7), kullanıcı sayısına (5), alan adı veya MAC adresine (4), yazılım sürümüne (3) veya bir demo sürümünün yazılım özelliklerini sınırlayabilir (5). Korunan kaynakları derleyerek, kullanılan keyleri ve algoritmaları ortaya çıkarabiliriz. Örneğin, lisans verilerini doğrulamak veya şifrelerini çözmek için kullanılan PHP-Cart (MD5 salt), HelpSpot (RC4), gSales (SHA1 salt) ve Mailborder (AES 128bit) statik sırrını kurtarabiliriz. NagiosFusion’da, kurulumun kısıtlamalarını lisans anahtarından çıkarmak için kullanılan özel bir şifreleme algoritması keşfettik. Bu hassas kaynakların geri derlenmesi yalnızca geçerli bir çalışma zamanı ortamını ve lisansını taklit etmekle kalmaz, aynı zamanda bu kontrolleri tamamen kaldırır.

Güvenlik Açığı: Dahası orijinal korunan uygulamalara karşı teyit edilebilecek, geri derlenmiş kaynak kodlarında kritik güvenlik açıkları tespit ettik. Örneğin, HelpSpot’ta ve komut kılıfında sunucudan herhangi bir dosyayı uzaktan almaya izin veren çoklu güvenlik açıklarını ve hassas verileri veritabanından çıkarmaya izin veren HelpSpot, xtCommerce ve gSales’te SQL enjeksiyon zayıflıkları tespit ettik. Bu güvenlik açıklarının kullanılamayan kaynak kodu yüzünden daha önce fark edilmediğini düşünüyoruz. Bunun satıcı için mi yoksa saldırganlar için daha yararlı olup olmadığı tartışmalıdır. Muhtemelen, kaynak kodu olmadan bazı zayıflıklar da tespit edilebilir. Bununla birlikte, kara kutu senaryosunda bazı güvenlik açıklarının kullanılması zordur. Örneğin, xtCommerce, PHP-Cart ve HelpSpot’ta Mailborder veya PHP nesne ekleme güvenlik açıklarında, ikinci bir sipariş dosyası eklenebilecek bir güvenlik açığı bulundu. Açıkçası, bir satıcı, güvenlik sorunlarının fark edilmeden kaldığını varsayarak, kaynak kod koruyucularına güvenmemelidir. Tanımlanan tüm sorunları ilgili satıcıya sorumlu bir şekilde rapor ettik.

Pingbackler ve İzinsiz Erişim Geçişleri: Güvenlik açıklarının yanında korumalı uygulamaların şüpheli işlevleri aradık. Oldukça zararsız pingback özelliklerini bulduk, örneğin xtCommerce’de, yükleme ortamı ve lisans hakkında bir SOAP tabanlı web hizmetine bilgi gönderiyor. Bu güncellemeleri kontrol etmek için kullanılabilirken, aynı zamanda aktif kurulumları gözlemlemek için de iyi bir yoldur. Daha ciddi olanı, xtCommerce, kullanıcının PayPal API kimlik bilgilerini HTTP yoluyla sunucusuna düz metin olarak gönderiyor olmasıdır. Precorio, ionCube lisansının sunucuyla eşleşmediği veya süresinin dolması durumunda, uygulamanın sunucusu ve sahibi hakkında bilgi toplayarak CURL isteği yoluyla Precurio web sitesine göndeririyor. Bununla birlikte, Precurio’da da bir güvenlik açığı da tespit ettik. Aşağıdaki üç kod satırı, istek yolunun bir dosya olup olmadığını ve bu durumda içeriğinin çıktı olup olmadığını belirler. Böylece, örneğin sunucudan /index.php/index.php URL’sini istemek suretiyle, dizin dosyasının PHP kaynak kodu sızdırılır.

$filename = $root . ‘/public/’ . $_SERVER[‘PATH_INFO’];

if ( is_file($filename) )

echo file_get_contents($filename);

Üstelik, kod, kullanıcı dosyaları ve lisans dosyası da dahil olmak üzere Precurio’nun web dizininden herhangi bir dosyayı almaya izin verir. Ayrıca, Precorio’daki ErrorController’ın bir downloadAction’ı gerçekleştirdiğini tespit ettik. Böylece, URL / hata / indirme, Precurio ekibinin yanı sıra diğer uzak kullanıcılara Precurio yüklemesinin ayrıntılı yığın izlerini ve istisnalarını sızdıran günlük dosyasını indirmesini sağlar. Precurio’ya her iki konuda da bilgi verdik.

İlişkili İşler

Tersine mühendislik maliyetlerini artırmak için yazılım sistemlerinin karmaşıklığı pratikte kullanılır. Örneğin dijital haklar yönetimi sistemleri veya IP koruması bağlamında. Sonuç olarak, son yıllarda pek çok farklı türde şaşırtma tekniği geliştirildi ve çoğunun ikili yürütülebilir dosyaları üzerinde duruldu. Sözde çalıştırılabilir paketleyiciler, belirli bir ikili korumak için farklı şaşırtma ve şifreleme stratejileri uyguluyorlar. Şaşırtma, kötü niyetli yazılım örneklerinin analizini engellemek için düşmanlar tarafından da yaygın olarak kullanılmaktadır. Bu tür taktikleri önlemek için otomatik ayrıştırma için birkaç yöntem geliştirildi ve devam etmekte olan bir silahlanma yarışını izliyoruz.

Benzer şifreleme stratejileri PHP kaynak kodunu korumak için kullanılır ve bu tür stratejileri uygulamak için ticari araçlar vardır. Bildiğimiz kadarıyla PHP’nin şaşırtmaca üzerine hiçbir akademik çalışma yoktur. Çalışmalarımız Esser tarafından yapılan ve PHP kaynak kodu şifrelemesine genel bir bakış sağlayan ve kaynak kodunun nasıl kurtulabileceği konusunda fikir veren bir konuyla yakından alakalı. Saher, ionCube için bazı ters mühendislik detaylarını bir konuşmada sundu. En popüler 3 PHP kod koruma ürününe ters mühendislik yaptık ve geri derleyici bir yaklaşımla birlikte dahili bileşenleri hakkında ayrıntılı bilgi verdik. Statik ve dinamik kod analiz teknikleri güvenlik açıklarını tespit edebilir ve önemli bir araştırma konusudur. Korunan PHP koduna nasıl erişileceğini ve bir analizin nasıl yapılabileceğini göstererek bu alanı tamamlıyoruz. Tersine mühendislik ve ikili enstrümantasyon teknikleri ile karmaşıklaştırma / koruma mekanizmaları kırıldı ve bu tür saldırıların PHP’nin karmaşıklaştırma araçlarına karşı da geçerli olduğunu gösterdik.

Sonuç

Bu yazıda, PHP kaynak kodu için mevcut IP koruma araçlarının sağladığı koruma düzeyini değerlendirdik ve belgeledik. En popüler üç enkoderin iç kısımlarını inceledik ve bir kanıt konsepti uygulamasıyla paylaşılan bir zayıflığa karşı bir saldırı gösterdik. Sonuç olarak, geri derleyici programımız, bir saldırganın lisans sistemlerini çatlatmasına ve önceden bilinmeyen zayıf noktaları ve arka kapıyı tanımasına imkan verecek şekilde korunan PHP kodunun% 96’sını kurtarabildiğini gösteriyordu. Bu sebeple şu anda mevcut olan enkoder ürünlerinin fikri mülkiyet koruması için uygun bir çözüm olmadığını ve PHP kaynak kodunu daha iyi korumak için daha ayrıntılı karmaşıklaştırma yaklaşımları gerektiğini iddia ediyoruz.

Etik Hususlar: Çalışmalarımızın, telif hakkı ihlali veya sunucu uzlaşması gibi yasadışı faaliyetler gerçekleştirme niyetiyle motive olmadığının ve diğerleri için bu faaliyetlerin kolaylaştırılmasının mümkün olmadığını açıklamak isteriz. Bu nedenle, geri derleyici aracımızı yayınlamıyoruz ve tespit edilen tüm güvenlik açıklarını satıcılara sorumlu bir şekilde rapor ettik. Üstelik, analiz edilen ürünlerin sadece temel görüşlerini sunduk ve sunulan keyler ve sabitler muhtemelen değişime tabi tutulurken belli ayrıntılar bilerek kaldırıldı. En son kodlayıcılara yönelik saldırılarımızı çoğaltmak için bir saldırganın hala yüksek bir ters mühendislik ve çaba harcadığını düşünüyoruz. Bunun yerine, araştırmamızın saldırılardan zarar görmeyen daha iyi enkoderler geliştirmemize ve sanatın gelişimine katkıda bulunmasını umuyoruz.

 

Yorum yapın