远程代码执行/命令执行漏洞
原理
在操作系统中,& | ||
都可以作为命令连接符使用,用户通过浏览器提交执行命令,由于服务器没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令。
应用有时需要调用一些执行系统命令的函数,如PHP中的system、exec、shellexec、passthru、popen、procpopen等,当用户能够控制这些函数中的参数时,就可以将恶意系统命令拼接到正常命令中,从而造成命令执行攻击,这就是命令执行漏洞。
命令执行与代码执行的区别
命令执行漏洞可以直接调用操作系统命令;代码执行漏洞靠执行脚本代码调用操作系统命令,可以执行代码和系统命令进行读写文件、反弹shell等操作,借此拿下服务器后,进一步进行内网渗透。
修复
命令执行修复方案
- 尽量少用执行命令的函数或直接禁用
- 在使用动态函数时,确保使用的函数是指定的函数之一
- 在进入执行命令的函数/方法之前,对参数进行过滤,对敏感字符转义
- 能使用脚本解决的工作,不要调用其他程序处理。尽量少用执行命令的函数,并在disable_functions中禁用
- 在可控点是程序参数的情况下,使用escapeshellcmd函数进行过滤;在可控点是程序参数值的情况下,使用escapeshellarg函数进行过滤。
- 参数的值尽量使用引号包括,并在拼接前用addslashes进行转义
- 对由特定第三方组件引发的漏洞,要及时打补丁,修改安装时的默认配置
代码执行修复方案
- 能使用Json保存数组、对象就使用Json,不要将php对象保存成字符串,否则读取时需要使用eval。将字符串转化为对象的过程其实是将数据转化 为代码的过程,这个过程很容易出现漏洞,像PHP的unserialize导致代码执行、Struts 2的ognl命令执行等漏洞,都是这个过程出现的。
- 对于必须使用eval的情况,一定要保证用户不能轻易接触eval的参数(或用正则严格判断输入的数据格式)。对于字符串,一定要使用单引号包括可控代码,并在插入前进行addslashes,这样就无法闭合单引号,因为不包括双引号,故不能执行
${}
- eval(’${phpinfo()}’)、eval(”phpinfo()”)、等都不会执行,eval(”${phpinfo()}”)、eval(phpinfo())、eval(${@phpinfo()})都可以执行,因为双引号里面的内容会被当作变量解析一次,函数前加@表示执行函数不报错
- 放弃使用pregreplace的e修饰符,而换用pregreplacecallback代替。如果非要使用pregreplace的e模式的话,请保证第二个参数中,对正则匹配出的对象用单引号包括。
- 首先,确保register_globals=off,若不能自定义php.ini,则应该在代码中控制;其次,熟悉可能造成变量覆盖的函数和方法,检查用户是否能控制变量的来源;最后,养成初始化变量的好习惯
- 能够王本地写入的函数都需要重点关注,如fileputcontents()、fwrite()、fputs()等
- 当前自动化漏洞检测中可以直接输入“;print(md5(test));$a=”等字符,匹配返回页面是否有md5关键字符串。