1.關于SQL Injection
迄今為止,我基本沒有看到誰寫出一篇很完整的文章,或者說很成熟的解決方案(能做到 的人肯定很多,問題是沒有流傳開來,很遺憾) 我簡單的說幾點,希望啟發大家思考,起到抛磚引玉的作用
一、SQL Injection的原理
SQL Injection的實作方法和破壞作用有很多,但萬變不離其宗,其原理可以概括為一句話 :SQL Injection就是向伺服器端送出事先準備好的資料,拼湊出攻擊者想要的SQL語句,以改變資料庫操作執行計劃。
我想,這麼說也許不算精煉,但意思應該很明确了,這句話主要包含這麼三層意思:
1.攻擊者通過何種途徑注入?
存在SQL Injection漏洞的地方都是應用程式需要根據用戶端環境構造SQL語句的地方。由此可以推論,隻要存在"用戶端資料替換預定義變量"的地方,就有可能被注入。
用戶端送出資料可以有很多種方式:GET,POST,Client-Agent,Cookie,Server Enviroment...
2.攻擊者為什麼可以将它想要的語句"注入"?
因為伺服器端應用程式采用拼湊(請特别留意這個詞)SQL語句的方式,這使得攻擊者有機會在送出的資料中包含SQL關鍵字或者運算符,來構造他們想要的語句。
3.SQL Injection最終結果是什麼?
改變資料庫操作執行計劃。
這個結果不一定是惡意的,隻要你的SQL語句沒有按照你預期的計劃(plan)執行,那麼就 可以視為被注入了,不管送出資料的人是不是惡意的。
設有這樣的sql語句:
update tableName set columnName1 = " $Client_Submit_Data " where PK_ID = 1234
$Client_Submit_Data是一個變量,它代表用戶端送出的資料,這裡我就不管環境是ASP還 是PHP還是其他什麼東西了。
假設這個操作是要更新一篇文章的标題,很多人是不是會這麼構造SQL語句?我們看看$Cl ient_Submit_Data包含引号的情況,令$Client_Submit_Data = 誰能告訴我"sql injecti on"是什麼?
那麼sql語句将被拼湊成這樣:
update tableName set columnName1 = "誰能告訴我"sql injection"是什麼?" where PK_ID = 1234
執行結果很明顯,将執行這樣的語句:update tableName set columnName1 = "誰能告訴我"
where子句被忽略掉了,很遺憾,你的資料庫中所有文章标題都會被update為"誰能告訴我 "
在這個例子當中,使用者應該是無心的——标題裡面包括引号應該很正常吧——但結果卻和SQL Injection無異。
好啦,說了半天廢話,言歸正傳,說一下如何應對這種問題。
我相信這裡的朋友都看過很多防止SQL Injection的文章了,也大都會通過replace來防範一些注入,問題是:你們知其然的時候是否知其是以然?
我認為,徹底解決SQL Injection的最好方法是:避免拼湊SQL語句。這就是我在上面要大家特别注意拼湊這個詞的原因。
SQL Injection之是以有機可乘,是因為絕大多數Server Application采用拼湊SQL語句的方式來建構應用程式(閱讀這個文章的諸位,你們回首想想自己的項目,有幾個不是通過拼湊SQL語句的方式來操作資料庫?想想你們見過的被注入的案例,有幾個不是采用的拼湊SQL語句的應用),所謂拼湊SQL語句,簡單一點說就是:用連接配接字元串操作(ASP中的&和PHP中的.)将SQL關鍵字和用戶端送出的資料連接配接起來并發送給DBMS執行。這樣做直接導緻 DBMS根本不知道你計劃(plan to)做什麼,而隻知道你要(is to)做什麼,不是嗎,伺服器端腳本總是将要執行的SQL語句構造好,然後發給資料庫,DBMS根本不知道用戶端資料 替換了變量之後,這個語句的執行計劃是否有變化。伺服器端腳本總是粗暴的告訴DBMS:你隻管這麼做好了,别問我為什麼。就像上面我提到的更新文章标題的例子,DBMS不知道你隻想更新第1234篇文章的标題,它以為你就是要把所有的标題都變成這個,因為你的語句就是沒有where子句嘛!
說到這裡,可能大家都明白了,所謂的最好方法是Stored Procedure。Yes! That is!
要想做出安全可靠的Server application,你最好把自己當作兩個人,一個DBA,一個Coder(ASP Coder,PHP Coder or others),很多人往往隻知道:我在做一個BBS,我在做一個留言本,我在做一個新聞釋出系統,我們的流程都是這樣的,給使用者一個表單,讓使用者送出,然後去寫資料庫,用的時候根據條件把資料記錄找出來,然後顯示。沒事,如果你 是一個業餘愛好者,隻想自己寫點小東西玩玩,這足夠了!如果你想把WebDev作為你的職業,或者說,你想成為一個非常專業的業餘愛好者,你必須當自己是一個DBA+Coder,至于要不要是一個Designer就看你的能力和精力咯!
好了,點到為止,我就說這麼多,徹底的解決方法是要在DBMS上寫入你的資料操作計劃,讓伺服器在開始執行之前知道你的意圖,不要粗暴的告訴它:我就是要你執行這個指令,不要問我為什麼!
實作方法嘛,目前比較普遍的,也比較容易實作的就是存儲過程了,應用存儲過程不僅可以從根本上解決SQL Injection這個安全問題,還會使得你的應用程式速度成倍增長(這個增長的幅度甚至可能達到一個數量級,這跟很多因素有關,不好一概而論),還會使得你開發的系統更想大型系統,擁有更好的架構體系(例如MVC模式)。
在 MySQL 4.1.x及其後續版本和ODBC中,提供了一種叫做prepared statements的東西,它 本質上也是一種存儲過程,一種系統預置(相對于使用者自定義)的存儲過程。
如果你沒有條件用上存儲過程(比如資料庫不支援,MySQL,Access,SQLite等都不支援),那麼就隻能将SQL Injection扼殺在搖籃裡了。解決方法,我也隻簡單的說一句:不要相信任何來自用戶端的資料。這個用戶端的資料,可以通過很多途徑被送出,比如get,post ,cookie,browser參數,IP位址,等等,隻要不是伺服器上擷取的就都算用戶端資料,隻要是用戶端資料,都是不可信的,在TCP/IP這個大架構下,什麼都是可以僞造的,包括IP位址。
凡是來自用戶端的資料,必須校驗——注意是校驗,不是過濾。基本上,不管你多聰明多細心(哪怕像我一樣,不許笑,不許笑,嚴肅點,嚴肅點,我們這兒講SQL Injection呢) 也無法窮舉可能被用于SQL Injection的符号和關鍵字,也無法預知替換掉他們是否會有副 作用,最好的辦法是不去判斷什麼資料不符合條件,而改由判斷什麼資料符合條件,假設你的一個系統使用者名隻能是字母數字和下劃線,那麼你就可以用[0-9a-zA-Z_]+這個正則來比對它,如果不符合條件,拒之即可,這比費盡心思去過濾單引号分号逗号空格什麼的要明了和簡潔的多。
春節前夕,數萬個用PHPBB作為論壇的網站被攻陷,大家有印象嗎?罪魁禍首隻是一個單引 ,盡管PHP有magic_quotes_gpc,可還是被幹掉了,原因是%2527在url_decode函數中會被解析為%27(因為%25就是百分号),%27正是引号,By the way,盡管部落格中國的論壇也 是基于PHPBB的,但是那次我們幸免于難,因為在那之前我們被黑過一次了(汗),就是因為這個,哈哈! 其實,SQL Injection不是ASP程式設計領域特有的,Web開發最容易碰到,但Desktop Application也有,隻要有資料庫的地方,隻要采用拼湊SQL語句的方式,就可能存在Injection的機會,大家牢記,如果有條件,盡量把資料DBMS職責範圍的事情交給DBMS去做,如果沒條件,一定要注意校驗用戶端送出的資料,當然,雙管齊下也行,^_^
好了,最後,說句話給那些有志于從事WebDev工作的朋友,如果将來你進入這個領域,你把總結出來這篇文章,你應該會很順利的通過面試,并得到一個不錯的薪水等級。
附:微軟釋出3款SQL Injection攻擊檢測工具
随着 SQL INJECTION 攻擊的明顯增多,微軟近日釋出了三個免費工具,幫助網站管理者和檢測存在的風險并對可能的攻擊進行攔截。
Scrawlr
這個微軟和 HP合作開發的工具,會在網站中爬行,對所有網頁的查詢字元串進行分析并發現其中的 SQL INJECTION 風險。Scrawlr 使用了部分 HP WebInspect 相同的技術,但隻檢測 SQL INJECTION 風險。Scrawlr 從一個起始 URL 入口,爬遍整個網站,并對站點中所有網頁進行分析以找到可能存在的漏洞。
Microsoft Source Code Analyzer for SQL Injection
這款被稱作 MSCASI 的工具可以檢測 ASP 代碼并發現其中的 SQL INJECTION 漏洞(ASP 代碼以 SQL INJECTION 漏洞著稱),你需要向 MSCASI 提供原始代碼,MSCASI 會幫你找到存在風險的代碼位置。
URLScan 3.0
該工具會讓 IIS 限制某些類型的 HTTP 請求,通過對特定 HTTP 請求進行限制,可以防止某些有害的請求在伺服器端執行。UrlScan 通過一系列關鍵詞發現惡意請求,并阻止惡意請求的執行。
本文轉自周金橋51CTO部落格,原文連結: http://blog.51cto.com/zhoufoxcn/166058,如需轉載請自行聯系原作者