自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

小心你的WEB應用程序成為數(shù)據(jù)竊賊的幫兇

安全
當心,你以為固若金湯的數(shù)據(jù)庫可能已遭到了入侵。你需要重新思考一下自己公司的網(wǎng)站是否真得不會遭到SQL注入攻擊。本文將闡述攻擊者如何通過這種方法來利用Web應用程序的漏洞。有時,即使攻擊者也不了解自己正在利用的漏洞的性質。

當心,你以為固若金湯的數(shù)據(jù)庫可能已遭到了入侵。你需要重新思考一下自己公司的網(wǎng)站是否真得不會遭到SQL注入攻擊。SQL注入是最流行也是最危險的Web應用程序漏洞利用技術,它可以攻擊存儲著珍貴企業(yè)信息的后端數(shù)據(jù)庫,且“簡約高效”。

本文將闡述攻擊者如何通過這種方法來利用Web應用程序的漏洞。有時,即使攻擊者也不了解自己正在利用的漏洞的性質。

何為SQL注入

就其最基本的意義來說,SQL注入只不過是操縱一個已有的SQL查詢,執(zhí)行一個并非開發(fā)人員意圖的動作。這種動作通常是通過Web應用程序的用戶界面完成的。

但這種攻擊是如何進行的?它為什么屢屢得逞?

Web應用程序和數(shù)據(jù)庫之間的正常交互

所有的SQL注入漏洞都是由某些未經(jīng)驗證的用戶輸入開始的。用戶輸入可以采取多種形式,它可以包括一個攻擊者操縱的由服務器處理的任何東西,例如:用戶代理、HTTP報頭、POST參數(shù)、cookies、GET參數(shù),甚至網(wǎng)址標頭等。是什么令未經(jīng)驗證的用戶輸入如此特殊呢?答案是:應用程序并沒有對其進行充分的檢查,從而不能確保所收到的輸入就是所期望的類型和方式。例如,雖然你的應用程序的編制目的是為了接收可以包括字母、數(shù)字的字符串作為用戶名,但此程序并沒有驗證輸入,從而使得黑客可以插入SQL注入的數(shù)據(jù)庫查詢:

比如,一個典型的網(wǎng)站會要求你的用戶名,并希望這個結果是“Zhangsan”:

Wangzhan.com/usertetail.asp?username=Zhangsan

在這個例子中,有可能會發(fā)生這樣的情況:某個查詢促使網(wǎng)站在后臺與數(shù)據(jù)庫交互,從而獲取關于用戶(如,Zhangsan)的信息:

SELECT uname,fname,lname,phone,street,city,state,zip FROM users WHERE user =$var_username

當Web應用程序代碼處理這個請求時,為了完成查詢,來自用戶名的值(Zhangsan)被傳遞給$var_username。服務器應當將SQL查詢的結果變成標準格式,并顯示此結果以便于用戶查看Zhangsan的細節(jié)。#p#

攻擊者尋找突破口

首先,攻擊者可能查看應用程序是否能夠正確地處理錯誤條件。有許多方法可以檢查SQL錯誤消息,每一個方法都依賴于數(shù)據(jù)庫自身。最常見的例子是“‘”( 撇號)。攻擊者可能會嘗試插入“‘”而不是一個合法的用戶名:

Wangzhan.com/userdetail.asp?username=‘

如果出現(xiàn)錯誤,攻擊者就可以了解一些信息。例如,下面的錯誤就會使攻擊者知道這是一個MySQL數(shù)據(jù)庫,而且表明數(shù)據(jù)庫將“‘”解釋為查詢的一部分,從而揭示出這可能是一個SQL注入點,值得進一步調查。

錯誤:您的SQL語法有一個錯誤,請檢查您的MySQL服務器版本對應的手冊,查看正確的語法…在第4行

在此例中,我們使用了一個“‘”,但任何“保留”字符,即在測試數(shù)據(jù)庫錯誤時可以使用的為特別目的而保留的一個字符。保留字符對每種數(shù)據(jù)庫類型來說都是獨一無二的。

借助上面顯示的MySQL錯誤消息,我們可以看出黑客是多么聰明,而且能夠發(fā)現(xiàn)應用程序正在訪問的數(shù)據(jù)庫表的其它細節(jié)。請看:

Wangzhan.com/userdetail.asp?username=Zhangsan order by 1

如果我們沒有收到錯誤,就可以知道用戶名要么是SQL WHERE語句中的最后一個變量(允許我們從一個數(shù)據(jù)庫表中重新獲取數(shù)據(jù),同時又排除其它的無關數(shù)據(jù)),或者是WHERE語句中的唯一變量。我們可以讓數(shù)字每次增加1,直至收到一個錯誤。例如,可能在到達“Zhangsan order by 9”,就可以看到:

