程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> SQL注入攻擊(1)

SQL注入攻擊(1)

編輯:MySQL綜合教程

一個客戶對我們請求說,請我們來檢查一下他的內部網絡,這個網絡被公司的職員以及客戶們來使用。這是一個較大的安全評估的一部分,而且,雖然我們以前從沒 有真正的使用過SQL注入來破解一個網絡,但是我們對於其一般的概念相當的熟悉。在此次“戰斗”中,我們是完全成功的,而且想要通過把這個過程的每一個步驟重新記錄下來,並作為一個“生動的例子”。

“SQL注入”是特定的一種未被確認或未明確身份的用戶輸入漏洞的一個子集“緩沖溢出”是一個不同的子集),而這個想法的目標是,讓應用程序確信從而去 運行SQL代碼,而這些代碼並不在其目的之內。如果一個應用程序是在本地通過即時的方式來創建一個SQL字符串,結果很直接,會造成一些真正的出人意料的結果。

我們要明確說明的是,這是一個有些曲折的過程,並且其中會有多次的錯誤的轉折,而其余的更有經驗的人當然會有著不同的-甚至更好的-方法。而事實上,我們成功的實現了建議,並沒有被完全的誤導。

還有一些不同的論文討論SQL注入問題,包括一些更加詳細的文章,不過此文所展示的,與破解的過程同樣份量的是發現了SQL注入的原因。

目標內網

這顯然是一個完全自主開發的應用程序,而我們對於它沒有預先的了解,或者訪問源代碼的權限:這已是一個“blind”攻擊。若干次偵測之後,我們了解到服 務器運行的是微軟的IIS6,並使用ASP.NET框架,從這其中得到的,似乎可以假定數據庫是微軟的SQL服務器:我們相信這些技術可以應用於幾乎任何 一種web應用,而此應用可能為任何一種SQL服務器所支持。

登陸頁面是一個傳統的用戶名-密碼表單,帶有一個用電子郵件給我傳送密碼的鏈接;而後者被證實是整個系統的敗筆。

當輸入一個電子郵件地址的時候,系統會假定次郵件存在的方式,再用戶數據庫裡面尋找這個電子郵件地址,並且會郵寄一些內容到這個地址。由於我的電子郵件地址沒有被找到,所以它不會給我發送任何內容。

所以,第一個測試,對於任何SQL化的表單而言,是輸入一個帶有單引號構成的數據:這樣做的目標是查看是否他們在構建SQL字符串的時候根本沒有使用數據 的清理機制。當為此表單提交了一個有單引號的電子郵件之後,我們得到了一個500錯誤服務器失敗),這就是說,這個“被破壞了的”的輸入實際上被真實的 分析過。中!

我們猜測底層的SQL代碼可能類似於如此:

  1. SELECT fieldlist FROM table WHERE field = '$EMAIL'; 

這裡,$EMAIL是由用戶通過表單提交的電子郵件地址,而這段較長的查詢提供的應用符號,是為了使得這個$EMAIL成為一個真正的字符串。我們不知道 這個數據域的確切的名字或者是於此相關的數據表的名字,但是我們卻了解他們的特性,而此後我們將會得到一些很好的猜測結果。

當我們輸入[email protected]' - 留意那個結尾的引號 - 這將產生出一個如下構建的SQL:

  1. SELECT fieldlist FROM table WHERE field = '[email protected]''; 

當這個SQL被執行的時候,SQL分析器發現了多余的引號,從而中止了工作,並給出一個語法錯誤。而這個錯誤如何表述給用戶,取決於應用程序內部錯誤修復 的過程,但是這通常不同於“電子郵件地址不存在”的錯誤提示。這個錯誤的響應是致命的第一通道,既用戶的輸入沒有被正確的清理,而因此應用程序成為了破解 的美食。

由於我們輸入的數據顯然位於WHERE子語句中,讓我們用合法的SQL方式改變一下這個子句的本貌並看看會發生什麼。通過輸入任何一種‘OR ’x‘=x語句,結果SQL成為:

  1. SELECT fieldlist FROM table WHERE field = 'anything' OR 'x'='x'; 

