既然昨天講了基礎的 SQL injection (以下簡稱 SQLi) 的語法,今天是時候講一些進階的東西,那就是 UNION SELECT(希望不要覺得我太水,但是想解釋真的好麻煩)
根據 YJK 大神(團隊的隊友)所述,UNION SELECT 是個噁心的東西,簡答的講一下,就是把一坨 SELECT 的條件收集起來然後匯出集合,用昨天星〇克跟炒飯的例子來講,今天的 UNION SELECT 就像是你跟店員點餐的時候講了多個關鍵字,例如:中餐、飯,然後店員又把炒飯端了出來,沒錯又是一個奇妙的例子(我絕對不是在臭星〇克,只是我覺得這個例子很棒 XD),那剛剛例子中的中餐不一定只有炒飯,而飯也不是只有炒飯,但是這兩個的集合很容易讓你聯想到炒飯,當然這只是一個簡單的舉例
我知道我的例子可能忽略了過多的細節,各位電神大大一定準備要開噴了,沒關係我這裡會仔細的講 detail,那基本上 UNION 就是 SQLi 的語法的延伸,那 UNION SELECT 跟昨天提到的 SELECT 之間的差別就是 SELECT 一次只能做一個查詢,而 UNION SELECT 可以執行多個,並輸出他們的結果的集合,那基本上會用到的相關語法會是這樣
SELECT a, b FROM table1 UNION SELECT c, d FROM table2
那使用這一串語法去做查詢以後產生的返回值會包含 table 和其中的資料,以及 table 之間的集合
a b table1 c d table2
那麽問題來了,難道可以在不知道有幾列的情況下隨便亂戳嗎?當然不是,想要滿足他的語法必須符合以下幾個條件
那詳細的操作基本上有一個固定的流程
一般要確定欄位的話有兩種常見的方法,兩種很簡單,説白了就是直接跟他硬爆,先講第一種,會用到的語法如下
' ORDER BY 1 --
' ORDER BY 2 --
' ORDER BY 3 --
後面就是無限延伸直到試出報錯
這種方法是利用注入一堆子句并且逐漸遞增,直到發生錯誤,這樣就可以知道它的欄位有幾項,像我這邊的例子是假設該查詢子句本身會出現數字,所以我這裡就一步步遞增來測試欄位的數量
那這種方法成功套出欄位數量的話會回傳偵錯,然後你塞入子句的數量 -1 就會是欄位的數量,一般報錯會長的差不多,例如以下的例子,但還是因情況而改變
The ORDER BY position number 3 is out of range of the number of items in the select list.
而第二種方法是我比較1喜歡的方法,我是覺得他比較直覺啦,概念一樣,只是提交的不是逐漸遞增的子句而是用複製 NULL 來爆破專有名詞叫做提交有效負載,但是我不 care,不用動腦就是讚,語法也是如下:
' UNION SELECT NULL --
' UNION SELECT NULL, NULL --
' UNION SELECT NULL, NULL, NULL --
也是一直複製貼上直到報錯消失
是不是真的很直覺,原理就是使用空值 NULL,如果與空值的數量與欄位數不相同就一樣會報錯,而報錯長相也是如以下的例子:
All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.
例題網址:https://portswigger.net/web-security/sql-injection/union-attacks/lab-determine-number-of-columns
首先進去一樣是購物網站的形式
那既然題目是叫我們用 UNION SELECT 來處理 category ,那就直接照做,那要如何找到 category,就是隨便點一個除了 All 以外的分項,就會跑出查詢的語法,而查詢的地方就會跑出 c
ategory,如圖示:
而我們要做的就是把 =
後面的參數先通通刪掉,然後補上剛剛提到的語法
filter?category= ' UNION SELECT NULL --
那正常來説在那個 Lab 裡面會出現這樣的報錯(我的 solved 那一串是因爲我先解了一次了)
我們的目標是把 NULL 的數量補到剛好符合欄位的數量,所以就一直持續的複製貼上,直到試到第三個的時候報錯就突然消失了 Σヽ(゚Д ゚; )ノ
這邊順便附上答案以防有人真的不會
' UNION SELECT NULL, NULL, NULL --
或者是你真的特別喜歡 ORDER BY
這個語法也是可以解開這一題,只是他不會算你對,但是我還是可以演示一次
首先一樣的把 =
後面的參數先通通刪掉,用上另一個語法:
filter?category= ' ORDER BY n--
n 就是從 1 開始帶入,那這個就是跟 NULL 反過來,NULL 是嘗試到報錯消失,而這個是嘗試到報錯,然後 n-1 就是欄位數量,像這裡我試到答案 3,但是依然沒有報錯,而一到 4 就開始報錯了,代表 4 之前都是欄位的數量,只是我不知道爲什麽這個不算對,可能跟設計的機制有關
好不管,恭喜答對,現在你會怎麽找欄位數量了,但是在進入下一步之前我還是要説明一下,每種網頁用到的語法可能會不同,實際操作的話就是需要做出各種嘗試,不會每個都像是題目的 Lab 一樣經過精心設計,這也是之後想要嘗試盲注的時候的必經之路
很好我們完成了第一步,確認完欄位數量以後就是想辦法找出適合的資料類型,那假設我們對某種形式的資料特別感興趣,我們就在 UNION SELECT NULL --
中混入我們想找的資料形式,當然前提是你要找到欄位的數量,對就是上面那一題,所以這些東西基本上就是環環相扣的根本坐牢,那詳細的語法就跟著 Lab 一起教
例題網址:https://portswigger.net/web-security/sql-injection/union-attacks/lab-find-column-containing-text
好我們首先講解語法,那基本上就是用要的資料類型去一個個帶入 NULL,如以下的示範:
' UNION SELECT 'a', NULL, NULL, NULL --
' UNION SELECT NULL, 'a', NULL, NULL --
' UNION SELECT NULL, NULL, 'a', NULL --
' UNION SELECT NULL, NULL, NULL, 'a' --
那找到正確位置的話就會跑出正常頁面看不到的東西,而錯誤的話則是跳報錯如下:
Conversion failed when converting the varchar value 'a' to data type int.
那正式進入例題,一樣熟悉的購物網站,那也是一樣的流程,隨便點開一個除了 All 以外的分頁,那他有提示叫你找'BKgPC0'這一串東西,不然你也不知道要找什麽就是了
先利用上一題的方法找到欄位數量
那找出來是 3 個以後就把關鍵字套進去,排列組合一下答案就出來了
例題網址:https://portswigger.net/web-security/sql-injection/union-attacks/lab-retrieve-data-from-other-tables
那例題 3 就是總結前面學的東西做一個進一步的練習啦,基本上可以把它當成真實情況來試,因爲一般你拿到也是毫無頭緒,那就一樣先從欄位數量開始做嘗試
可以看到很好心的只有兩欄,不然真的會推到吐血(癱,接著測試每一欄的資料形式,那他只有教過文字,那我們就都用文字,我這邊是使用 'abc'
來分別測試兩個欄位,結果都是符合的形式,代表兩個欄位的資料類型其實都是字串(string)
那再根據 Lab 首頁給出的提示,我們要從 users
中想辦法把 username
跟 password
都生出來,再加上兩個欄位都是字串,拿我先試試看一下的語法:
' UNION SELECT username, password FROM users --
然後就是蹦蹦答案,沒,只是真的把他的賬號密碼給捅了出來,那我們要做的就是按照題目要求登入administrator
這個賬號,那賬號跟密碼都幹到手,Go Go ~
administrator
94k0cku11r2r6gsmck3s
你以爲昨晚這題看起來很通靈的就結束了嗎?我看你是沒看過更刺激的😇,問就是最後一題,也是進階應用
例題網址:https://portswigger.net/web-security/sql-injection/union-attacks/lab-retrieve-multiple-values-in-single-column
我發誓這是今天的最後一題,因爲想解釋真的好麻煩_(:3 」∠ )_,好啦這題其實說難也沒有到特別難(嗎,反正就是步驟改一下然後塞一些進階的語法想辦法達到他的要求,下面附上官方給的作弊表單,想要自我挑戰自虐的可以不用參考
Cheat-sheet:https://portswigger.net/web-security/sql-injection/cheat-sheet
好的回歸正題,一樣的方法先找欄位數,然後確認資料的類型,那我這裡會跳比較快,如果有步驟不是清楚就去上面翻或者直接提問啾咪
首先確認是兩欄
經過測試只有第二欄是字串,第一欄是未知,那先放著不管,那就先測試套 username 看看能不能捅出什麽東西來用
' UNION SELECT NULL,username FROM users --
可以看到真的捅出了賬號,所以我説那個密碼呢 (メ ゚皿゚)メ,好沒有的話我們就自己敲出來,那至於要怎麽捅,理論上要麽是靠個人經驗要麽就是剛剛提到的 cheat-sheet,對,就是怎麽無恥,好啦其實一個一個硬試其實太耗時間了,有前人整理的資料就是要用啊,那我們就從 Oracle
開始試:
' UNION SELECT NULL, username ||'>'|| password FROM users --
好欸它又對你吐露心聲了,那就心懷感激的把賬號登進去吧
administrator
eu7ggorhzdnqvqcbmk1q
好欸成功了,基本上你去看那個 Lab 的詳解都是用他們平台的工具,理論上是免費的,但是要用到他們用的功能就要付費,啊不就還好我腦波夠強其實是沒錢,一開始在學的時候這題真的想了很久,可能是我沒有這個天賦吧,但是還是靠肝把經驗堆起來了,我個人是覺得 SQLi,通靈的成份真的偏高,其實不止 SQLi,CTF 跟 PT 都是通到就過了CTF大佬不要扁我拜托,我只是單純沒料而已,明天的部分可能就是盲注或其他的更更進階使用法吧,希望各位可以從我這裡學到東西~