錯誤:用戶警告:“order clause”查詢中有無法確認的列:SELECT

現(xiàn)在可以確認,直至提交了“9”,我們才收到了錯誤消息,所以可以斷定表中有8列。這個信息很有用,但我們只是想獲得盡量多的數(shù)據(jù)。假設沒有提供輸入驗證,通過在用戶名的位置使用一個通配符,我們實際上可以返回所有用戶的細節(jié):

Wangzhan.com/userdetail.asp?username=%

在該例中,我們將執(zhí)行下面的查詢,返回所有用戶的細節(jié):

SELECT uname,fname,lname,phone,street,city,state,zip FROM users WHERE user = %

如果攻擊使用此伎倆,勢必會造成數(shù)據(jù)損害,使大量的有價值的客戶信息處于風險之中。其中可能包括應當被加密的用戶口令,當然攻擊者可以在日后再進行破解。遭到泄露的客戶信息還有可能包括電子郵件地址,攻擊者可以將其用于釣魚攻擊。

其實,我們可以不用插入簡單的通配符,而是終止查詢,并讓查詢做一些查詢之外的事情:

Wangzhan.com/userdetail.asp?username=zhangsan;DROP users—

為便于比較,我們將SQL Server的數(shù)據(jù)庫語句列示如下:

SELECT uname,fname,lname,phone,street,city,state,zip FROM users WHERE user = ‘zhangsan’;DROP users—

還要注意,此例允許你在同一行上提交多個查詢(在此例中,即SELECT和DROP查詢)。其方法就是用分號(;)分開并用兩個破折號結束。因而,在完成最初的查詢后,攻擊者就可以發(fā)送并運行自己選擇的一個完整查詢。#p#

自動攻擊

攻擊者可以使用兩種主要的攻擊方法來利用SQL注入漏洞:自動攻擊和手動攻擊。從字面上看似乎很容易理解,但這兩種攻擊在機制上是非常不同的。自動攻擊一般是為特定目的而編制的一種工具所導致的結果。例如,有的攻擊使用大規(guī)模的注入攻擊,其目的是為了讓其攻擊范圍最大化并任意擴散其代碼。這種大規(guī)模的攻擊一般針對非常具體的應用程序架構,如運行ASP的IIS服務器等。而Asprox攻擊,其目的是為了將一個JavaScript或iframe標記注入到網(wǎng)頁中,從而傳播病毒。

自動SQL注入舉例

下面是一個高級SQL注入攻擊的例子,它能夠注入到某些字段類型中。很長一段時間以來,此類代碼可以有效的幫助攻擊者傳播病毒。

wangzhan.com/ssp.asp?username=zhangsan’;DECLARE @T VARCHAR  (255),@C VARCHAR(255) DECLARE TABLE_CURSOR CURSOR FOR SELECT   A.NAME,B.NAME FROM SYSOBJECTS A,SYSCOLUMNS B WHERE A.ID=B.ID AND   A.XTYPE=‘U’ AND (B.XTYPE=99 OR

B.XTYPE=35 OR B.XTYPE=231 OR B.XTYPE=167) OPEN TABLE_CURSOR FETCH   NEXT

FROM TABLE_CURSOR INTO @T,@C WHILE(@@FETCH_STATUS=0) BEGIN

EXEC(‘UPDATE [‘+@T+’] SET

[‘+@C+’]=RTRIM(CONVERT(VARCHAR(4000),[‘+@C+’]))+’<script   code>‘) FETCH NEXT FROM TABLE_CURSOR INTO @T,@C END CLOSE   TABLE_CURSOR DEALLOCATE TABLE_CURSOR;--

下面,我們簡單地看一下這段代碼是如何針對后端數(shù)據(jù)庫實施攻擊的。首先,攻擊者聲明了Table (T) 和 Column (C)這兩個變量。

DECLARE @T VARCHAR(255),@C VARCHAR(255)

并聲明了一個可以保存查詢結果的表cursor:

DECLARE TABLE_CURSOR CURSOR FOR

下面的SELECT語句通過“text”、“sysname”、“varchar”等列來檢索所有的用戶對象,并且將結果存儲在前面創(chuàng)建的CURSOR中。

SELECT A.NAME,B.NAME FROM SYSOBJECTS A,SYSCOLUMNS B WHERE A.ID=B.ID AND A.XTYPE=‘U’ AND (B.XTYPE=99 OR B.XTYPE=35 OR B.XTYPE=231 OR B.XTYPE=167)

