來到第五天,讓我們實際進入探討Web題有機會牽涉的第一個技術——SQL注入。
在講SQL注入之前,讓我來簡單講講甚麼是SQL吧!
Structured Query Language(結構式查詢語言),簡稱SQL,是一種很常在資料庫中用於處理資訊的程式設計語言。
如果你從未接觸過SQL,你可以透過以下例子簡單看看SQL大概是個甚麼東西。
以下是一個 "SQL Query(陳述式)" 的例子:
假設有一個資料庫:
id | title | date | author |
---|---|---|---|
1 | Day 01 | 序 • 什麼是 CTF? • 系列介紹 | 2023-09-16 | sayakohzk |
2 | Day 02 | CTF資源介紹 | 2023-09-17 | sayakohzk |
3 | Day 03 | CTF的題目類型介紹 | 2023-09-18 | sayakohzk |
4 | 想問一下SQL到底可以怎麼學? | 2011-03-10 | helloworld123 |
現在運行以下 SQL Query (SQL表達式)
SELECT id, title, date
FROM articles
WHERE author = 'sayakohzk'
那麼將會返回:
id | title | date |
---|---|---|
1 | Day 01 | 序 • 什麼是 CTF? • 系列介紹 | 2023-09-16 |
2 | Day 02 | CTF資源介紹 | 2023-09-17 |
3 | Day 03 | CTF的題目類型介紹 | 2023-09-18 |
上面的例子中,我們執行了一個SQL Query,從articles 資料庫中選擇顯示列id ,title 和date ,而且只挑選author 是'sayakohzk' 的行。 |
||
類似於這樣,SQL能夠用於資料庫中進行各種數據的處理,因此也常常用於需要連接資料庫調用資料的網頁之中。 |
那麼,SQL注入是甚麼來的呢?
讓我們先來想像一個網頁登入系統,透過使用一個名為Users
的資料庫來儲存用戶資料:
id | username | password | ... |
---|---|---|---|
1 | ken | 23232323 | ... |
2 | henry | iamhenry | ... |
3 | colton | crayon | ... |
.. | ... | ... | ... |
每當用戶登入的時候,網頁伺服器將會收集用戶提供的Username和password。 | |||
我們假設網頁伺服器將他們分別儲存在 variables變數 uName 和 uPass 之中,而用戶登入時將會運行以下SQL Query: |
SELECT * FROM Users WHERE username = '[uName]' AND password = '[uPass]'
(假設上述的 [uName] 和 [uPass] 會被替換成用戶輸入的內容)
是不是看起來沒問題?當用戶輸入帳號和密碼之後,返回所有該用戶的資訊。
然而,你不能確定用戶輸入的真的是帳號名和密碼。
例如,假設我現在輸入以下資訊:
用戶名:' or '1'='1
密碼:' or '1'='1
那麼,網頁的服務端將會執行甚麼呢?
SELECT * FROM Users
WHERE Name = '' or '1'='1'
AND Pass = '' or '1'='1'
我們可以看到,'1'='1'
的部分將會永遠成立(true
),於是所有用戶的資訊都將會被返回。
結果,我們就靠輸入' or '1'='1
而輕易獲得了所有用戶的個人資料。
當然,實際上的CTF題目甚至真實的網絡安全應用會設有不少的防護措施來消除此類很明顯的漏洞。不過這,就是SQL注入的基本概念。
以CTFLearn中的 #88 題目 Basic Injection 為例,
我們首先會進入到一個頁面:
可以看到我們需要輸入一個 input,然後那個 input 會被放到 SQL 表達式當中。
我們嘗試輸入' or '1'='1
:
成功破解 Flag!
有時候我們可以利用資料庫某些特別的機制,刻意製造一些的錯誤,讓程式返回錯誤訊息而拿到SQL版本、伺服端表達式線索、甚至flag等隱藏訊息。
舉一個例子,假設有一個網店接受以下連結 https://xxxxx.com/item.php?id=(ID)
來查詢ID
編號的物品。如果我們在 id 輸入會導致錯誤的東西,例如一個引號:https://xxxxx.com/item.php?id=12'
,那很可能會返回一個錯誤,例如是:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘‘VALUE’’.
這樣,我們就知道了伺服端使用了 MYSQL 的語言,而且發生錯誤的語句使用了 VALUE 的字眼。
以這作為基礎,便能夠讓我們知道不少隱藏的訊息,例如其他資料庫的資料庫名,以協助我們找出 Flag。
盲注就是在不能收到包括抱錯等詳細的回應時,可以使用的注入方式。
主要分為布林(Boolean)盲注與時間盲注,
前者可以在只能收到 TRUE/FALSE 等兩種型態為回應時用,
後者則只需分析回應時間,只要有任何型式的回應都可以用。
布林注入的基本概念就是透過觀察特定表達式是否True來判斷資料庫的各種特徵;
例如:在某個網站會將我們輸入的內容放在select * from articles where id=$input
的SQL表達式之中,而嘗試輸入1 AND 1=1
的時候我們會收到成功的回復,1 AND 1=2
的時候我們會收到失敗/錯誤的回復,那麼理論上只要把AND後面改成任意我們想要確認的內容就能判斷其真實性。例如,我們可以透過改掉後面的部分判斷資料庫的名字(第一個字母='a'? 第一個字母='b'? 等等,持續下去),那麼如果自動化這個部分就能夠知道資料庫名字了。
時間盲注的概念也十分相似,然而我們不用伺服器回傳的成功/失敗 或 TRUE/FALSE來判斷,而是透過 IF(1=1, sleep(3), 0)
這種方式,如果前面的condition布林值是TRUE
,那麼程式就會等一段時間,不然就回傳0。我們可以透過回傳速度判斷其布林值,而其他操作則與布林注入相似
以上就是SQL注入的基礎啦!這算是比較入門也常見的一種WEB題牽涉的技術。下一則我將會說一說XSS,還請大家多多期待!