來自:碼農翻身(微訊號:coderising)
上次說到三兄弟用XSS和CSRF這兩個工具獲利頗豐,後來人們在程式設計中很註意防範,這兩個漏洞越來越少了,逼得三兄弟不得不開闢新財路。
老二給大家提了一個建議:“要不我們試一試SQL註入?”
老大說:“老掉牙的東西了,1998年都有了,估計漏洞也沒幾個了吧?”
“那不一定啊,反正我們要節源開流,我最近找了一個網站,可以讓老三來練練手。”
老三一聽又可以學到新東西了,非常興奮:“二哥,你先給我說說什麼是SQL註入。”
“原理非常簡單,比如網站有個users表格,資料如下:”
“這個網站有個功能,根據id來檢視使用者資訊,http://xxxx.com/user?id=xxxx, 對應的SQL可能是這樣的:”
string sql =”SELECT id , name, age from users WHERE id=“+
如果使用者在瀏覽器的URL 是 http://xxxx.com/user?id=1,那真正執行的SQL就是這樣:SELECT id , name, age from users WHERE id=1
就會把張大胖對應的那條記錄給取出來了。
老三說:“這沒什麼啊,程式不都是這麼寫的嗎?”
老二說:“作為駭客,如果遇到了這種情況,那可是個好機會啊,你想想,如果我輸入了 http://xxxx.com/user?id=1 or 1=1 會發生什麼狀況?”
老三把id的值代入到sql中,有趣的事情發生了,sql變成了這樣:
SELECT id , name, age from users WHERE id=1 or 1=1
“哇塞,這是哪個天才想出來的註意啊,or 1=1 會讓where字句的值一直是true, 那豈不把所有的user資料都給提取出來了!” 老三驚嘆。
老二笑道:“三弟,原理很簡單吧,但是想用好可不容易,你再試試這個網站:www.badblog.com/viewblog?id=U123,這個URL能顯示ID為U123的部落格摘要。
老三迫不及待地把url 改為 www.badblog.com/viewblog?id=U123 or 1=1 , 心想最終的sql 就是: SELECT xxx FROM xxx WHERE id =U123 or 1=1 ,他興奮地等待所有的部落格摘要顯示出來。
可是,瀏覽器只是提示:“無效的部落格ID”
這是怎麼回事? 輪到我怎麼不行了呢?老三撓了撓頭。
老二解釋道:其實吧,你沒有註意到,那個id不是一個數字,是一個字串(“U123”),背後的SQL可能是這樣的:
string sql = “SELECT xxx FROM xxx WHERE id=‘” +
字串的話需要用單引號括起來,所以URL應該這麼寫:www.badblog.com/viewblog?id=U123′ or ‘1’=’1
這樣才能生成有效的SQL:SELECT xxx FROM xxx WHERE id =’U123′ or ‘1’=’1′
“奧,原來是這樣,看來拼接字串也真的不容易啊!” 老三趕緊繼續試驗。
可是瀏覽器還是沒有把所有部落格都顯示出來,還是隻顯示了一條, 但不是U123對應的那條部落格。
老三想了想說:“二哥,是不是SQL執行成功了,但是內部的程式永遠只傳回SQL結果集的第一行啊。”
“應該是這樣。”
“那這所謂的SQL註入也沒啥用處啊。 ”
在一旁忙活XSS的老大笑了: 咱們做駭客的,得有無比的耐心,還得充分發揮想象力才行啊。
老二說:“大哥說得非常對, 我們換一個URL www.badblog.com/news?id=3,我實驗過,這個URL也有SQL註入漏洞,並且如果我輸入id=3 or 1=1 , 就會把資料庫中所有的新聞給顯示出來。”
“現在我們利用這個漏洞: 努力把這個網站的使用者名稱和密碼給挖出來。”
老三瞪大了眼睛,似乎有點不相信:“不登入它的伺服器,僅僅透過瀏覽器就可以嗎?”
“是可以滴,但也要看看我們運氣如何,我們假設這個網站是個Mysql資料庫,接下來你得懂一點Mysql 資料庫知識了。我們分三步走,首先獲取這個資料庫的庫名,然後獲取所有的表名,最後找到使用者表,從中select 資料。”
“我似乎有點明白了,就是不斷地往那個URL註入SQL陳述句,對吧?”
“對的,第一步,我們已經能猜出那個URL對應的SQL是:SELECT xxx FROM xxx WHERE xx=
SELECT xxx FROM xxx WHERE xx=3 union select 1,2,3,4,5,6,7,8 , 你猜猜為什麼要這麼做?”
“這難不倒我,union 要求兩個結果集的列必須個數相同,現在你在union的第二部分輸入了8個column ,就是猜測union的第一個字句也有8 個column, 對不對?”
老二說:“沒錯,孺子可教,如果這個SQL執行不正常(介面會有錯誤), 我們就再嘗試,增加或減少列,直到成功為止。”
老三試了幾次,等到列數為3的時候,SELECT xxx FROM xxx WHERE xx=3 union select 1,2,3
瀏覽器頁面突然顯示了出了兩條新聞, 一條有正常的標題和內容, 另外一條的標題是2, 內容是3, 正是老三構造出來的。
老三說:“理解了, 關鍵點是第二列和第三列的值會被顯示到瀏覽器的介面中,接下來我們可以這麼做:SELECT xxx FROM xxx WHERE xx=3 union select 1,2,database() ”
於是就獲得了資料庫的名稱: epdb
老二心想,三弟悟性確實不錯啊,資料庫也扎實。他說:“那我問你,你怎麼才能獲得這個資料庫的所有表的名稱?”
“這難不倒我,mysql 中 information_schema.tables 這個表儲存著所有的表名,現在知道了資料庫的名稱,只需要把資料庫名稱傳遞過去就行了”
SELECT xxx FROM xxx WHERE xx=3 union select 1,2,table_name from information_schema.tables where table_schema=’epdb’
果然,epdb這個資料庫所有的表都取出來了:
老三指著ep_users 大叫,“二哥,使用者表肯定就是這個了!”
老大扭過頭來:“小點聲,老子正處於XSS的緊要關頭。”
老二說:“接下來你知道怎麼辦了吧?”
老三點點頭,又構造出一個sql ,把ep_users的列名全取出來:
SELECT xxx FROM xxx WHERE xx=3 union select 1,2,column_name from information_schema.columns where table_name=’ep_users’
看來這個ep_users有這麼幾個column : id ,name, pwd。
再接再厲,把ep_users表的資料給選出來:
SELECT xxx FROM xxx WHERE xx=3 union select 1,name,pwd from ep_users
“二哥,二哥,看到使用者名稱和密碼了,著名的張大胖(zhangdapang)的密碼也暴露了!” 老三忍不住再次歡呼, 老大回過頭來就是一巴掌。
“可是,這密碼不是明文的啊!看看這亂七八糟的字元。” 老三捱了一巴掌後清醒了一點。
“當然了,現在的資料庫基本上都不會存明文的密碼了,2012年CSDN的資料庫被駭客曝光,大家震驚地發現,密碼都是明文儲存的,由於很多人在多個網站都用同樣的密碼,明文密碼的暴露一下子讓很多網站都面臨攻擊的威脅。”
“那這些密碼是加密的嗎? ”
“是透過Hash的演演算法計算出來的。”
“這個Hash值會儲存到資料庫當中,等到你下次登入,輸入使用者名稱和密碼的時候,就會再次對密碼進行同樣的hash計算,然後和資料庫的值比較,看看是不是相同。” 老二補充道。
“這個hash 我知道,是不可逆的運算,所以即使被偷取了,也無法得到明文密碼。二哥,我們折騰了半天,難道白忙活了嗎?”
“不不,有幾種辦法可以去破解密碼,一種就是猜測,比如我準備了很多人們最常用的密碼,然後把這些密碼也做hash操作,和資料庫密碼對比,如果匹配,我就知道明文密碼了。
還有一種就是查表,我事先把明文密碼和計算好的hash值形成一個對照表,然後用資料庫中密碼的hash值去對照表中查詢,如果找到了,明文密碼也就有了。當然為了提高效率,人們還製作了所謂彩虹表。”
(一個明文密碼和Hash值的對照表)
“二哥你趕快查一下啊, 我真是想知道著名的張大胖(zhangdapang)的密碼是多少!”
老二在電腦前面敲了半天,沮喪地說:“看來不好查,這個密碼應該是加鹽(salt)了。”
“加鹽?”
“對,他們給每個密碼都加了一了隨機數,然後再做Hash操作。 這樣一來,透過查詢的方式就難於破解了!”
沒想到老三神秘地一笑:“二哥,沒那麼麻煩,我現在已經用管理員賬號(admin)登入後臺了!”
“啊?!你怎麼做到的?”老三極度震驚。
“很簡單,剛才我試了下登入的功能,發現也有SQL註入漏洞,那個SQL可能是這樣子的:
select xx from ep_users where user=‘
然後程式碼會判斷這個sql 傳回的結果集數目是否為0, 如果不為0就認為登入成功。
那我透過註入把它改寫成:
select xxx from ep_users where user=’admin‘ and password=’password’ OR ‘1’=’1‘
然後我就立刻就登入了,由於使用者名稱是admin,現在我已經有了管理員許可權了!可以為所欲為了。”
老三有點尷尬:我忙活了半天,還不如這小子找的一個漏洞。
本文描述了SQL註入的原理,實際上SQL註入漏洞的危害非常巨大,因為駭客可以利用漏洞去執行資料庫中很多函式(mysql的LOAD_FILE, SELECT INTOFILE),儲存過程(例如臭名卓著的xp_cmdshell), 可以向伺服器植入程式碼。 如果有資料庫賬號適當許可權,還可以建立表,刪除表,非常可怕。
防禦SQL註入的最佳方式,就是不要拼接字串, 而要使用預編譯陳述句,系結變數,不管你輸入了什麼內容,預編譯陳述句只會把它當成資料的一部分。
String sql = “select id from users where name=?”;
PreparedStatement pstmt = conn.prepareSatement(sql);
pstmt.setStrig(1,request.getParameter(“name”);
pstmt.executeQuery();
推薦閱讀:
●本文編號534,以後想閱讀這篇文章直接輸入534即可
●輸入m獲取文章目錄
Python程式設計
更多推薦《18個技術類微信公眾號》
涵蓋:程式人生、演演算法與資料結構、駭客技術與網路安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。