复现HITB PHP lover代码审计
參考文獻(xiàn):https://www.anquanke.com/post/id/104952
一直想學(xué)代碼審計(jì)來著,看到了一篇大佬的關(guān)于php代碼審計(jì)的wp,決定自己試一下
源碼下載地址:https://hitbxctf2018.xctf.org.cn/contest_challenge/里面的web題目中的PHP lover
代碼結(jié)構(gòu)
Controller 控制器,只有index.controller.php Core 類及方法定義 templates 前端的各種html界面 uploads 里面是兩張圖片 back.sql 創(chuàng)建的數(shù)據(jù)表 config.php 連接數(shù)據(jù)庫 function.php 定義過濾函數(shù) index.php 入口文件從index.controller.php看下主要功能
public function login() public function register() public function add() public function view() public function edit() public function export()- login()
1.png
登錄調(diào)用User類的login()方法,跟進(jìn)login()函數(shù)(在user.class.php中)
2.png
跟進(jìn)username的過濾函數(shù)filter()(在function.php文件中)
3.png
其中正則表達(dá)式中的b表示的為單詞邊界,而不是通配,如preg_match("/bwebb/i")只能匹配到web,而web123這種就不能。
所以可以用"select * from/**/users"繞過此過濾(/**/作為空格注入)
但是在User類的login()方法中,
這就把/**/過濾了,所以這個(gè)方法不行
-
register()
1.png跟進(jìn)user類的register()方法
2.png
其中$username和$nickname沒有可能了
再看一下email,看下正則匹配
其中([\"].+[\"])只需要""包圍即可,引號(hào)中可以隨便寫。所以可以用·'"' and 1=1#'"@skysec.top'這種繞過,但是在daddslashes()這個(gè)函數(shù)中將"轉(zhuǎn)義了。
-
add()
1.png跟進(jìn)user類中的add()方法
2.png
全部被轉(zhuǎn)義 -
view()
1.png
跟進(jìn)user類中的getarticle()函數(shù)
2.png
emmm,直接intval()也是妙。。 -
edit()
1.png上傳功能,類型檢測(cè)可以抓包bypass,但是
文件后綴直接是mine的類型,這樣就不能bypass上傳惡意文件了
跟進(jìn)下user類的getuser()方法
2.png
文件名、是我們注冊(cè)的用戶名,用戶名是無法bypass的,所以這里的上傳,除了文件名長度其他都不可控
-
export()
1.png跟進(jìn)user()類中的report()方法
2.png
這里被當(dāng)做錯(cuò)誤觸發(fā),未做任何過濾,其中email的插入很關(guān)鍵
所以接下來才算步入正題。。。emmm先膜拜下大佬的思路。
攻擊點(diǎn)
- 這題注冊(cè)的時(shí)候,可以Bypass注冊(cè)惡意郵箱,但是其中有符號(hào)被轉(zhuǎn)義了
- 但是這個(gè)轉(zhuǎn)義在取出數(shù)據(jù)庫的時(shí)候會(huì)被去除
- 如果在取出后,系統(tǒng)又對(duì)這個(gè)數(shù)據(jù)進(jìn)行了一次sql操作,就可以觸發(fā)注入,通過二次注入
- 我們的注冊(cè)的時(shí)候注冊(cè)惡意郵箱,在這里觸發(fā)錯(cuò)誤報(bào)告的時(shí)候就會(huì)被系統(tǒng)再次調(diào)用,取出數(shù)據(jù)庫后轉(zhuǎn)義消失
- 拼接到insert語句時(shí),構(gòu)成sql注入攻擊
我們根據(jù)這一點(diǎn)注冊(cè)用戶,郵箱為
假設(shè)我們能觸發(fā)export()函數(shù)中的$this->user->report(1)
$this->email為我們郵箱取出數(shù)據(jù)庫的值:
"', 233), (2333, (SELECT group_concat(TABLE_NAME) FROM/**/ information_schema.TABLES where TABLE_SCHEMA=database()), 23333)#"@skysec.top此時(shí)利用report插入了兩條數(shù)據(jù)
$this->id,'"', 233 2333, (SELECT group_concat(TABLE_NAME) FROM/**/ information_schema.TABLES where TABLE_SCHEMA=database()), 23333)觸發(fā)sql注入需要解決
①自己的id需要知道,這樣可以插入
在view()方法中
若是不輸入article參數(shù),會(huì)調(diào)用
function getid(){if ($this->islogin) return $this->id;else return null;}就可獲得id
②觸發(fā)if(file_exists($avatar) and filesize($avatar)<65535)false,這樣就會(huì)成功到else,構(gòu)成攻擊
跟進(jìn)user類中的getavatar()方法
2.png
查看back.sql文件,其中 $r[1]:data $r[3]:filepath
如果我們的上傳圖片有數(shù)據(jù),就返回Base64后的數(shù)據(jù),否則返回路徑
edit()的上傳功能中有
$filename="uploads/".$this->user->getuser().".".$type; if(is_uploaded_file($_FILES['avatar']['tmp_name'])){$this->user->edit("avatar",array($filename,$type));跟進(jìn)user類中的edit()方法
if($feild=="avatar"){return $this->db->Insert("avatar",array("''",$this->id,"'$value[0]'","'$value[1]'")); }即avatar表的filepath字段為
uploads/用戶名.文件mine數(shù)據(jù)庫結(jié)構(gòu)中
2.png用戶名的長度是300,而路徑長度
`filepath` varchar(300),如果我們的用戶名長度為300,此時(shí)插入的路徑就會(huì)被300截?cái)?#xff0c;而變成一個(gè)不存在的路徑,此時(shí)即可觸發(fā)file_exists($avatar)錯(cuò)誤
題目鏈接打不開了,放下大佬的完整攻擊流程:
- 先隨便注冊(cè)個(gè)用戶,看一下自己的id
- 然后再迅速注冊(cè)用戶,驗(yàn)證id是否是自己預(yù)想的id+1
- 登錄后觸發(fā)上傳功能
- 上傳空文件,抓包改mine
- 觸發(fā)export功能,即可完成攻擊,發(fā)現(xiàn)注入成功后的數(shù)據(jù)
最后得到flag表,以及數(shù)據(jù)
總結(jié)
以上是生活随笔為你收集整理的复现HITB PHP lover代码审计的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [日常] Go语言圣经--Channel
- 下一篇: Redis 缓存数据库