概述
一款某单子Tp二开平台,开发者嚷嚷着要找人审计一下源码,说有预算,洞审出来之后人就没了,感觉审都审了,不做点什么不是浪费时间了,于是就发出来顺便讲一下在Tp二开情况下如何对源码进行审计,一般在拿到Tp二开的源码,首先要做的事,确认系统版本,然后利用搜索引擎寻找当前框架版本的漏洞,这次拿到手之后在确认下是Tp3.2.3的系统,其次就是查看TP的路由是默认还是说更改了,然后找到web类,对类中的代码一行一行的仔细审计,Tp3.2.3爆出的漏洞挺多的,结合前辈的各种经验,成功寻找到了开发中的雷区,这里直接贴代码。
任意文件包含代码执行
在Application\Home\Controller\VueController.class.php下,可以看到这里是这样写的。
但是在TP3.2.3中,这是个大问题,因为display方法会直接包含这个变量中的文件,并且在Controller.class.php中的_Call类定义了如果存在_empty方法,就会优先调用,这里methed_name就是a方法类的传值,但是如果我们另调用的a类直接为我们要包含的文件的绝对路径,那么就会直接包含掉我们所给的文件。
这里贴出详情漏洞代码
public function _empty($methed_name){ $this->display($methed_name); exit(0); }
我们这里可以看到,当把A设置为日志的绝对路径时,会直接包含掉这个日志,从而造成任意代码执行。
Sql注入
在Application\Api\Controller\AreaController.class.php下,先铺上代码。
这里没有使用I方法,而是直接通过$_REQUEST['pid']去取得Pid的值,我们这里可以构造Exp表达式用于Where条件,然后对代码进行注入,也不知道是不是留的后门,前面都写了I,就这里非要用$_REQUEST['pid']去接受参数,构造pid[0]=exp&pid[1]= and updatexml(1,concat(0x7e,(select user())),0)可以看到成功爆出来了用户名。
public function ajax() { $pid = $_REQUEST['pid']; $list = D('Area')->where(array('pid'=>$pid))->select(); $html = ''; foreach( $list as $k=>$v ) { $html .= '<option value="'.$v["area_id"].'">'.$v["title"].'</option>'; } echo $html; }
Session操控
在Application\Api\Controller\CodePayController.class.php中,就更离谱了,铺上代码。
这里的$key,$value值都是经过$_REQUEST传参进来的,也就是说,我们可以任意的对Session进行操控,结合判断的Check_login来看,发现只是判断Session里面是否存在值。
```php
public function setsession()
{
$key = (isset($_REQUEST['key']) && !empty($_REQUEST['key']) ) ? $_REQUEST['key'] : '';
$value = (isset($_REQUEST['value']) && !empty($_REQUEST['value']) ) ? $_REQUEST['value'] : '';
session($key,$value);
}
```php
function check_login(){
if (!empty($_SESSION['user']['id'])){
return true;
}else{
return false;
}
}
还有这里写入的,我们就可以自己构造出相应的变量,从而达到未授权登录的目的。
番外
其实在TP3.2.3中,还有一种情况,可以直接调用Dispaly。
当ThinkPHP\Library\Think\Controller.class.php中的Display为Public的情况下(默认为Protected),可以从前台控制器中直接调用Display造成执行任意代码,当然一般情况下遇不到,不过如果当一个后门还是挺好用的。
protected function display($templateFile='',$charset='',$contentType='',$content='',$prefix='') { $this->view->display($templateFile,$charset,$contentType,$content,$prefix); }
总结
如果遇到TP二开的系统,确认版本,找到控制类,结合前辈们的经验,站在巨人肩膀上对其进行审计,要是类中的代码没问题,我建议尝试寻找Tp的0day(好像某个大佬手上有Tp3.2.3的代码执行)。