NoneCMS1.3版本SSRF漏洞

0x00前言

NoneCMS添加文章处过滤不严存在SSRF漏洞

0x01漏洞分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#application/admin/controller/Article.php
public function copy()
{
if (request()->isAjax()) {
$url = input('post.url');
$cid = input('post.cid');

if (!$url || !substr_count($url, 'csdn')) {
exit(json_encode(['status' => 0, 'msg' => '请输入csdn博客文章地址', 'url' => '']));
}

if (!$cid) {
exit(json_encode(['status' => 0, 'msg' => '请先选择分类', 'url' => '']));
}


try {
\phpQuery::newDocumentFile($url);
$title = pq('.link_title a')->text();
if (!$title) {
$title = pq('.list_c_t a')->text();
}
if (!$title) {
$title = pq('h1.csdn_top')->text();
}
$content = pq('#article_content')->text();

//如果抓取不到主内容
if (!$content) {
throw new Exception("文章不存在或禁止爬虫");

}
$params['cid'] = $cid;
$params['content'] = $content;
$params['title'] = $title;
$params['publishtime'] = '';
$params['description'] = trim(strip_tags($content));
$params['copyfrom'] = $url;
$article = new articleModel();
if ($article->data($params,true)->save()) {
return ['status' => 1, 'msg' => '转载成功', 'url' => url('article/index', ['id' => $cid])];
} else {
return ['status' => 0, 'msg' => '转载失败', 'url' => ''];
}
} catch (Exception $e) {
return ['status' => 0, 'msg' => '添加失败:' . $e->getMessage(), 'url' => ''];
}
} else {
return $this->fetch();
}

}

1.当请求copy方法时首先判断请求方式为Ajax,然后检测要求存在url参数,并且url中包含csdn字符串即可(很容易利用?csdn绕过)。
2.调用\phpQuery::newDocumentFile,函数内容如下:

1
2
3
4
5
6
public static function newDocumentFile($file, $contentType = null) {
$documentID = self::createDocumentWrapper(
file_get_contents($file), $contentType
);
return new phpQueryObject($documentID);
}

请求目标url,内部调用了file_get_contents请求。
3.由此可见,存在ssrf漏洞。

0x02POC:

payload

目标服务器成功收到请求

ssrf

0x03小结

需要管理员登录后才能利用,且由于请求目标不是CSDN,会导致copy函数后面的处理获取不到有效数据,会提示“服务器出错”,但是实际请求已经成功发送出去了。

0x04修复建议

利用parse_url提取URL的域名是否属于CSDN。