歡迎光臨
每天分享高質量文章

黑客三兄弟(續)

來自:碼農翻身(微信號:coderising)

還不認識黑客三兄弟的可以移步上一篇文章《黑客三兄弟》,三分鐘就可以混個臉熟。

上次說到三兄弟用XSS和CSRF這兩個工具獲利頗豐,後來人們在編程中很註意防範,這兩個漏洞越來越少了,逼得三兄弟不得不開闢新財路。

1
另闢蹊徑

老二給大家提了一個建議:“要不我們試一試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資料都給提取出來了!” 老三驚嘆。

2
牛刀小試

老二笑道:“三弟,原理很簡單吧,但是想用好可不容易,你再試試這個網站: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的老大笑了: 咱們做黑客的,得有無比的耐心,還得充分發揮想象力才行啊。

3
瘋狂註入SQL

老二說:“大哥說得非常對, 我們換一個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出的資料中至少有兩列(標題和內容),現在我們註入資料,形成一個這樣的sql 出來:

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

4
破解密碼

“二哥,二哥,看到用戶名和密碼了,著名的張大胖(zhangdapang)的密碼也暴露了!” 老三忍不住再次歡呼, 老大回過頭來就是一巴掌。

“可是,這密碼不是明文的啊!看看這亂七八糟的字符。” 老三挨了一巴掌後清醒了一點。

“當然了,現在的資料庫基本上都不會存明文的密碼了,2012年CSDN的資料庫被黑客曝光,大家震驚地發現,密碼都是明文儲存的,由於很多人在多個網站都用同樣的密碼,明文密碼的暴露一下子讓很多網站都面臨攻擊的威脅。”

“那這些密碼是加密的嗎? ”

“是通過Hash的演算法計算出來的。”

“這個Hash值會儲存到資料庫當中,等到你下次登錄,輸入用戶名和密碼的時候,就會再次對密碼進行同樣的hash計算,然後和資料庫的值比較,看看是不是相同。” 老二補充道。

“這個hash 我知道,是不可逆的運算,所以即使被偷取了,也無法得到明文密碼。二哥,我們折騰了半天,難道白忙活了嗎?”

“不不,有幾種辦法可以去破解密碼,一種就是猜測,比如我準備了很多人們最常用的密碼,然後把這些密碼也做hash操作,和資料庫密碼對比,如果匹配,我就知道明文密碼了。

還有一種就是查表,我事先把明文密碼和計算好的hash值形成一個對照表,然後用資料庫中密碼的hash值去對照表中查找,如果找到了,明文密碼也就有了。當然為了提高效率,人們還製作了所謂彩虹表。”

(一個明文密碼和Hash值的對照表)

“二哥你趕快查一下啊, 我真是想知道著名的張大胖(zhangdapang)的密碼是多少!”

老二在電腦前面敲了半天,沮喪地說:“看來不好查,這個密碼應該是加鹽(salt)了。”

“加鹽?”

“對,他們給每個密碼都加了一了隨機數,然後再做Hash操作。 這樣一來,通過查找的方式就難於破解了!”

沒想到老三神秘地一笑:“二哥,沒那麼麻煩,我現在已經用管理員賬號(admin)登錄後臺了!”

“啊?!你怎麼做到的?”老三極度震驚。

“很簡單,剛纔我試了下登錄的功能,發現也有SQL註入漏洞,那個SQL可能是這樣子的:

select xx from ep_users where user=‘ and pwd=’

然後代碼會判斷這個sql 傳回的結果集數目是否為0, 如果不為0就認為登錄成功。

那我通過註入把它改寫成:

select xxx from ep_users where user=’admin‘ and password=’password’ OR ‘1’=’1

然後我就立刻就登錄了,由於用戶名是admin,現在我已經有了管理員權限了!可以為所欲為了。”

老三有點尷尬:我忙活了半天,還不如這小子找的一個漏洞。

5
後記

本文描述了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、資料庫、運維等。

赞(0)

分享創造快樂