今天來繼續下一個課程吧,也就是進階版的SQL Injection技巧,而要使用這些進階版的技巧,就必須要自己本身也熟悉SQL式的使用技巧,如此一來才能活動這項邪惡的技術。
首先介紹在SQL語法中註解的用法:
/* */:只要在「/*」和「*/」間的文字都會當作註解,支援多行文字。
-- :只要在單行中加入「-- 」,空白以後的文字都會被當作註解,支援單行文字。
#:只要在單行中加入「#」,以後的文字都會被當作註解,支援單行文字。
那我們要怎麼運用註解符號呢?假設今天我用PHP寫個一個簡單的登入判斷SQL語法像這樣:
$query = "select * from member where member_id = '".$memberID."' and password = '".$password."';”;
$result = $conn->query($sql);
乍看之下很正常,把帳號跟密碼跟資料庫進行比對,如果相符的話就列出會員資訊,但如果這時候傳進memberID變數的值是「admin' -- 」,那SQL式就會變成:
select * from member where member_id = 'admin' -- ' and password = 'pass';
既然「-- 」後的字會被註解掉,也就代表實際執行時,這個SQL式會變成下述式子,所以我們不用知道密碼就可以把admin這個使用者的資料撈出來了。
select * from member where member_id = 'admin';
也就是說,只要利用註解的方式,我們就可以在「'」及「-- 」之間插入任何我們想要執行的SQL語法。
另外像是「;」在SQL語法中代表的是語句結束的意思;「'」、「+」、「||」在SQL語法中有串接字串的功能;「char()」在SQL語法中,則可以把括號中數字轉為該數字在ASCII碼中代表的字母;「union」可以允許你把將兩個 SQL 語句的結果合併起來,但他有一個限制是兩個 SQL 語句所產生的欄位需要是同樣的資料種類。上述這些都是可以拿來活用進行SQL Injection的字串,當然還有很多其他的SQL功能可以拿來利用,但那就要看個人的經驗累積囉。
在這邊就以WebGoat的範例來介紹兩個例子吧,首先是第3步的挑戰。
這一題裡有兩小題,第一小題中我們必須要先列出所有人的資料,我們先試著輸入跟昨天一樣的解法「' or 1='1」發現就成功把所有資料列出來了,當然也可以試著用今天新學到的「' or 1=1 -- 」,一樣可以成功達到目的。
第二小題中我們接著利用union的方式把一張額外的資料表顯示出來,接著再從這張表裡找到Dave的密碼。記得看一下題目上面有提示我們這個資料庫裡還有另一個叫做「user_system_data」的資料表,而裡面有一個欄位叫做password,很明顯的我們要的答案就在這個欄位裡。
因為union的特性就是上下兩個 SQL 語句所產生的欄位需要是同樣的資料種類,因此我們先觀察剛剛查詢出來的欄位,發現有7個欄位,所以我們接下來要寫在union後的SQL式也必須要列出7個欄位,但因為我們已經知道user_system_data這個資料表只有4個欄位,所以剩下的3個欄位就隨我們亂塞東西進去吧,只要跟第一張表格的「CC_TYPE」、「COOKIE」及「LOGIN_COUNT」欄位資料種類是一樣的就可以了,所以我們就可以得出下面的SQL語句,並得到Dave的密碼。
' union select userid,user_name,password,cookie, 'hello','bye',1 from user_system_data --
小提醒,因為WebGoat是給我們練習的,所以把密碼欄位的字直接顯示給我們看,但實際上外面網頁的密碼都會都會是把字串隱藏起來的,建議可以透過先在記事本打好再複製過來,或是利用瀏覽器的開發者工具把字串直接填入HTML裡。
有沒有覺得SQL Injection就是一個填字遊戲啊,但實際上要猜到系統原始使用的SQL式是什麼也不一定是件容易的事就是~