在下面的代碼中,數(shù)據(jù)表CURSOR檢索結果,并將其分配給表和列變量:

OPEN TABLE_CURSOR FETCH NEXT FROM TABLE_CURSOR INTO @T,@C WHILE(@@FETCH_STATUS=0)

此時,攻擊者已經(jīng)檢索了數(shù)據(jù)庫中基于文本的這些列,其意圖是為了修改這些列的內(nèi)容。在這里,攻擊者雖然沒有篡改數(shù)據(jù),但已經(jīng)完成了所有必要的偵察。然后,執(zhí)行更新語句,將JavaScript置于列變量中的每一列中。攻擊完成后,包含Web內(nèi)容(這些內(nèi)容源自數(shù)據(jù)庫的任何字段)的任何網(wǎng)頁都會提交攻擊者的惡意JavaScript代碼。然后,該JavaScript用一個病毒感染W(wǎng)eb用戶的計算機:

WHILE(@@FETCH_STATUS=0) BEGIN EXEC(‘UPDATE [‘+@T+’] SET [‘+@C+’]=RTRIM(CONVERT(VARCHAR(4000),[‘+@C+’]))+’<script code>‘) FETCH NEXT FROM TABLE_CURSOR INTO @T,@C END

在注入的結尾,攻擊者執(zhí)行清理,覆蓋所有的攻擊痕跡:

CLOSE TABLE_CURSOR DEALLOCATE TABLE_CURSOR;--

這些攻擊是完全自動化的;黑客攻擊只需使用搜索引擎簡單地搜索互聯(lián)網(wǎng),查找運行經(jīng)典的ASP代碼的Web服務器即可。別再自欺欺人的相信“我的網(wǎng)站很小,誰會愿意攻擊它呢?”這種愚蠢的謊言。如果你正在通過互聯(lián)網(wǎng)做商務,不管企業(yè)大小,都易于遭到攻擊。#p#

接管

在很多情況下,攻擊者能夠完全控制SQL服務器的底層操作系統(tǒng);攻擊者甚至可以接管Web應用程序,并最終接管Web服務器。

接管數(shù)據(jù)庫服務器可以導致?lián)p害其它的應用程序,甚至損害DMZ中的其它服務器?,F(xiàn)代的Web應用程序架構一般都有數(shù)據(jù)庫集群,與其它系統(tǒng)共享數(shù)據(jù)存儲,或者位于網(wǎng)絡中不太安全的地方。如果攻擊者考慮到這個方面,他就可以使用前面提到的方法繞過防火墻中一般的IP源過濾規(guī)則,從而攻擊內(nèi)部網(wǎng)絡,甚至還可以使用SQL服務器來存儲病毒、黃色圖片或其它非法內(nèi)容。

此外,通過首先接管數(shù)據(jù)庫服務器,攻擊者可以篡改Web應用程序的行為。通常,這種行為包括借助Web服務器的服務賬戶在本地服務器上運行命令。如果服務賬戶有了被提升的特權,攻擊者就可以通過數(shù)據(jù)庫服務器,將命令直接發(fā)送給Web服務器的操作系統(tǒng)。

有時,數(shù)據(jù)是根據(jù)計劃例程從DMZ數(shù)據(jù)庫服務器析取出來的。如果通過公司Intranet(內(nèi)聯(lián)網(wǎng))中的Web接口來查看數(shù)據(jù),情況就更危險,因為多數(shù)內(nèi)聯(lián)網(wǎng)的Web應用程序在運行時,其信任等級更高。

不要小看盲目攻擊

通常,控制框架會把SQL錯誤搞得不易分辨,如Java或.NET框架。有時,這些錯誤是由錯誤處理代碼自動處理的,或者是由底層的代碼解釋程序處理的。例如,攻擊者可以使用撇號(‘)而不是合法的輸入:

wangzhan.com/userdetail.asp?username=‘

其結果為:用戶未找到。

這就告訴我們,Web應用程序正在正確地檢查用戶輸入,或者是程序框架正在阻止顯示明顯的錯誤消息。在這種情況下,執(zhí)行SQL注入就變得困難了,但并不是不可能。這就引出了下一種攻擊:盲目SQL注入。

盲目SQL注入攻擊是如何工作的呢?它要查看數(shù)據(jù)庫服務器是否真正地處理請求,或者查看該請求是否會觸發(fā)來自Web服務器或SQL服務器的其它響應。

例如,我們已經(jīng)看到了能夠向我們提供張三(Zhangsan)用戶細節(jié)的請求,能夠看出該攻擊是否成功。不過,“WAITFOR DELAY”命令要求SQL服務器在用查詢結果響應之前,先暫停一分鐘。

