BUU-Web-[SUCTF 2019]EasySQL
第一步:對頁面進行分析

通過抓包看到頁面

沒有其他的敏感內(nèi)容
嘗試輸入【1】

輸入【or】后發(fā)現(xiàn)被過濾了

然后嘗試fuzz一下
發(fā)現(xiàn)以下內(nèi)容均被過濾
嘗試使用堆疊注入
所謂堆疊注入就是將多條sql語句放在一起執(zhí)行并且以【;】分開


由于 【from】被禁用,我們這里沒有辦法從flag中拿取數(shù)據(jù)
這里嘗試許多辦法最后在GitHub上獲取到了該題目的源代碼

$sql = "select ".$post['query']."||flag from Flag";
這就是執(zhí)行的sql語句
我們對源碼分析發(fā)現(xiàn)這里有【||】表示或,傳入的參數(shù)經(jīng)過拼接后就成了(如query=1)
? ?????select 1?|| flag?from?Flag
在數(shù)據(jù)庫中查詢就變成了

正如我們獲取到的數(shù)據(jù)

現(xiàn)在要做的就是如何繞過【||】,并且讓其執(zhí)行后面的代碼【flag from Flag】
方法一:使用Sql_mode 中的PIPES_AS_CONCAT函數(shù)
PIPES_AS_CONCAT:將【||】原本的“或”轉(zhuǎn)換為“連接字符”,就是將||前后進行拼接
使用方法:PayLoad1【1;set sql_mode=PIPES_AS_CONCAT;select 1】
拼接過后的結(jié)果就是【select 1;set sql_mode=PIPES_AS_CONCAT;select 1||flag from Flag】
數(shù)據(jù)庫就會識別為【select 1||flag from Flag;】注意:這里的||以及不是或的意思,是管道符的意思,就是將1查詢完后,會繼續(xù)查詢flag的內(nèi)容,然后將結(jié)果合并返回,如圖

同時還有別的sql_mode
ANSI_QUOTES
?啟用 ANSI_QUOTES 后,不能用雙引號來引用字符串,因為它被解釋為識別符,作用與 ` 一樣。設(shè)置它以后,update t set f1="" ...
,會報 Unknown column '' in 'field list 這樣的語法錯誤。NO_TABLE_OPTIONS
?使用?SHOW CREATE TABLE
?時不會輸出MySQL特有的語法部分,如?ENGINE
?,這個在使用 mysqldump 跨DB種類遷移的時候需要考慮。NO_AUTO_CREATE_USER
?字面意思不自動創(chuàng)建用戶。在給MySQL用戶授權(quán)時,我們習(xí)慣使用?GRANT ... ON ... TO dbuser
?順道一起創(chuàng)建用戶。設(shè)置該選項后就與oracle操作類似,授權(quán)之前必須先建立用戶。5.7.7開始也默認了。
方法二:利用非預(yù)期注入方式獲取Flag
我們傳遞過去的內(nèi)容會被解析為$sql = "select ".$post['query']."||flag from Flag";
因此我們可以在傳遞值這邊做文章,讓數(shù)據(jù)庫進行錯誤的判斷
我們可以嘗試傳入1,1


我們可以發(fā)現(xiàn),這里的內(nèi)容查詢不是對【1,1】||【flag】而是對【1】,【1||flag】
這就是數(shù)據(jù)庫對符號的判斷不嚴謹,導(dǎo)致的非預(yù)期漏洞
我們就可以將","前的內(nèi)容改為“ * ”, 從而構(gòu)建PayLoad【 *,1 】



這道題嚴格意義上來說難度不大,在于考察的是對注入的掌握程度
本題中核心的知識點有:
堆疊注入
利用Sql_mode中的PIPES_AS_CONCAT 將 ||?的作用轉(zhuǎn)換連接
非預(yù)期注入