SQL Injection 基本原理與保護

SQL Injection 基本原理與保護

由於每個網站背後都會有 Database 存放資料,

這篇文章主要介紹SQL Injection 的形成原因、如何避免、

SQL injection 所帶來的資訊安全風險與建議。

 

通常來說,網站或是雲端服務會利用資料庫來存放下列資料

  • 使用者資料、帳號
  • 商品資訊、訂單
  • 其他相關商業邏輯與權限

由於 SQL是直譯式的語言,

因此如果網站的使用者輸入與後端資料庫沒有適當的安全防護,

駭客就可以利入輸入SQL 語法與參數讓後端資料庫執行駭客所預期的行為甚至控制整個資料庫與電腦。

由於SQL Injection的問題存在多年,

目前新的程式語言的寫法與資料庫本身都會提供一些保護機制,避免SQL injection 的發生

當然,這也讓SQL injection 的攻擊方法有所演進,

接著我們將從幾個 SQL injection 基本概念到進階的攻擊方法做討論。

 

SQL 線上練習

這邊介紹一個可以線上練習各種 SQL database 的雲端服務,

讓你不需要安裝任何Database 就可以學習 SQL 語法,

還可以選擇 MySQL, MS SQL, Oracle..等資料庫

http://sqlzoo.net/wiki/Main_Page

 

SQL online

 

語法錯誤 ‘

為了測試是否有 SQL injection 的風險,一開始都會利用語法錯誤來做測試,

因此,常見的輸入值就是

因為這個很多 database 的保留字,舉例來說:

通常網站會有選單,當使用者選到法國,網站就會傳回該法國人口的數量,資料庫後端就會執行這樣的語法,

SELECT population

FROM world

WHERE name = ‘France’

回傳為:65350000

但是如果輸入值加入 ‘ 讓SQL 語法就會變成:

SELECT population

FROM world

WHERE name = ‘France’

多了一個’ 就會造成 SQL Syntax error ,

SQL Server 錯誤

[Microsoft][ODBC SQL Server Driver][SQL Server]Unclosed quotation mark after the character string ‘France”. (SQL-42000) [err was 1 now 1] [state was 42000 now 42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near ‘France”. (SQL-42000) [err was 1 now 1] [state was 42000 now 42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Statement(s) could not be prepared. (SQL-42000)

MySQL 的錯誤

You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ”France”’ at line 2

為什麼這樣的錯誤會造成 SQL injection 呢?

因為我們知道原來輸入的值,在這個例子中:

  • France
  • France’

最後這些值會變成整個SQL Query 語法的一部分讓 SQL 執行

因此,接下來就可以把 ‘ 變成更複雜的查詢語句,達到其他特定目的。

 

跳過過濾條件 or 1 = 1 —

剛剛的例子中,我們查詢法國的人口數,

那要如何得知所有國家的人口數呢?

如果網站的控管沒有做好,透過 SQL injection 的語法就會變成

SELECT population

FROM world

WHERE name = ‘France’ or 1 = 1 —

透過 or 1 = 1 — 的輸入會造成 SQL 語句中的 Where 條件整個失效

因此,將所有國家的人口數列出。

(註: —  主要在 MS SQL Server 中為註解,將 — 後面的所有語句都變成註解)

 

跳過登入驗證

如果這樣的例子應用在登入驗證,原本的SQL 語句為

使用者名稱輸入 Lily

密碼輸入 secret

SELECT *

FROM users

WHERE username = ‘Lily’ and password = ‘secret’

 

變成

使用者名稱輸入Lily’ or 1 = 1 —

密碼輸入 secret

該輸入傳到後端資料庫執行,就會變成如下

SELECT *

FROM users

WHERE username = ‘Lily’ or 1 = 1 — ‘ and password = ‘secret’

因為 — 之後所有的語句都是註解,加上 1= 1的緣故,

造成整個 SQL 語法Where 的條件永遠為真,不管 password 是否輸入正確。

 

SQL Injection 簡單測試

因此,對於該網站是否有 SQL injection 可以用幾個簡單的測試,

看看是否有相關的 SQL syntax 回傳

  • Oracle: ‘||’test
  • MS-SQL: ‘+’test
  • MySQL: ‘    ‘test

 

網站保護

如何避免 SQL injection 呢? 通常要由程式的寫法著手

主要有三種方式

 

1.Prepared statement

每種程式語言都會提供類似的方式,將使用者輸入當作參數處理,而非直接組成一整個 SQL query 語句

  • Java EE – PreparedStatement() with bind variables
  • .NET – SqlCommand() or OleDbCommand() with bind variables
  • PHP – bindParam()

 

2.Stored Procedure

利用事先定義好的 Stored procedure來執行,

Stored Procedure 與 Prepared statement

主要的差異在於Stored procedure 是事先定義好的 SQL 程式存放在資料庫中。

這兩個方式都可以避免 SQL injection 的發生。

 

3.Validate User input

使用者資料輸入的驗證與編碼。這種方法無法完全避免 SQL injection。

主要是針對上線很久的程式,

短時間又無法改為 Stored procedure 或是 prepared statement的寫法的時候

就必須針對輸入的參數做一定的檢查與編碼,避免變成 SQL 語句執行。

 

 

網站安全

這篇文章主要介紹 SQL injection 的基本原理

線上 SQL database 測試的雲端服務

SQL injection 形成原因與如何測試

最後說明三種由程式保護SQL Injection 的方法

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *