本次搭建OWASP靶机中自带的DWVA靶机对命令注入执行
Simple级别
源代码查看
<?php
if( isset( $_POST[ 'submit' ] ) ) {
$target = $_REQUEST[ 'ip' ];
// Determine OS and execute the ping command.
if (stristr(php_uname('s'), 'Windows NT')) {
$cmd = shell_exec( 'ping ' . $target );
echo '<pre>'.$cmd.'</pre>';
} else {
$cmd = shell_exec( 'ping -c 3 ' . $target );
echo '<pre>'.$cmd.'</pre>';
}
}
?>
关键函数
php_uname(mode) 函数:
mode内容如下:
'a':此为默认。包含序列 "s n r v m" 里的所有模式。
's':操作系统名称。例如: FreeBSD。
'n':主机名。例如: localhost.example.com。
'r':版本名称,例如: 5.1.2-RELEASE。
'v':版本信息。操作系统之间有很大的不同。
'm':机器类型。例如:i386。
shell_exec() 函数:
通过shell执行命令并以字符串的形式返回完整的输出
代码审计:
通过关键函数结合源代码,可以看到原意是通过ping命令和用户输入的信息进行拼接调用shell_exec()函数来执行shell命令,最后回显结果。由于此处只是进行简单凭借,所以通过构造特殊输入内容,可以利用命令注入漏洞来进行执行。
命令注入
核心思想是,通过执行完第一个command后,在执行恶意拼接的command
主要使用的命令拼接符号有 | || & &&
拼接符 | 使用方法 | 功能 | 适用系统 |
---|---|---|---|
| | command1 | command2 | 只显示Command2结果 | W/L |
|| | command1 || command2 | 显示command1和command2结果,Command1不影响2 | W/L |
& | command1 & command2 | 显示command1和command2结果,Command1不影响2 | W |
&& | command1 && command2 | 显示command1和command2结果,Command1必须正确 | W/L |
; | command1 ; command2 | 显示command1和command2结果,Command1不影响2 | L |
Simple测试
| 符号测试|| 符号测试,Command1正确
|| 符号测试,Command1错误
&& 符号测试,Command1正确
&& 符号测试,Command1错误
; 符号测试
Medium级别
源代码查看
<?php
if( isset( $_POST[ 'submit' ] ) ) {
$target = $_REQUEST[ 'ip' ];
$substitutions = array(
'&&' => '',
';' => '',
);
// Determine OS and execute the ping command.
if (stristr(php_uname('s'), 'Windows NT')) {
$cmd = shell_exec( 'ping ' . $target );
echo '<pre>'.$cmd.'</pre>';
} else {
$cmd = shell_exec( 'ping -c 3 ' . $target );
echo '<pre>'.$cmd.'</pre>';
}
}
?>
代码分析
相对于Simple的源代码,此处进行了关键性的黑名单替换,对&&与;进行了过滤,所以可以通过采用未过滤连接符( | 与 || )进行测试。
当然可以尝试继续利用黑名单的&&符号,可以进行绕过操作,为了更好理解,可以添加代码,查看效果。代码添加部分如下
回显过滤后效果
根据最后黑名单替换结果变为' '的思想,可以输入
&;&
进行绕过,由于;进入了黑名单,而&与第二个&和黑名单不匹配所以,可以进行绕过。运行效果如下
成功利用命令注入漏洞
经过测试可进行绕过的payload有
&a&
;&-&
;&+&
;&_&
;对于这些payload,刚开始不是很理解为什么可以执行,通过在系统呢测试,可以发现,本质上是将中间的符号当做命令执行了
&uname&测试
High级别
源代码查看
High等级代码代码分析
相对于Simple和Medium的源代码,对输入内容进行严格的预处理,通过点.将Ip地址分开,将每部分进行判断是否是数字。
关键函数
stripslashes():删除反斜杠
反函数:addslashes()函数添加的反斜杠
explode():将字符串分割后打散为数组
is_numeric():函数用于检测变量是否为数字或数字字符串
此函数具有漏洞,常见于CTF中获取flag时进行与特定值比较
目前自己未发现有好的绕过方法,详细可以参考资料一栏
思维扩展
可以根据目前High级别的源码,可进行稍作修改,变为正则表达式匹配,自己尝试写出的简单WAF如下:
[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}
参考资料
CSDN:PHP is_numeric()函数安全漏洞
51CTO:PHP 函数漏洞原理解析
实战练习
可参考文章
RCE-命令注入
网友评论