PHP代码审计-某cms逻辑漏洞导致getshell
- 技术教程
- 2023-04-27
- 20热度
- 0评论
前言 如果存在exec进行拼接的漏洞,该如何绕过 <mark>一黑俩匹配 </mark>?当前如果是拼接和编码这种手法就不说了,现在在看的师傅您是审计大牛的话,这文章可以忽略不看。黑名单...
前言
======
如果存在exec进行拼接的漏洞,该如何绕过 一黑俩匹配 ?
当前如果是拼接和编码这种手法就不说了,现在在看的师傅您是审计大牛的话,这文章可以忽略不看。
黑名单
$_GET[ $_POST[ $_REQUEST[ $_COOKIE[ $_SESSION[file_put_contentsfile_get_contentsfwritephpinfobase64`shell_exec eval assertsystemexecpassthrupcntl_execpopenproc_openprint_r print urldecodechr include request __FILE__ __DIR__ copycall_user_preg_replacearray_maparray_reversearray_filtergetallheadersget_headersdecode_stringhtmlspecialcharssession_idstrrevsubstrphp.info
第一个匹配:
/([w]+)([x00-x1Fx7F/*%ws]+)?(/i
第二个匹配:
这里不能有$符号,这里是重点 ,当然如果你想编码也可以,或者啥的手法都行,不过我在此之前没想到过,可以继续往下看
/{pboot:if(([^}^$]+))}([sS]*?){/pboot:if}/
正文
======
先看效果
审计流程
通过审计工具半自动筛选出漏洞点。
跟进该漏洞点文件:[小]apps/home[谦]/controll[娱]er/Parser[乐]Controlle[网]r.php
最终是通过了$matches[1][$i]进入到eval函数中。
第一个黑名单
接着往上看,这里有黑名单,如果$matches[1][$i]有黑名单就会跳出解析
这里的是社区编辑器默认加上防止转义,太多就懒得改了
// 过滤特殊字符串 if (preg_match('/(([ws.]+))|($_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)|(strrev)|(substr)|(php.info)/i', $matches[1][$i])) { $danger = true;} // 如果有危险函数,则不解析该IF if ($danger) { continue;}
黑名单分别是拦截以下内容:
$_GET[$_POST[$_REQUEST[$_COOKIE[$_SESSION[file_put_contentsfile_get_contentsfwritephpinfobase64`shell_exec eval assertsystemexecpassthrupcntl_execpopenproc_open print_r print urldecodechr include request__FILE____DIR__copycall_user_preg_replace array_map array_reverse array_filtergetallheadersget_headersdecode_stringhtmlspecialcharssession_idstrrevsubstrphp.info
这可以看出过滤了好多函数,当然既然是黑名单就有绕过的方式,这里可以是加密形式绕过,不过加密后的密文做成payload就逆向解密不了了,因为是由特殊不可见数据流存在就会导致反解密会不到原来的明文。
这里可以用file和fputs函数绕过
第一个过滤
继续往上看,看到这个if判断,这里也是将$matches[1][$i]进行过滤,保证用户输入的字符串是无危害的,简单来说就是‘括号前面不能有字母、数字字符串’。
// 带有函数的条件语句进行安全校验 if (preg_match_all('/([w]+)([x00-x1Fx7F/*%ws]+)?(/i', $matches[1][$i], $matches2)) { foreach ($matches2[1] as $value) { if (function_exists(trim($value)) && ! in_array($value, $white_fun)) { $danger = true; break;}} foreach ($matches2[2] as $value) { if (function_exists(trim($value)) && ! in_array($value, $white_fun)) { $danger = true; break;}}}
当然这里也是黑名单[内],直接/*--*/[容]绕过
4.3. 第三个过滤
这个就比较好过了就是指定的标签语法,使用这个{pboot:if(312313)}(13123){/pboot:if}
4.3.1. 注意:
这里不能有$符号,这里是重点
$pattern = '/{pboot:if(([^}^$]+))}([sS]*?){/pboot:if}/'; if (preg_match_all($pattern, $content, $matches)) {}
构建payload
由于这里不能用美元符号”$“,前面第一个过滤说过,可用file函数绕过,如下图:
通过上面file函[保]数获取的美元符号,[护]并且通过fputs[小]进行写文件,当然需[谦]要绝对路径才能读取[娱]美元符,这里就比较[乐]简单了,直接让cm[网]s报错就好了。
调用链
ParserController.php:84, apphomecontrollerParserController->parserAfter()TagController.php:47, apphomecontrollerTagController->index()IndexController.php:50, apphomecontrollerIndexController->_empty()2:2, corebasicKernel::axqjlxzuuxaapu328937ae1368b88e8bf79cb6b342866a()2:2, corebasicKernel::run()start.php:17, require()index.php:23, {main}()
访问首页就会进入到apps/home/controller/IndexController.php的_empty()方法,需要get的参数带有tag就可进入该判断
跟进到apps/h[内]ome/contr[容]oller/Tag[保]Controlle[护]r.php的ind[小]e()方法,跟进第[谦]47行并跟进到ap[娱]ps/home/c[乐]ontroller[网]/ParserCo[内]ntroller.[容]phpparser[保]After()方法[护],最后就会到84行[小]的漏洞方法中。
目前新版本未发现有该处函数
文章首发在:奇安信攻防社区
https://forum.butian.net/share/2142
黑白之道发布、转载[谦]的文章中所涉及的技[娱]术、思路和工具仅供[乐]以安全为目的的学习[网]交流使用,任何人不[内]得将其用于非法用途[容]及盈利等目的,否则[保]后果自行承担!
如侵权请私聊我们删[护]文
END
【本页内容来源于互联网或网友投稿,可用性与真实性请自行辨别】

保存图片 使用微信扫码即可成为美团圈圈达人