命令注入漏洞
漏洞成因
应用有时需要调用一些执行系统命令的函数,如PHP中的system、exec、shell_exec、 passthru、popen、proc_popen等,当用户能控制这些函数中的参数时,就可以将恶意系统命令。 拼接到正常命令中,从而造成命令注入攻击,这就是命令注入漏洞。
利用条件
1.应用调用执行系统命令的函数 2.将用户输入作为系统命令的参数拼接到了命令行中 3.没有对用户输入进行过滤或过滤不严
漏洞分类
1.代码层过滤不严 商业应用的一些核心代码封装在二进制文件中,在web应用中通过system函数来调用: system(“/bin/program --arg $arg”);
2.系统的漏洞造成命令注入,bash破壳漏洞(CVE-2014-6271)
3.调用的第三方组件存在代码执行漏洞,如WordPress中用来处理图片的ImageMagick组件,JAVA中的命令注入漏洞(struts2/ElasticsearchGroovy等),ThinkPHP命令注入
漏洞危害
继承Web服务程序的权限去执行系统命令或读写文件 反弹shell 控制整个网站甚至控制服务器 进一步内网渗
复现过程
我们再输入框输入www.baidu.com&ifconfig
,点击submit提交,可以看到不仅ping命令成功执行,并且后面的ifconfig命令也成功执行。(ifconfig是linux中用于显示或配置网络设备(网络接口卡)的命令,英文全称是network interfaces configuring。)
其中实验的关键代码: $target= $_REQUEST[ ‘ip’ ];
这条语句就是直接把用户输入的IP赋值给$target,没有做任何过滤,如果是用户正常输入IP那么正常执行,如果用户输入的不是IP?这里就涉及业务逻辑了,漏洞的产生就是源于程序员对于此处用户输入的信任。以至于对入用户输入没有进行任何的过滤,为命令注入攻击发生提供了条件。
接下来有一个if语句,判断条件是“stristr(php_uname(‘s’),‘Windows NT’)”,这是用来判断当前的系统是否是Windows,因为Windows和Linux下的ping命令注入参数是不同的。 再下面是将函数“shell_exec( 'ping ’ . $target )”的值赋值给变量$cmd,并输出$cmd的值,其实也就是在执行shell_exec('ping ' . $target )
函数,因而shell_exec()
函数就是这里的核心了。 shell_exec()
函数的作用就是可以在PHP中去执行[操作系统命令,因而如果不对用户输入的命令进行过滤,那么理论上就可以执行任意系统命令,也就相当于直接获得了系统级的Shell
,因而命令包含漏洞的威力相比SQL
注入要大多了。
黑名单过滤
现运用数组的方式建立了一个黑名单
$substitutions = array(‘&&’ => ‘’ , ‘;’ => ‘’,);
这行语句的意思是定义了一个数组并赋值给变量$substitutions,数组中包括2个键:&&和;,它们对应的值都是NULL。
$target =str_replace( array_keys( $substitutions ), $substitutions, `$target );
这行语句是用str_replace函数对$target变量中的字符进行替换,替换的方法是将array_keys( $substitutions )替换成$substitutions,也就是将&&和;都替换成空值。
输入www.baidu.com|ifconfig
可以看到两个命令回显,成功绕过。
high环境代码分析
登录DVWA,设置安全环境为high。进入Command Injection(命令注入漏洞实验界面)。(如若已登录,则可略去登陆步骤,直接设置安全环境) 鼠标右键查看源文件,查看high环境下,命令注入漏洞的代码
high环境相对于medium环境并没有多大改变,只是将黑名单数组array进行了扩充,相比medium增加了不少,这里就不过多赘述,请自行比较。细心观察我可以发现黑名单中’| '中|后多了个空格。这样我们仍然可以用|绕过。 从回显结果可以看到成功绕过。
命令注入常见函数
system 执⾏命令并输出结果 system(‘id’);
exec 执⾏命令 只可获取最后⼀⾏结果
exec(‘id’, a ) ; p r i n t r ( a); print_r( a);printr(a);
passthru 同 system passthru(‘id’);
shell_exec 执⾏命令并返回结果 a = s h e l l e x e c ( ′ i d ′ ) ; p r i n t r ( a=shell_exec('id');print_r( a=shellexec(′id′);printr(a); a = ‘ i d ‘ ; p r i n t r ( a=`id`;print_r( a=‘id‘;printr(a);
popen 执⾏命令并建⽴管道 返回⼀个指针 使⽤fread等函数操作指针进⾏读写
a = p o p e n ( " i d " , " r " ) ; e c h o f r e a d ( a=popen("id", "r"); echo fread( a=popen("id","r");echofread(a, 2096);
proc_open 同 popen (进程控制功能更强⼤)
pcntl_exec 执⾏命令 只返回是否发⽣错误 pcntl_exec(‘id’);
绕过方式汇总
https://uuzdaisuki.com/2020/07/15/%E5%91%BD%E4%BB%A4%E6%B3%A8%E5%85%A5%E7%BB%95%E8%BF%87%E6%96%B9%E5%BC%8F%E6%80%BB%E7%BB%93/