wangzhan.com/userdetail.asp?username=zhangsan;WAITFOR DELAY ‘0:1:0’—

如果網(wǎng)站能夠正確地處理用戶輸入,它應當返回一個消息,說明找不到用戶,或者發(fā)出其它的通知,說明“zhangsan;WAITFOR DELAY ‘0:1:0’--”不是一個合法用戶。

必須指出,只有在將用戶名變量的值被提交給SQL服務器時,并且Web應用程序能夠正確地處理用戶名變量的值時,才會出現(xiàn)這種情況。

傳統(tǒng)的SQL注入將會返回錯誤,讓用戶知道有關查詢失敗的原因的細節(jié)。從本質上講,盲目SQL注入依賴的是一種來自服務器的布爾邏輯響應(是/否,真/假等):查詢請求要么被處理,要么遭遇失敗。盲目SQL注入攻擊一旦得以發(fā)現(xiàn),它就會提供與典型的SQL注入一樣的功能,但它更難以執(zhí)行,為了獲取信息也需要更多的時間。#p#

讓盲目攻擊起作用

假設在示例頁面中,我們已經(jīng)發(fā)現(xiàn)了盲目注入,我們希望發(fā)現(xiàn)關于表和數(shù)據(jù)庫設計的細節(jié)。請看下面的請求:

wangzhan.com/userdetail.asp?username=zhangsan AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtype=0x55),1,1)),0)>65—

如果我們分解一下,會看出這個查詢的結果實際上是一個是或否的回答,“這個表名的第一個字符是一個比65大的ASCII值嗎?”先看最里面的查詢:

SELECT TOP 1 name from sysObjects WHERE xtype=0x55

這意味著:獲取來自sysObjects(所有的表)列表最上面的一個名字,其xtype(對象類型)等于ASCII碼0x55(大寫的字母“U”),轉換成用戶(user)表。所以,基本而言,我們獲取了用戶在數(shù)據(jù)庫中所創(chuàng)建的第一個表。為簡單起見,假設這個表就是“users”:

SUBSTRING(users),1,1

現(xiàn)在,我們創(chuàng)建了一個子串,它包含了表名users的首個字符。其值為“u”:

ISNULL(ASCII(u),0)>65

在這里我們查看u的ASCII碼值的結果是否大于65,確認表名以字母開頭。如果答案是肯定的,查詢就會被處理。否則,查詢就不會被處理。

使用這種方法,我們可以對每個查詢簡單地增加數(shù)字,從而發(fā)現(xiàn)首個用戶名的第一個字母。例如,假設我們在大于117時(>117)得到了一個否定的響應,我們知道第一個字母是字母“u”,因為“u”的ASCII值是117。在發(fā)現(xiàn)這一點之后,我們可以簡單地改變SUBSTRING參數(shù)來選擇第二個字母,然后是第三個字母,等等。

最后,在沒有錯誤代碼時,我們借助于盲目注入就可以發(fā)現(xiàn)有漏洞的Web應用程序的數(shù)據(jù)庫的完整的表結構。#p#

防御措施:保證應用程序編碼的安全

安全的編碼技術可以清除造成SQL注入攻擊的漏洞。下面說的是Web應用程序安全編碼的三個基本方法。

方法一:輸入驗證

在Web應用程序這一層防止SQL注入最常見的方法是使用輸入驗證。無論是何種語言或平臺,這種方法都很有用。其實質就是在驗證用戶輸入的大小和類型前,不對其采取行動。如果你期望用戶輸入的是數(shù)字,就不要接受非數(shù)字的東西。

例如,下面的URL:

wangzhan.com/userdetail.asp?userid=9899

很明顯,在這個GET請求中,我們期望輸入一個整數(shù)。一個簡單的類型檢查會告訴我們這是不是一個合法的字符,從而確保應用程序不會處理非數(shù)字值的輸入。

if (is_numeric($userid)){}

此外,如果用戶的ID總是四個字符的長度,我們就可以進一步采取措施,除了使用常規(guī)的表達式來執(zhí)行整型檢查,還可以強化邊界檢查。

if (preg_match(‘\d{4}’, $string)) {}

在對待如何驗證用戶輸入值的這個問題上,我們僅受到自己創(chuàng)造力的限制。這里的關鍵是驗證由用戶發(fā)送并由系統(tǒng)使用的每一個值。