因為應用程序沒有真正的對這樣的查詢有所考慮,而僅僅是構建一個字符串,以致於我們使用的引號使得一個單元素的WHERE子句,變成了一個雙元素的子句, 而且’x'=x字句是確定為真的,無論第一個字句是什麼。有一種更好的方式來確保“始終為真”,這部分我們後面會談及)

不過與“真實”的查詢不同,本應當一次返回一個單獨的項,這個版本必然會返回成員數據庫裡面的每一個項。唯一的可以發現應用程序在這種情況下會做什麼的方式,就是嘗試。不斷嘗試,我們留意到以下結果:

你的登錄信息已經發送到 [email protected].

我們一般都會把查詢返回的第一行作為作為猜測的主要入口。這哥們確實從E-mail裡拿回了他的密碼,同樣這個郵件可能會讓他感到吃驚並且會引起懷疑。

現在我們知道怎麼在本地玩這條查詢了,雖然目前我們還不知道我們看不到的那部分SQL結構是怎麼拼起來的。但是我們通過逆向工程看到了三個不同的查詢結果:

  • 您的登陸信息已經以Email形式發送給您
  • 我們無法識別您的Email地址
  • 服務端錯誤

頭兩個響應是有效的查詢的結果,最後一個是無效SQL造成的。 類似這樣的響應結果會幫助我們更好的逆推服務端用來查詢的SQL語句結構。

預設字段映射

我們要干的第一步就是猜字段名,首先我們合理的推測查詢帶了“email address” 和 “password”,所以可能的字段名選擇會有“US Mail Address”  或者 “userid” 亦或者“phone number”  。當然最好能執行 show table,但是我們又不知道表名,貌似目前沒什麼明顯的方法能讓我們拿到表名。

那就分步走吧。在每個例子裡,我們會用我們已知的SQL加上我們自己的特殊“段”。我們已知的這條SQL的結尾是個Email地址的比對,那就猜下email是這個字段名吧

  1. SELECT fieldlist FROM table WHERE field = 'x' AND email IS NULL; --'; 

如果服務器響應是報錯,那基本上可以說明我們的SQL拼錯了。但是如果我們得到任何正常的返回,例如“未知的郵件地址” 或 “密碼已發送”  ,說明我們的字段名蒙對了。

要注意的是,我們的“And” 關鍵字而沒用“OR” 關鍵字,這麼做是有目地滴。在上一步中,我們不關心到底是哪一個Email,而且我們不想因為蒙中某人的Email然後給他發了重置密碼的郵件。這麼搞那 哥們兒一定會懷疑有人對他的帳號搞三搞四。所以用“And”關鍵字拼上一個不合法的Email地址,這樣服務端總是返回空結果集,也就不會給任何人發郵 件。

提交上面的SQL代碼段確實返回了“未知的郵件地址” 這麼一個響應。現在我們確認了email地址的字段名是email。如果不是這麼個響應,那我就再蒙“email_adress”或者“mail”亦或者 其他類似的。這個環節總是靠蒙的,但是蒙也得講技巧和方法方式。

這段SQL的用意是我們假設預設的SQL查詢中的字段名是 email ,跑一下看看是不是有效。我不會管你到底有沒有匹配的Email,所以用了個偽名“x” , “--” 這個標示是表示SQL的起始。這樣SQL解析到這就會把它直接當成一條命令,而“--”後面的會是一個新的命令,這樣就屏蔽掉了後面的那些不知道的玩意 兒。

下一步,我們來猜下其他比較明顯的字段名: "password","userid","name" 和類似的。每次我們只蒙一個名字,當返回結果不是“服務端錯誤” , 那就說明我們蒙對了。

  1. SELECT fieldlist FROM table WHERE email = 'x' AND userid IS NULL; --'; 

通過這一步,我們蒙出來了下面幾個字段名:

  • email
  • passwd
  • login_id
  • full_name

肯定還有更多其他的把HTML頁面表單的 <Input   name="XXXXX"> 拿來做參考是個非常不錯的選擇)後來我又挖了一下但是沒挖出來更多的字段名。 到目前為止,我們還是不知道這些字段所屬的表的表名--咋個弄呢?


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved