今天我們進到SQL Injection的課程,相信大家或多或少都有聽過他的大名,那到底什麼是SQL Injection呢?
首先,SQL是一種跟資料庫進行溝通的語法,不論是要向資料庫查詢或插入資料,都需要仰賴SQL式才能讓資料庫了解你現在想做的是什麼。每個資料庫對應的SQL語法可能不盡相同,但主要的功能卻是大同小異的,如下三種。
可以對資料庫中的資料進行存取及修改等行為,包含查詢 (SELECT)、插入 (INSERT)、更新 (UPDATE)及刪除 (SELETE)等。
可以定義或修改資料庫結構及物件,包含建立 (CREATE)、修改 (ALTER)、刪除 (DROP)及清空 (TRUNCATE)等。
可以用來對資料存取權進行控制,例如可以控制特定使用者帳戶對資料表、檢視表、預存程式、使用者自訂函式等資料庫物件的控制權限,包含新增權限 (GRANT)及移除權限 (REVOKE)。
而SQL Injection就是利用程式的漏洞,利用SQL執行的錯誤語法,或是猜測資料庫結構或欄位名稱等,幫原本要執行的SQL語法加料,進而造成資料庫執行到被加料的SQL語法,並造成非預期的結果,像是資料被修改、外洩及刪除等,也有可能整個資料庫被刪除或多新增幾個帳號等,總之只要是SQL語法能做到的事情都有可能因此被執行。
那這樣的漏洞到底是怎樣發生的呢?
假設今天我要用PHP寫網頁,在我的網頁上有一個欄位可以讓使用者輸入訂單編號並查詢訂單進度,所以我把程式碼寫成這樣:
$query = "select * from order where order_id = '".$orderID."'";
$result = $conn->query($sql);
如果我沒有限制使用者輸入的字串,一般正常使用的使用者若是輸入了訂單編號,資料庫接收到的SQL式如下,並會吐出對應的查詢結果。
select * from order where order_id = '訂單編號';
但如果今天使用者不乖,在網頁的查詢欄位輸入了「' or 1='1」,資料庫接收到的SQL式如下,並會吐出該資料表中的所有資料。
select * from order where order_id = '' or 1='1';
如果使用者只是列出所有資料倒也還好,但如果他在欄位中輸入「'; DROP TABLE 'order」,資料庫接收到的SQL式如下,並會把order這個資料表直接給刪掉,是不是非常的刺激啊。
select * from order where order_id = ''; DROP TABLE 'order';
接著來看WebGoat的練習吧,在WebGoat中,他們把SQL Injection分為兩種類型,分別是字串型跟數字型,接下來我們就直接透過練習來介紹這兩種的差別吧。
第7步是練習字串型的Injection,在這邊他們很好心,已經把SQL語法長怎樣直接告訴我們了,也就是「"select * from users where LAST_NAME = '" + userName + "'";」,我們只需要想辦法讓資料庫把資料都吐出來就好,
這一題也很簡單,我們只要運用剛剛的說明,想辦法把SQL式改為「"select * from users where LAST_NAME = '' or 1 = '1'";」就可以了,所以我們在欄位中輸入「' or 1='1」就可以通過這一題囉。
接著進到第8步,也就是數字型Injection的部分,而題目也一樣有把SQL寫出來給我們看,也就是「"select * from users where USERID = " + userID;」,而我們一樣要想辦法讓資料庫把資料表的所有資料吐出來。跟字串型不一樣的是,在這邊的SQL式中,參數值的前後並沒有用單引號括起來。
我先輸入個單引號試試看,發現出現了錯誤訊息,原來這一個欄位會把單引號過濾掉。
輸入空白鍵會出現SQL式語法結尾錯誤的訊息。
直接來試試看上一題的解法,我們要想辦法把SQL式變成「"select * from users where USERID = '' or 1='1';」,接著我們就在欄位中輸入「'' or 1 = '1'」,但卻發現一樣出現了錯誤訊息無法成功過關,而這個錯誤訊息代表的意思是你在一個只接受數字的欄位中輸入了字串。
既然知道了這個欄位只接受數字,因此我們把目標SQL語法改為「"select * from users where USERID =任意數字 or 1=1;」,所以我們就在欄位中輸入「123 or 1=1」,並且成功解開這一題。
而這就是字串型及數字型Injection不同的地方啦~
以上就是基礎SQL Injection的介紹,明天會再介紹更進階的技巧喔。
參考資料:
[1] https://zh.wikipedia.org/wiki/%E8%B3%87%E6%96%99%E5%AE%9A%E7%BE%A9%E8%AA%9E%E8%A8%80
[2] https://zh.wikipedia.org/wiki/%E8%B3%87%E6%96%99%E6%93%8D%E7%B8%B1%E8%AA%9E%E8%A8%80
[3] https://zh.wikipedia.org/wiki/%E8%B3%87%E6%96%99%E6%8E%A7%E5%88%B6%E8%AA%9E%E8%A8%80