秒懂 SQL Injection

# 前言

現實生活中也可能發生 SQL Injection ? 買飲料的時候店員問你甜度冰塊,你卻跟店員說店長已經連續三個月忘記繳水電費,再不交就要斷水斷電,店員情急之下不疑有他,把盈餘拿出來請你幫忙繳清,你就帶著這筆錢一走了之,SQL Injection 就如同這詐騙一般的行為發生在網站上,開發者沒考慮到意料之外的輸入,駭客趁機對資料庫下命令來竊取或竄改資料,特定狀況下還可以攻到伺服器。

# 實際案例

SQL Injection 真的已經出現很久了,但它依然不斷發生,這邊分享幾個相關的資安新聞,逐個介紹的話就偏離我們快速了解的目標,先了解其嚴重性即可,如果對 SQL Injection 攻擊所造成的影響有興趣,不仿花點時間看看。

# SQL Injection 怎麼發生 ?

SQL Injection 的原理很簡單,利用網頁程式設計者忽略檢查使用者輸入內容造成攻擊,但只從一句話很難看出到底發生了什麼,下面用生活化的例子,帶大家快速了解整個流程。

# 正常流程

了解攻擊流程之前需要先了解正常網站的作業流程,這邊先用兩張圖來說明。

網站登入流程

  1. 用戶在頁面上輸入帳號密碼。
  2. 前端將從頁面上將資料整理給後端。
  3. 後段將資料整理成 SQL 格式,向資料庫詢問是否存在一個名稱欄位為 admin 密碼欄位為 password 的使用者,如果存在的話 ID 是多少。
  4. 後端從資料庫找到這個使用者後判斷讓用戶登入。
  5. 前端在頁面上顯示登入成功。

# 攻擊流程

SQL Injection 攻擊的流程,示範如何不用密碼就可登錄網站。

網站登入流程(SQL Injection)

  1. 用戶輸入帳號密碼。
  2. 前端將資料整理給後端。
  3. 後段將資料整理成SQL語法格式,向資料庫詢問是否存在一個名稱欄位為 admin 或 1=1 和密碼為空的使用者,如果存在的話 ID 是多少。
  4. 後端從資料庫找不到這個使用者但因為 1 等於 1 所以讓讓用戶登入。
  5. 前端在頁面上顯示登入成功。

從流程中可以看出因為輸入中加上符號後組合成 SQL 語句,影響了步驟 3 的輸入與步驟 4 的判斷,因為與 1=1 取聯集導致查詢一定成立,所以即使密碼錯了也可以成功登入。明顯看出攻擊者透過截斷原本程式的語意,插入他希望執行的 SQL 語法,達成攻擊的效果。

# SQL Injection 有哪些種類 ?

看懂攻擊原理後是否感覺 SQL Injection 其實很單純 ? 可惜在實務較為複雜,當開發者想出了方法來保護資料庫後,駭客會在想出新的攻擊手法來繞過,在這互相競爭的過程中,衍伸出各種花式攻擊,我們通常依攻擊手法分成 3 大類,接著利用知名的靶站 DVWA 做一個簡單的示範。

# 1. In-band SQL Injection

最常見和最容易被利用的一種。攻擊者藉由插入 SQL 語法來從資料庫收集資訊,以攻擊方式來看又可再細分為兩個小類別。

在了解攻擊之前還是要先了解正常運作的狀況,範例中是一個查詢頁面,輸入整數的 ID 可以顯示出對應的人員名稱。

# 2. Inference (Blind) SQL Injection

部分頁面輸入後並不像查尋頁面會直接顯示從資料庫來的資料,甚至根本沒有回應 ! 所以攻擊者需要靠其他資訊來攻擊,因為大多數狀況下要靠反複猜測來猜取資料內容,這類型攻擊又常被稱為盲測,以攻擊方式來看又可再細分為兩個小類別,分別對應網站有回應跟沒有回應的兩種狀況。

在了解攻擊之前還是要先了解正常運作的狀況,範例中是一個查詢頁面,輸入整數的 ID 之後網站會告訴你這個 ID 在資料庫中資否存在,所以只會回應有跟沒有,不會直接顯示從資料庫中得到的資料。

# 3. Out-of-band SQL Injection

該類因為攻擊前置需求比較高,所以比較少發生,攻擊方式主要是透過 SQL Injection 來攻擊與資料庫有串連的系統,像是 DNS Server、文件系統、電子郵件等等,所以攻擊方式取決於後面有串那些系統,本次測試靶站利用 docker 架的環境相對單純,沒有這類型的問題。

發生機會低不代表問題不會發生,因為缺範例這邊補上一篇近期從 SQL 打到 DNS 的資安新聞。

政府網路遇襲上月近10萬件 非核心系統也成目標

# 總結:

SQL Injection 畢竟是由使用者輸入所導致的問題,要解決當然也要從輸入下手。

解決方案(一) : 輸入過濾

過濾輸入是最常見的防範方法,藉由檢查 SQL 語法中有意義的符號來避免語意被竄改,但要特別注意兩點,第一是必須在後端進行過濾,因為駭客有太多機會繞過前端檢查,第二是避免用黑名單的方式過濾,因為駭客會嘗試用合法的字元來組合出該被過濾掉的符號,用白名單可以將這個問題的發生機率降到最低,不過白名單只適合用在輸入較為單純的網站,如果網站的輸入較複雜或者必須包含符號,建議改用其他方法。

解決方案(二) : 參數化

限制輸入僅含參數不含語法,接著在輸入後立刻轉換輸入格式。

以開頭的免密碼登入攻擊來舉例,實際上資料庫收到的 SQL 語句如下。

SELECT ID FROM Accounts WHERE user ='admin or '1'=1' and 'pass'='';

如果在先轉換輸入內容轉換為字串再放入 SQL 語句。

SELECT ID FROM Accounts WHERE user="admin\' or \'1\'=\'1" and 'pass'="";

這時會去檢查有沒有一個名稱為 admin' or '1'='1 的帳號,結果當然是找不到攻擊也失效,這種方法比較通用,不過要注意轉換失敗時的例外處理,部分程式語言會直接 crash,影響到網站服務。

解決方案(三) : 資料庫套件

其實這個解決方案是前兩個安案的延伸,有一些套件已經幫你做完上述兩件事情,所以透過套件來呼叫資料庫可防止攻擊發生,常見的像是 JAVA 的 JDBC 套件,其他程式語言也有類似的套件,但使用前務必做好功課,避免用了不安全的套件導致網站還是受到攻擊。


前面為快速說明原理挑了一些簡單易懂的攻擊來示範,實際上還有更多進階的攻擊手法,如果閱覽數量夠多,之後會再加開一篇分享一些更進階的用法與經典案例,有任何資安方面相關的問題都歡迎留言討論,或者直接到 Cymetrics 尋求協助。

更多同分類文章

隨機推薦

  1. PWN 入門 - rop, gadget 是什麼?
  2. 關於 email security 的大小事 — 延伸篇
  3. 關於 email security 的大小事 — 範例篇
  4. 零基礎資安系列(五)-路徑遍歷(Path Traversal)
  5. 從Indexing的角度切入MySQL-Innodb與PostgreSQL的效能比較