![PHP中防止SQL注入_第1頁](http://file3.renrendoc.com/fileroot_temp3/2022-2/6/cd9fea3b-9939-4b5f-a89a-42be747bf901/cd9fea3b-9939-4b5f-a89a-42be747bf9011.gif)
![PHP中防止SQL注入_第2頁](http://file3.renrendoc.com/fileroot_temp3/2022-2/6/cd9fea3b-9939-4b5f-a89a-42be747bf901/cd9fea3b-9939-4b5f-a89a-42be747bf9012.gif)
![PHP中防止SQL注入_第3頁](http://file3.renrendoc.com/fileroot_temp3/2022-2/6/cd9fea3b-9939-4b5f-a89a-42be747bf901/cd9fea3b-9939-4b5f-a89a-42be747bf9013.gif)
![PHP中防止SQL注入_第4頁](http://file3.renrendoc.com/fileroot_temp3/2022-2/6/cd9fea3b-9939-4b5f-a89a-42be747bf901/cd9fea3b-9939-4b5f-a89a-42be747bf9014.gif)
![PHP中防止SQL注入_第5頁](http://file3.renrendoc.com/fileroot_temp3/2022-2/6/cd9fea3b-9939-4b5f-a89a-42be747bf901/cd9fea3b-9939-4b5f-a89a-42be747bf9015.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、在本系列文章中, 我們將全面探討如何在PHP 開發(fā)環(huán)境中全面阻止SQL注入式攻 擊,并給出一個(gè)具體的開發(fā)示例。一、 引言PHP是一種力量強(qiáng)大但相當(dāng)容易學(xué)習(xí)的服務(wù)器端腳本語言,即使是經(jīng)驗(yàn)不多 的程序員也能夠使用它來創(chuàng)建復(fù)雜的動態(tài)的web站點(diǎn)。然而,它在實(shí)現(xiàn)因特網(wǎng)服 務(wù)的秘密和安全方面卻常常存在許多困難。在本系列文章中,我們將向讀者介紹 進(jìn)行web開發(fā)所必需的安全背景以及PHP特定的知識和代碼-你可以借以保護(hù)你 自己的web應(yīng)用程序的安全性和一致性。首先,我羌虻鼗毓艘幌路衿靼踩侍?展示你如何存取一個(gè)共享宿主環(huán)境下的私人信息,使開發(fā)者脫離開生產(chǎn)服務(wù) 器,維持最新的軟件,提供加密的頻道,并且控制對你的
2、系統(tǒng)的存取。然后,我們討論P(yáng)HP腳本實(shí)現(xiàn)中的普遍存在的脆弱性。我們將解釋如何保護(hù) 你的腳本免于SQL注入,防止跨站點(diǎn)腳本化和遠(yuǎn)程執(zhí)行,并且阻止對臨時(shí)文件及 會話的"劫持"。在最后一篇中,我們將實(shí)現(xiàn)一個(gè)安全的Web應(yīng)用程序。你將學(xué)習(xí)如何驗(yàn)證用 戶身份,授權(quán)并跟蹤應(yīng)用程序使用,避免數(shù)據(jù)損失,安全地執(zhí)行高風(fēng)險(xiǎn)性的系統(tǒng) 命令,并能夠安全地使用web服務(wù)。無論你是否有足夠的PHP安全開發(fā)經(jīng)驗(yàn),本 系列文章都會提供豐富的信息來幫助你構(gòu)建更為安全的在線應(yīng)用程序。二、 什么是SQL注入如果你打算永遠(yuǎn)不使用某些數(shù)據(jù)的話, 那么把它們存儲于一個(gè)數(shù)據(jù)庫是毫無 意義的; 因?yàn)閿?shù)據(jù)庫的設(shè)計(jì)目的是為了
3、方便地存取和操作數(shù)據(jù)庫中的數(shù)據(jù)。 但是, 如果只是簡單地這樣做則有可能會導(dǎo)致潛在的災(zāi)難。 這種情況并不主要是因?yàn)槟?自己可能偶然刪除數(shù)據(jù)庫中的一切;而是因?yàn)?當(dāng)你試圖完成某項(xiàng)"無辜"的任務(wù) 時(shí), 你有可能被某些人所"劫持"-使用他自己的破壞性數(shù)據(jù)來取代你自己的數(shù)據(jù)。 我們稱這種取代為"注入"。其實(shí),每當(dāng)你要求用戶輸入構(gòu)造一個(gè)數(shù)據(jù)庫查詢,你是在允許該用戶參與構(gòu) 建一個(gè)存取數(shù)據(jù)庫服務(wù)器的命令。 一位友好的用戶可能對實(shí)現(xiàn)這樣的操作感覺很 滿意;然而,一位惡意的用戶將會試圖發(fā)現(xiàn)一種方法來扭曲該命令,從而導(dǎo)致該 被的扭曲命令刪除數(shù)據(jù),甚至做出更
4、為危險(xiǎn)的事情。作為一個(gè)程序員,你的任務(wù) 是尋找一種方法來避免這樣的惡意攻擊。三、 SQL注入工作原理構(gòu)造一個(gè)數(shù)據(jù)庫查詢是一個(gè)非常直接的過程。典型地,它會遵循如下思路來 實(shí)現(xiàn)。僅為說明問題,我們將假定你有一個(gè)葡萄酒數(shù)據(jù)庫表格"wines",其中有 一個(gè)字段為"variety"(即葡萄酒類型:1. 提供一個(gè)表單-允許用戶提交某些要搜索的內(nèi)容。 讓我們假定用戶選擇搜 索類型為"lagrein"的葡萄酒。2. 檢索該用戶的搜索術(shù)語, 并且保存它-通過把它賦給一個(gè)如下所示的變量 來實(shí)現(xiàn):$variety = $_POST'variety
5、'因此,變量$variety的值現(xiàn)在為:lagrein3. 然后,使用該變量在WHERE子句中構(gòu)造一個(gè)數(shù)據(jù)庫查詢:$query = "SELECT * FROM wines WHERE variety='$variety'"所以,變量$query的值現(xiàn)在如下所示:SELECT * FROM wines WHERE variety='lagrein'4. 把該查詢提交給MySQL服務(wù)器。5. MySQL返回wines表格中的所有記錄-其中,字段variety的值為 "lagrein"。到目前為止,這應(yīng)該是一個(gè)你所熟悉
6、的而且是非常輕松的過程。遺憾的是,有時(shí) 我們所熟悉并感到舒適的過程卻容易導(dǎo)致我們產(chǎn)生自滿情緒。現(xiàn)在,讓我們再重 新分析一下剛才構(gòu)建的查詢。1. 你創(chuàng)建的這個(gè)查詢的固定部分以一個(gè)單引號結(jié)束,你將使用它來描述變 量值的開始:$query = " SELECT * FROM wines WHERE variety = '"2. 使用原有的固定不變的部分與包含用戶提交的變量的值:$query .= $variety;3. 緩螅閌褂昧硪桓齙爬戳喲私峁?描述該變量值的結(jié)束:$ query .= "'"于是,$query的值如下所示:SELECT *
7、FROM wines WHERE variety = 'lagrein'這個(gè)構(gòu)造的成功依賴用戶的輸入。在本文示例中,你正在使用單個(gè)單詞(也可能是一組單詞來指明一種葡萄酒類型。因此,該查詢的構(gòu)建是無任何問題的, 并且結(jié)果也會是你所期望的-一個(gè)葡萄酒類型為"lagrein"的葡萄酒列表?,F(xiàn)在, 讓我們想象, 既然你的用戶不是輸入一個(gè)簡單的類型為"lagrein"的葡萄酒類型, 而是輸入了下列內(nèi)容(注意包括其中的兩個(gè)標(biāo)點(diǎn)符號:lagrein' or 1=1;現(xiàn)在, 你繼續(xù)使用前面固定的部分來構(gòu)造你的查詢(在此, 我們僅顯示$query
8、變量的結(jié)果值:SELECT * FROM wines WHERE variety = '然后,你使用包含用戶輸入內(nèi)容的變量的值與之進(jìn)行連接(在此,以粗體顯 示:SELECT * FROM wines WHERE variety = 'lagrein' or 1=1;最后,添加上下面的下引號:SELECT * FROM wines WHERE variety = 'lagrein' or 1=1;'于是,這個(gè)查詢結(jié)果與你的期望會相當(dāng)不同。事實(shí)上,現(xiàn)在你的查詢包含的 不是一條而是兩條指令,因?yàn)橛脩糨斎氲淖詈蟮姆痔栆呀?jīng)結(jié)束了第一條指令(進(jìn) 行記錄選擇從
9、而開始了一條新的指令。在本例中,第二條指令,除了一個(gè)簡單 的單引號之外別無意義;但是,第一條指令也不是你所想實(shí)現(xiàn)的。當(dāng)用戶把一個(gè) 單引號放到他的輸入內(nèi)容的中間時(shí),他結(jié)束了期望的變量的值,并且引入了另一 個(gè)條件。因此,不再是檢索那些variety為"lagrein"的記錄,而是在檢索那些 滿足兩個(gè)標(biāo)準(zhǔn)中任何一個(gè)(第一個(gè)是你的,而第二個(gè)是他的-variety為 "lagrein"或1等于1的記錄。既然1總是1,因此,你會檢索到所有的記錄!你可能反對: 我不會使用雙引號來代替單引號來描述用戶提交的變量嗎?不 錯(cuò),這至少可以減慢惡意用戶的攻擊。(在以前的文章中,
10、我們提醒過你:應(yīng)該 禁止所有對用戶的錯(cuò)誤通知信息。如果在此生成一條錯(cuò)誤消息,那么,它有可能 恰恰幫助了攻擊者-提供一個(gè)關(guān)于他的攻擊為什么失敗的具體的解釋。在實(shí)踐中, 使你的用戶能夠看到所有的記錄而不只是其中的一部分乍看起來 似乎不太費(fèi)事,但實(shí)際上,這的確費(fèi)事不少;看到所有的記錄能夠很容易地向他 提供有關(guān)于該表格的內(nèi)部結(jié)構(gòu), 從而也就向他提供了使其以后實(shí)現(xiàn)更為惡毒目的 的一個(gè)重要參考。 如果你的數(shù)據(jù)庫中不是包含顯然無害的酒之類信息而是包含例 如一個(gè)含有雇員年收入的列表,那么,剛才描述情形會是特別真實(shí)的。而從理論角度分析,這種攻擊也的確是一件很可怕的事情。由于把意外的內(nèi) 容注入到你的查詢中,所以,
11、此用戶能夠?qū)崿F(xiàn)把你的數(shù)據(jù)庫存取轉(zhuǎn)化為用于實(shí)現(xiàn) 他自己的目的。因此現(xiàn)在,你的數(shù)據(jù)庫已經(jīng)對他打開-正如對你敞開一樣。四、 PHP和MySQL注入如我們前面所描述的,PHP,從本身設(shè)計(jì)來說,并沒有做什么特別的事情- 除了按照你的指示操作之外。因此,如果為惡意用戶所用,它也只是按照要求" 允許"特別設(shè)計(jì)的攻擊-例如我們前面所描述的那樣。我們將假定, 你不會故意地或甚至是偶然地構(gòu)造一個(gè)具有破壞性效果的數(shù)據(jù)庫查 詢-于是,我們假定問題出在來自你的用戶的輸入方面?,F(xiàn)在,讓我們來更為細(xì) 致地分析一下用戶可能向你的腳本提供信息的各種途徑。五、 用戶輸入的類型如今,用戶能夠影響你的腳本的行為已
12、變得越來越復(fù)雜。用戶輸入最明顯的來源當(dāng)然是表單上的一個(gè)文本輸入域。使用這樣的一個(gè) 域,你簡直是在故意教唆一個(gè)用戶輸入任意數(shù)據(jù)。而且,你向用戶提供了一個(gè)很 大的輸入范圍;沒有什么辦法能夠使你提前限制一個(gè)用戶能夠輸入的數(shù)據(jù)類型 (盡管你能夠選擇限制它的長度。 這正是絕大多數(shù)的注入式攻擊源主要來自于無 防備的表單域的原因。但是,還存在其它的攻擊源,并且稍加思考你就會想到的一種潛于表單后臺 的技術(shù)-POST方法!通過簡單地分析顯示在瀏覽器的導(dǎo)航工具欄中的URI,一個(gè) 善于觀察的用戶能夠很容易地看出是什么信息傳遞到了一個(gè)腳本。 盡管典型情況 下這樣的URI是以編程方式生成的,但是,沒有什么辦法能夠阻止一
13、個(gè)惡意的用 戶簡單地把一個(gè)帶有一個(gè)不適當(dāng)?shù)淖兞恐档腢RI輸入到一個(gè)瀏覽器中-而這樣潛 在地打開一個(gè)可能會被其濫用的數(shù)據(jù)庫。限制用戶輸入內(nèi)容的一個(gè)常用策略是在一個(gè)表單中提供一個(gè)選擇框, 而不是 一個(gè)輸入框。這種控件能夠強(qiáng)制用戶從一組預(yù)定義的值中進(jìn)行選擇,并且能夠在 一定程度上阻止用戶輸入期望不到的內(nèi)容。 但是正如一個(gè)攻擊者可能"哄騙"一個(gè) URI(也即是,創(chuàng)建一個(gè)能夠模仿一個(gè)可信任的卻無效的URI一樣,他也可能模 仿創(chuàng)建你的表單及其自己的版本, 并因此在選項(xiàng)框中使用非法的而不是預(yù)定義的安全選擇。要實(shí)現(xiàn)這點(diǎn)是極其簡單的;他僅需要觀察源碼,然后剪切并且粘貼該 表單的源代碼-然后一
14、切為他敞開大門。在修改該選擇之后,他就能夠提交表單,并且他的無效的指令就會被接受, 就象它們是原始的指令一樣。因此,該用戶可以使用許多不同的方法試圖把惡意 的代碼注入到一個(gè)腳本中。上篇文章我們介紹了PHP中防止SQL注入式攻擊一,本文我們來繼續(xù)學(xué)習(xí), php防SQL注入式攻擊。一、注入式攻擊的類型可能存在許多不同類型的攻擊動機(jī),但是乍看上去,似乎存在更多的類型。 這是非常真實(shí)的-如果惡意用戶發(fā)現(xiàn)了一個(gè)能夠執(zhí)行多個(gè)查詢的辦法的話。本文 后面,我們會對此作詳細(xì)討論。如果你的腳本正在執(zhí)行一個(gè)SELECT指令,那么,攻擊者可以強(qiáng)迫顯示一個(gè) 表格中的每一行記錄-通過把一個(gè)例如"1=1"
15、;這樣的條件注入到WHERE子句中, 如 下所示(其中,注入部分以粗體顯示:SELECT * FROM wines WHERE variety = 'lagrein' OR 1=1;'正如我們在前面所討論的,這本身可能是很有用的信息,因?yàn)樗沂玖嗽摫?格的一般結(jié)構(gòu)(這是一條普通的記錄所不能實(shí)現(xiàn)的, 以及潛在地顯示包含機(jī)密信 息的記錄。一條更新指令潛在地具有更直接的威脅。通過把其它屬性放到SET子句中, 一名攻擊者可以修改當(dāng)前被更新的記錄中的任何字段,例如下面的例子(其中, 注入部分以粗體顯示:UPDATE wines SET type='red',
16、9;vintage'='9999' WHERE variety = 'lagrein' 通過把一個(gè)例如1=1這樣的恒真條件添加到一條更新指令的WHERE子句中, 這種修改范圍可以擴(kuò)展到每一條記錄,例如下面的例子(其中,注入部分以粗體 顯示:UPDATE wines SET type='red','vintage'='9999 WHERE variety = 'lagrein' OR 1=1;'最危險(xiǎn)的指令可能是DELETE-這是不難想像的。其注入技術(shù)與我們已經(jīng)看到 的相同-通過修改WHERE
17、子句來擴(kuò)展受影響的記錄的范圍,例如下面的例子(其 中,注入部分以粗體顯示:DELETE FROM wines WHERE variety = 'lagrein' OR 1=1;'二、多個(gè)查詢注入多個(gè)查詢注入將會加劇一個(gè)攻擊者可能引起的潛在的損壞-通過允許多條破 壞性指令包括在一個(gè)查詢中。在使用MySQL數(shù)據(jù)庫時(shí),攻擊者通過把一個(gè)出乎意 料之外的終止符插入到查詢中即可很容易實(shí)現(xiàn)這一點(diǎn)-此時(shí)一個(gè)注入的引號(單 引號或雙引號標(biāo)記期望變量的結(jié)尾;然后使用一個(gè)分號終止該指令?,F(xiàn)在,一 個(gè)另外的攻擊指令可能被添加到現(xiàn)在終止的原始指令的結(jié)尾。 最終的破壞性查詢 可能看起來如下所示:S
18、ELECT * FROM wines WHERE variety = 'lagrein'GRANT ALL ON *.* TO 'BadGuy%' IDENTIFIED BY 'gotcha''這個(gè)注入將創(chuàng)建一個(gè)新的用戶BadGuy并賦予其網(wǎng)絡(luò)特權(quán)(在所有的表格上 具有所有的特權(quán);其中,還有一個(gè)"不祥"的口令被加入到這個(gè)簡單的SELECT 語句中。如果你遵循我們在以前文章中的建議-嚴(yán)格限制該過程用戶的特權(quán),那 么,這應(yīng)該無法工作,因?yàn)閣eb服務(wù)器守護(hù)程序不再擁有你撤回的GRANT特權(quán)。 但是從理論上講,這樣的一個(gè)攻擊可
19、能給予BadGuy自由權(quán)力來實(shí)現(xiàn)他對你的數(shù) 據(jù)庫的任何操作。至于這樣的一個(gè)多查詢是否會被MySQL服務(wù)器處理,結(jié)論并不唯一。這其中 的一些原因可能是由于不同版本的MySQL所致, 但是大多數(shù)情況卻是由于多查詢 存在的方式所致。MySQL的監(jiān)視程序完全允許這樣的一個(gè)查詢。常用的MySQL GUI-phpMyAdmin,在最終查詢之前會復(fù)制出以前所有的內(nèi)容,并且僅僅這樣做。但是, 大多數(shù)的在一個(gè)注入上下文中的多查詢都是由PHP的mysql擴(kuò)展負(fù)責(zé) 管理的。幸好,默認(rèn)情況下,它是不允許在一個(gè)查詢中執(zhí)行多個(gè)指令的;試圖執(zhí) 行兩個(gè)指令(例如上面所示的注入將會簡單地導(dǎo)致失敗-不設(shè)置任何錯(cuò)誤,并且 沒有生成
20、任何輸出信息。在這種情況下,盡管PHP也只是"規(guī)規(guī)矩矩"地實(shí)現(xiàn)其缺 省行為,但是確實(shí)能夠保護(hù)你免于大多數(shù)簡單的注入式攻擊。PHP5中的新的mysqli擴(kuò)展(參考 樣,內(nèi)在地也不支持多個(gè)查詢,不過卻提供了一個(gè)mysqli_multi_query(函數(shù) 以支持你實(shí)現(xiàn)多查詢-如果你確實(shí)想這樣做的話。然而,對于SQLite-與PHP5綁定到一起的可嵌入的SQL數(shù)據(jù)庫引擎(參考 /和 用而吸引了大量用戶的關(guān)注。在有些情況下,SQLite缺省地允許這樣的多指令 查詢,因?yàn)樵摂?shù)據(jù)庫可以優(yōu)化批查詢,特別是非常有效的批INSERT語句處理。 然而,如果查詢的結(jié)
21、果為你的腳本所使用的話(例如在使用一個(gè)SELECT語句檢 索記錄的情況下,sqlite_query(函數(shù)卻不會允許執(zhí)行多個(gè)查詢。三、INVISION Power BOARD SQL注入脆弱性Invision Power Board是一個(gè)著名的論壇系統(tǒng)。2005年五月6號,在登錄 代碼中發(fā)現(xiàn)了一處SQL注入脆弱性。其發(fā)現(xiàn)者為GulfTech Security Research 的James Bercegay。這個(gè)登錄查詢?nèi)缦滤?$DB->query("SELECT * FROM ibf_members WHERE id=$mid ANDpassword='$pid
22、9;"其中,成員ID變量$mid和口令I(lǐng)D變量$pid被使用下面兩行代碼從my_cookie(函數(shù)中檢索出:$mid = intval($std->my_getcookie('member_id'$pid = $std->my_getcookie('pass_hash'在此,my_cookie(函數(shù)使用下列語句從cookie中檢索要求的變量: return urldecode($_COOKIE$ibforums->vars'cookie_id'.$name;【注意】從該cookie返回的值根本沒有被處理。盡管$mid在
23、使用于查詢之 前被強(qiáng)制轉(zhuǎn)換成一個(gè)整數(shù),但是$pid卻保持不變。因此,它很容易遭受我們前 面所討論的注入類型的攻擊。因此,通過以如下方式修改my_cookie(函數(shù),這種脆弱性就會暴露出來:if (!in_array( $name,array('topicsread', 'forum_read','collapseprefs'return $this->clean_value(urldecode($_COOKIE$ibforums->vars'cookie_id'.$name; elsereturn urldecode(
24、$_COOKIE$ibforums->vars'cookie_id'.$name;經(jīng)過這樣的改正之后,其中的關(guān)鍵變量在"通過"全局clean_value(函數(shù)后 被返回,而其它變量卻未進(jìn)行檢查?,F(xiàn)在,既然我們大致了解了什么是SQL注入,它的注入原理以及這種注入的 脆弱程度,那么接下來,讓我們探討如何有效地預(yù)防它。幸好,PHP為我們提供 了豐富的資源,因此我們有充分的信心預(yù)言,一個(gè)經(jīng)仔細(xì)地徹底地使用我們所推 薦的技術(shù)構(gòu)建的應(yīng)用程序?qū)哪愕哪_本中根本上消除任何可能性的SQL注入- 通過在它可能造成任何損壞之前"清理"你的用戶的數(shù)據(jù)來實(shí)
25、現(xiàn)。四、界定你的查詢中的每一個(gè)值我們推薦,你確保界定了你的查詢中的每一個(gè)值。字符串值首當(dāng)其沖,以及 那些你通常期望應(yīng)該使用"單"(而不是"雙"引號的內(nèi)容。一方面,如果你使用雙 引號來允許PHP在字符串內(nèi)的變量替代,這樣可以使得輸入查詢更為容易些;另 一方面,這(無可否認(rèn),只是極少量地也會減少以后PHP代碼的分析工作。下面,讓我們使用我們一開始使用的那個(gè)非注入式查詢來說明這個(gè)問題:SELECT * FROM wines WHERE variety = 'lagrein'或以PHP語句表達(dá)為:$query = "SELECT * F
26、ROM wines WHERE variety = '$variety'"從技術(shù)上講,引號對于數(shù)字值來說是不需要使用的。但是,如果你并不介意 用引號把例如葡萄酒這樣的一個(gè)域相應(yīng)的一個(gè)值括起來并且如果你的用戶把一 個(gè)空值輸入到你的表單中的話,那么,你會看到一個(gè)類似下面的查詢:SELECT * FROM wines WHERE vintage =當(dāng)然,這個(gè)查詢從語法上講是無效的;但是,下面的語法卻是有效的:SELECT * FROM wines WHERE vintage = ''第二個(gè)查詢將(大概不會返回任何果,但是至少它不會返回一個(gè)錯(cuò)誤消息。五、檢查用
27、戶提交的值的類型從前面的討論中我們看到,迄今為止,SQL注入的主要來源往往出在一個(gè)意 料之外的表單入口上。然而,當(dāng)你經(jīng)由一個(gè)表單向用戶提供機(jī)會提交某些值時(shí), 你應(yīng)該有相當(dāng)?shù)膬?yōu)勢來確定你想取得什么樣的輸入內(nèi)容-這可以使得我們比較容 易地檢查用戶入口的有效性。 在以前的文章中, 我們已經(jīng)討論過這樣的校驗(yàn)問題; 所以, 在此, 我們僅簡單地總結(jié)當(dāng)時(shí)我們討論的要點(diǎn)。 如果你正在期望一個(gè)數(shù)字, 那么你可以使用下面這些技術(shù)之一來確保你得到的真正.· 使用is_int(函數(shù)(或is_integer(或is_long(。· 使用gettype(函數(shù)。· 使用intval(函數(shù)。&
28、#183; 使用settype(函數(shù)。為了檢查用戶輸入內(nèi)容的長度,你可以使用strlen(函數(shù)。為了檢查一個(gè) 期望的時(shí)間或日期是否有效,你可以使用strtotime(函數(shù)。它幾乎一定能夠確 保一位用戶的入口中沒有包含分號字符(除非標(biāo)點(diǎn)符號可以被合法地包括在內(nèi)。 你可以借助于strpos(函數(shù)容易地實(shí)現(xiàn)這一點(diǎn),如下所示:if( strpos( $variety, '' exit ( "$variety is an invalid value for variety!" ;正如我們在前面所提到的,只要你仔細(xì)分析你的用戶輸入期望,那么,你應(yīng) 該能夠很容易地檢查出其
29、中存在的許多問題。六、從你的查詢中濾去每一個(gè)可疑字符盡管在以前的文章中,我們已經(jīng)討論過如何過濾掉危險(xiǎn)字符的問題;但是在 此,還是讓我們再次簡單地強(qiáng)調(diào)并歸納一下這個(gè)問題:· 不要使用magic_quotes_gpc指令或它的"幕后搭擋"-addslashes(函 數(shù),此函數(shù)在應(yīng)用程序開發(fā)中是被限制使用的,并且此函數(shù)還要求使用額外的步 驟-使用stripslashes(函數(shù)。· 相比之下,mysql_real_escape_string(函數(shù)更為常用,但是也有它自 己的缺點(diǎn)。-一、 建立一個(gè)安全抽象層我們并不建議你手工地把前面介紹的技術(shù)應(yīng)用于每一個(gè)用戶輸入的
30、實(shí)例中, 而是強(qiáng)烈推薦你為此創(chuàng)建一個(gè)抽象層。 一個(gè)簡單的抽象是把你的校驗(yàn)方案加入到 一個(gè)函數(shù)中,并且針對用戶輸入的每一項(xiàng)調(diào)用這個(gè)函數(shù)。當(dāng)然,我們還可以創(chuàng)建 一種更復(fù)雜的更高一級的抽象-把一個(gè)安全的查詢封裝到一個(gè)類中,從而應(yīng)用于 整個(gè)應(yīng)用程序。在網(wǎng)上已經(jīng)存在許多這種現(xiàn)成的免費(fèi)的類;在本篇中,我們正要 討論其中的一些。進(jìn)行這種抽象至少存在三個(gè)優(yōu)點(diǎn)(而且每一個(gè)都會改進(jìn)安全級別:1. 本地化代碼。2. 使查詢的構(gòu)造更快且更為可靠-因?yàn)檫@可以把部分工作交由抽象代碼來 實(shí)現(xiàn)。3. 當(dāng)基于安全特征進(jìn)行構(gòu)建并且恰當(dāng)使用時(shí),這將會有效地防止我們前面 所討論的各種各樣的注入式攻擊。二、 改進(jìn)現(xiàn)有的應(yīng)用程序如果你想
31、改進(jìn)一個(gè)現(xiàn)有的應(yīng)用程序,則使用一個(gè)簡單的抽象層是最適當(dāng)?shù)摹?一個(gè)能夠簡單地"清理"你所收集的任何用戶輸入內(nèi)容的函數(shù)可能看起來如下所 示:function safe( $string return "'" . mysql_real_escape_string( $string . "'"【注意】我們已經(jīng)構(gòu)建了相應(yīng)于值要求的單引號以及mysql_real_escape_string(函數(shù)。接下來,就可以使用這個(gè)函數(shù)來構(gòu)造一個(gè) $query變量,如下所示:$variety = safe( $_POST'variety
32、' ;$query = " SELECT * FROM wines WHERE variety=" . $variety;現(xiàn)在,你的用戶試圖進(jìn)行一個(gè)注入式攻擊-通過輸入下列內(nèi)容作為變量 $variety 的值: lagrein' or 1=1; 注意,如果不進(jìn)行上面的"清理",則最后的查詢將如下所示(這將導(dǎo)致無法 預(yù)料的結(jié)果): SELECT * FROM wines WHERE variety = 'lagrein' or 1=1;' 然而現(xiàn)在, 既然用戶的輸入已經(jīng)被清理,那么查詢語句就成為下面這樣一種 無危害的
33、形式: SELECT * FROM wines WHERE variety = 'lagrein/' or 1=1/;' 既然數(shù)據(jù)庫中不存在與指定的值相應(yīng)的 variety 域(這正是惡意用戶所輸入的內(nèi) 容-lagrein' or 1=1;,那么,這個(gè)查詢將不能返回任何結(jié)果,并且注入將會失 敗。 三、 保護(hù)一個(gè)新的應(yīng)用程序 如果你正在創(chuàng)建一個(gè)新的應(yīng)用程序,那么,你可以從頭開始創(chuàng)建一個(gè)安全抽 象層。如今,PHP 5 新改進(jìn)的對于 MySQL 的支持(這主要體現(xiàn)在新的 mysqli 擴(kuò) 展中)為這種安全特征提供了強(qiáng)有力的支持(既有過程性的,也有面向?qū)ο筇卣?的)。你
34、可以從站點(diǎn) 上獲取有關(guān) mysqli 的信息。注意, 只有當(dāng)你使用-with-mysqli=path/to/mysql_config 選項(xiàng)編譯 PHP 時(shí),這種 mysqli 支持才可用。 下面是該代碼的一個(gè)過程性版本, 用于保護(hù)一個(gè)基于 mysqli 的查詢: ?php /檢索用戶的輸入 $animalName = $_POST'animalName' /連接到數(shù)據(jù)庫 $connect = mysqli_connect( 'localhost', 'username', 'password', 'database'
35、; ; if ( !$connect exit( 'connection failed: ' . mysqli_connect_error( ; /創(chuàng)建一個(gè)查詢語句源 $stmt = mysqli_prepare( $connect,"SELECT intelligence FROM animals WHERE name = ?" ; if ( $stmt /把替代綁定到語句上 mysqli_stmt_bind_param( $stmt, "s", $animalName ; /執(zhí)行該語句 mysqli_stmt_execute( $st
36、mt ; /檢索結(jié)果. mysqli_stmt_bind_result( $stmt, $intelligence ; / .并顯示它 if ( mysqli_stmt_fetch( $stmt print "A $animalName has $intelligence intelligence./n" else print 'Sorry, no records found.' /清除語句源 mysqli_stmt_close( $stmt ; mysqli_close( $connect ; ? 在上面的片斷中,首先收集用戶提交的輸入內(nèi)容并建立數(shù)據(jù)庫連接
37、。然后,使用 mysqli_prepare(函數(shù)創(chuàng)建一個(gè)查詢語句源-在此命名為$stmt 以反映使用它的 函數(shù)的名稱。這個(gè)函數(shù)使用了兩個(gè)參數(shù):連接資源和一個(gè)字符串(每當(dāng)你使用擴(kuò) 展插入一個(gè)值時(shí),"?"標(biāo)記被插入到其中)。在本例中,你僅有一個(gè)這樣的值動物的名字。 注意, 在一個(gè) SELECT 語句中,放置"?"標(biāo)記的唯一的有效位置是在值比較部 分。這正是為什么你不需要指定使用哪個(gè)變量的原因(除了在 mysqli_stmt_bind_param(函數(shù)中之外)。在此,你還需要指定它的類型-在本 例中,"s"代表字符串。其它可能的類型有:&q
38、uot;I"代表整數(shù),"d"代表雙精度數(shù)(或 浮點(diǎn)數(shù),而"b"代表二進(jìn)制字符串。 函數(shù) mysqli_stmt_execute(,mysqli_stmt_bind_result(和 mysqli_stmt_fetch(負(fù)責(zé)執(zhí)行查詢并檢索結(jié)果。如果存在檢索結(jié)果,則顯示它 們;如果不存在結(jié)果,則顯示一條無害的消息。最后,你需要關(guān)閉$stmt 資源以 及數(shù)據(jù)庫連接-從內(nèi)存中對它們加以釋放。 假定一個(gè)合法的用戶輸入了字符串"lemming", 那么這個(gè)例程將(假定是數(shù)據(jù) 庫中適當(dāng)?shù)臄?shù)據(jù)輸出消息"A lemming has
39、very low intelligence."。假定存 在一個(gè)嘗試性注入-例如"lemming' or 1=1;",那么這個(gè)例程將打印(無害消息 "Sorry, no records found."。 此外,mysqli 擴(kuò)展還提供了一個(gè)面向?qū)ο蟀姹镜南嗤睦?。下面,我們想說 明這種版本的使用方法。 ?php $animalName = $_POST'animalName' $mysqli = new mysqli( 'localhost', 'username', 'password', 'database' if ( !$mysqli exit( 'connection failed: ' . mysqli_connect_error( ; $s
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 執(zhí)行案件代理合同(2篇)
- 八年級上冊道德與法治第二單元 遵守社會規(guī)則 復(fù)習(xí)聽課評課記錄
- 冀教版歷史九年級上冊第2課《古代印度文明》聽課評課記錄
- 新版(修訂版)北師大版小學(xué)五年級數(shù)學(xué)下冊聽評課記錄精寫
- 蘇科版數(shù)學(xué)八年級上冊4.3《實(shí)數(shù)》聽評課記錄2
- 湘教版數(shù)學(xué)七年級上冊《2.5整式的加法和減法(1)》聽評課記錄5
- 蘇教版數(shù)學(xué)九年級上冊聽評課記錄《2-1圓(2)》
- 蘇科版數(shù)學(xué)八年級上冊《4.2 立方根》聽評課記錄
- 華師大版歷史九年級上冊第6課《古希臘羅馬文化》聽課評課記錄
- 人民版道德與法治七年級上冊5.1《心中有他人》聽課評課記錄
- 礦井主要災(zāi)害事故防治應(yīng)急避災(zāi)知識培訓(xùn)課件
- 不老莓行業(yè)分析
- STARCCM基礎(chǔ)培訓(xùn)教程
- 2016-2023年婁底職業(yè)技術(shù)學(xué)院高職單招(英語/數(shù)學(xué)/語文)筆試歷年參考題庫含答案解析
- 貴陽市2024年高三年級適應(yīng)性考試(一)一模英語試卷(含答案)
- 地理標(biāo)志專題通用課件
- 全國大學(xué)高考百科匯編之《哈爾濱工業(yè)大學(xué)》簡介
- 《小英雄雨來》讀書分享會
- 學(xué)校安全教育教你如何遠(yuǎn)離危險(xiǎn)
- 【人教版】九年級化學(xué)上冊全冊單元測試卷【1-7單元合集】
- 口腔科導(dǎo)診分診技巧(PPT課件)
評論
0/150
提交評論