執(zhí)行類型檢查的另外一種方法是通過ASCII字符。用戶名一般是由字母和數(shù)字組成的,所以我們不希望看到類似“@”、“;”之類的字符。因而,我們可以解析用戶名變量,看看是否存在著不屬于48-57,65-90,97-122的任何ASCII字符。在這個范圍之外的任何ASCII字符對于用戶名變量來說,都是不合法的,應當拒絕接受。這就是所謂白名單的一個例子。

知道白名單和黑名單的區(qū)別非常重要。白名單僅接受已知為安全的值或字符,如字母和數(shù)字。而黑名單則會阻止或不接受已知為惡意的字符。

方法二:規(guī)避技術

到目前為止,類型檢查和邊界檢查似乎很容易,但并非在檢查所有的數(shù)據(jù)類型時都會這么簡單。許多情況下,我們還會使用VARCHAR數(shù)據(jù)類型(VARCHAR是一種比CHAR更加靈活的數(shù)據(jù)類型,同樣用于表示字符數(shù)據(jù),但是VARCHAR可以保存可變長度的字符串。)此類型有可能包含危險字符。這在備注字段和其它的長表單文本字段中很常見。

在這種情況下,我們可以利用一種稱為規(guī)避的技術來確保變量的內(nèi)容絕對不會被解析為SQL語句的一部分。

請看下面這個例子中的請求:

wangzhan.com/comment.asp?msg=I’m zhangsan.

在這個例子中,有一個撇號(’),這是一種常被認為是惡意字符的字符(請參考上一篇文章提到的撇號),我們并不希望排除它,因為此處它的用法是合法的,我們也不希望拒絕這個消息。

例如,在PHP中,我們可以使用mysql_real_escape_string函數(shù):

mysql_real_escape_string($GET[‘msg’]);

這就不會導致安全問題,而是安全地解決了撇號問題,使其不能用于任何MySQL查詢中:

msg=“Hello I\’m zhangsan”

同樣地,在微軟的.NET架構中,設計者常用REPLACE來保證字符串的安全。在下面的例子中,REPLACE函數(shù)將撇號(’)放在引號中,使其成為一種安全字符:

sql = replace(str, “’“, “’“)

方法三:參數(shù)化查詢

防止SQL注入的第三種方法是一種稱為參數(shù)化查詢的技術。這種方法非常有效,因為它可以非常嚴密地控制SQL語句的組成結構。此方法在將對SQL語句的任何重要變更交給SQL服務器處理之前就拒絕其操作。

下面的Java例子中,我們簡單地將參數(shù)添加到已經(jīng)構建的靜態(tài)查詢中。首先,我們使用問號作為變量建立了真實的SELECT語句:

String query = “SELECT account_balance FROM user_data WHERE user_name = ? “;

下一步,我們調用prepareStatement函數(shù):

PreparedStatement pstmt = connection.prepareStatement( query );

然后,在查詢中我們將字符串“custname”指派給變量:

pstmt.setString( 1, custname);

最后,我們執(zhí)行查詢,并將結果存儲在一個變量中:

ResultSet results = pstmt.executeQuery( );

通過使用這種方法,我們能夠確保在附加的惡意查詢或參數(shù)被發(fā)送給數(shù)據(jù)庫之前,不會被添加到查詢中。注意,應當像前面所討論的那樣來驗證“custname”變量,因為它是不受信任的用戶輸入。

【編輯推薦】

  1. 名為LizaMoon的SQL注入攻擊正在席卷全球
  2. SQL注入攻擊三部曲之入門篇
  3. SQL注入攻擊三部曲之進階篇
  4. SQL注入攻擊三部曲之高級篇
責任編輯:于爽 來源: TechTarget中國
相關推薦

2009-10-22 11:03:20

OSGi Web應用程

2022-02-23 15:33:19

前端框架開發(fā)Web

2024-08-19 08:54:02

2010-09-03 15:17:29

2009-04-01 14:33:33

2009-07-09 16:47:26

Servlet的Web

2011-08-10 10:25:42

iPhoneAndroid應用安全

2010-11-11 09:15:08

Web應用程序

2009-02-27 17:00:25

2021-11-08 16:18:20

網(wǎng)絡犯罪Deepfakes網(wǎng)絡攻擊

2012-04-19 09:34:21

ibmdw

2009-01-16 09:22:40

Web應用程序Web程序管理Web服務

2021-04-08 08:06:55

SAP應用程序攻擊

2012-04-25 22:56:10

Android

2012-05-29 09:21:21

API

2011-11-15 10:28:37

2010-05-20 09:48:36

2011-03-22 14:12:17

LAMP

2012-05-14 17:35:28

移動Web

2015-02-02 15:46:59

Web應用架構大數(shù)據(jù)
點贊
收藏

51CTO技術棧公眾號