当应用需要调用一些外部程序去处理的情况下,就会用到一些执行系统命令的函数,这些函数将字符串当做参数传递给 shell 来当做系统命令来执行,若用户可以控制参数,就有可能通过 OS 命令注入来执行任意命令。
以下 payload 均在 Ubuntu 的 bash 实际测试过
简介
“命令注入” 是一种通过存在漏洞的应用程序向主机操作系统执行任意命令。当应用程序对用户提供的数据(表单,cookie,http 头)不进行检测,直接传递给系统 shell,那么就有可能存在命令注入。在这种攻击中,攻击者提供的操作系统命令通常以易受攻击的应用程序的特权执行。主要原因是输入验证不足导致命令注入攻击。
需要注意的是,OS 命令注入导致命令执行,和代码执行是不同的,代码执行的例子:<?php assert($_POST['a']);?>
,当a=phpinfo()
的时候就会执行phpinfo
。最后,任意代码执行会导致任意命令执行。
执行系统命令
编程语言一般都会提供内置的函数来执行系统命令,例如 PHP 的 system()
。不同语言与 shell 之间的调用大同小异,本文内容主要以 PHP 为例。
应对限制
限制命令分隔符
常规的是命令分隔符 ;
,但是还有很多可以代替它的:
;
:常规分隔符,不论;
前面的命令执行成功与否都会执行后面的命令。&&
:&&
左边的命令成功执行后,&& 右边的命令才能够被执行。||
:如果||
左边的命令执行失败了就执行||
右边的命令。&
:&
放在启动参数后面表示设置此进程为后台进程,这里可以巧妙地作为命令分隔符:ls&whoami
实际上相当于ls &; whoami
,即将ls
放到后台运行,结束后再运行whoami
。|
:管道符左边命令的输出作为管道符右边命令的输入。所以左边的输出并不显示。%0a
:url 编码的换行符%0d
:url 编码的回车符%00
:url 编码的 NULL,高版本的 PHP 会报 Warning:
Warning: system(): NULL byte detected. Possible attack in /var/www/html/index.php on line 3
限制空格或者特殊字符
能替换空格的也有很多:
<
:输入重定向,后面需要接目录或者文件名,例如ls<.>,所以不是所有的命令都可以使用它作为空格替代符,例如
ping
:
bash-3.2$ pingbash: baidu.com: No such file or directory
<>
:打开一个文件作为输入与输出使用。所以它比<
的限制更严格,后面必须是文件,连目录都不行:
bash-3.2$ cat<>key
Macr0phag3
bash-3.2$ ls<>./
bash: ./: Is a directory
%09
:url 编码的制表符的。%0a
:url 编码的换行符。${IFS}
、$IFS
:首先,IFS
是一个系统变量,内置的分隔符,查看默认的IFS
:
bash-3.2$ set |grep IFS
IFS=$' \t\n'
所以它可以用来替代空格。那么 ${IFS}
与$IFS
有什么区别呢?其实是没有区别的,${}
的作用仅仅是起到了精确界定变量名称的作用