《注入攻擊-SQL注入和代碼注入》要點(diǎn):
本文介紹了注入攻擊-SQL注入和代碼注入,希望對(duì)您有用。如果有疑問,可以聯(lián)系我們。
OWASP將注入攻擊和跨站腳本攻擊(XSS)列入網(wǎng)絡(luò)應(yīng)用程序十大常見安全風(fēng)險(xiǎn).實(shí)際上,它們會(huì)一起出現(xiàn),因?yàn)?XSS 攻擊依賴于注入攻擊的成功.雖然這是最明顯的組合關(guān)系,但是注入攻擊帶來的不僅僅是 XSS.
注入攻擊代指一類攻擊,它們通過注入數(shù)據(jù)到一個(gè)網(wǎng)絡(luò)應(yīng)用程序以期獲得執(zhí)行,亦或是通過非預(yù)期的一個(gè)方式來執(zhí)行惡意數(shù)據(jù).這種類別的攻擊包括跨站腳本攻擊(XSS)、SQL 注入攻擊、頭部注入攻擊、日志注入攻擊和全路徑暴露.當(dāng)然限于篇幅,這里只是一個(gè)簡(jiǎn)單的介紹.
這類攻擊是每個(gè)程序員的夢(mèng)魘.它們數(shù)量龐大、攻擊范圍廣,并且有時(shí)候防御措施很復(fù)雜,因此是最常見、成功率最高的網(wǎng)絡(luò)攻擊.所有的應(yīng)用程序都需要從某個(gè)地方獲取數(shù)據(jù)來運(yùn)行.跨站腳本攻擊和界面?zhèn)窝b漏洞最為常見,并且它們本身就已經(jīng)非常重要,通常與注入攻擊分開歸類.接下來的一章我將單獨(dú)介紹它們.
OWASP 對(duì)注入攻擊的定義如下:
類似SQL、OS、LDAP注入攻擊等注入攻擊會(huì)在不可信數(shù)據(jù)作為命令或請(qǐng)求的一部分被發(fā)送到解釋程序時(shí)發(fā)生.攻擊者的惡意數(shù)據(jù)會(huì)迷惑解釋程序去執(zhí)行非計(jì)劃的命令,或訪問非授權(quán)的數(shù)據(jù).
目前最常見的注入攻擊形式是臭名昭著的 SQL 注入攻擊.SQL 注入攻擊不僅常見,而且致命.我要特別強(qiáng)調(diào),了解這種攻擊、實(shí)現(xiàn)攻擊的條件以及防御攻擊需要采取的措施極為重要.
SQL 注入攻擊通過將數(shù)據(jù)注入網(wǎng)絡(luò)應(yīng)用程序,然后被用于 SQL 請(qǐng)求來操作.數(shù)據(jù)通常來自類似網(wǎng)頁(yè)表單的不可信來源.不過,數(shù)據(jù)也可能來自包括數(shù)據(jù)庫(kù)本身在內(nèi)的其他來源.程序員通常會(huì)信任來自自己數(shù)據(jù)庫(kù)的數(shù)據(jù),以為它們是非常安全的,卻沒有意識(shí)到,在一種用法中安全,不代表它在所有其他用法中都是安全的.來自數(shù)據(jù)庫(kù)在經(jīng)過證明(比如說,通過驗(yàn)證流程)之前,應(yīng)該被視為不可信.
如果攻擊成功,SQL 注入攻擊能夠操縱受攻擊的 SQL 請(qǐng)求,從而進(jìn)行非程序員意愿的數(shù)據(jù)庫(kù)操作.
看一下這條請(qǐng)求:
git·$db = new mysqli(‘localhost’, ‘username’, ‘password’, ‘storedb’); $result = $db->query( ‘SELECT * FROM transactions WHERE user_id = ‘ . $_POST[‘user_id’] ); ·git
上面的請(qǐng)求中存在多處問題.首先,我們還沒有驗(yàn)證 POST 數(shù)據(jù)來確保這是個(gè)有效的 userid.其次,我們?cè)试S一個(gè)不可信來源告訴我們要使用哪個(gè) userid——攻擊者可以任意設(shè)置一個(gè)有效 userid.也許 userid 包含在一個(gè)隱藏的表單字段,因?yàn)榫W(wǎng)絡(luò)表單不允許編輯,我們就以為安全了(卻不知道攻擊者可以提交任何信息).第三,我們并沒有 escape 該 user_id,或?qū)⑵渥鳛橐粋€(gè)綁定參數(shù)傳給請(qǐng)求,由于我們一開始沒有驗(yàn)證 SQL 請(qǐng)求,這就讓攻擊者有機(jī)會(huì)注入任意字符串來操縱該請(qǐng)求.
上述三點(diǎn)問題在網(wǎng)絡(luò)應(yīng)用程序中極其常見.
至于信任來自數(shù)據(jù)庫(kù)的數(shù)據(jù),想象一下我們使用 user_name 字段來搜索交易.用戶名的范圍相當(dāng)廣闊,可能還包含引用.可以想見,攻擊者可以在一個(gè)用戶名內(nèi)儲(chǔ)存一個(gè) SQL 注入字符串.如果我們將數(shù)據(jù)庫(kù)視為可信的數(shù)據(jù)來源,沒能合理地 escape 或約束它,當(dāng)我們?cè)诤罄m(xù)請(qǐng)求中再次使用該字符串時(shí),它就可以操縱請(qǐng)求字符串.
另一個(gè)需要注意的 SQL 注入攻擊因素是永久存儲(chǔ)不需要總是在服務(wù)器上進(jìn)行.HTML5 支持使用客戶端數(shù)據(jù)庫(kù),可以借助 Javascript 使用 SQL 來查詢.有兩個(gè)支持這項(xiàng)操作的接口:WebSQL 和 IndexedDB.WebSQL 于2010年被 W3C 棄用,受到后臺(tái)使用 SQLite 的 WebKit 瀏覽器支持.雖然這個(gè)接口不被推薦使用,但是 WebKit 處于后臺(tái)兼容考慮,很有可能會(huì)繼續(xù)支持它.正如它的名字所示,它接收 SQL 請(qǐng)求,因此容易遭受 SQL 注入攻擊.IndexedDB 是一個(gè)新的備選,不過它是一種 NOSQL 數(shù)據(jù)庫(kù)(不需要使用 SQL 查詢).
嘗試操縱 SQL 命令的目標(biāo)包含以下幾種:
防御 SQL 注入攻擊可采用深度防御原則.在將數(shù)據(jù)用于 SQL 命令之前,應(yīng)該進(jìn)行驗(yàn)證,以確保它是我們期望的正確格式,并且在將數(shù)據(jù)包含在請(qǐng)求或綁定參數(shù)前,應(yīng)該將其 escape.
第二章講述輸入驗(yàn)證,而且正如我在其中提到的,我們應(yīng)該假設(shè)不是由當(dāng)前請(qǐng)求的 PHP 源代碼直接生成的所有數(shù)據(jù)都不可信.對(duì)其嚴(yán)格驗(yàn)證,并且拒絕所有未通過驗(yàn)證的數(shù)據(jù).不要嘗試“修復(fù)”數(shù)據(jù),除非只是簡(jiǎn)單修正數(shù)據(jù)格式.
常見的驗(yàn)證錯(cuò)誤包括只驗(yàn)證數(shù)據(jù)當(dāng)下用途(例如,展示或計(jì)算),卻不考慮數(shù)據(jù)最終存儲(chǔ)位置的數(shù)據(jù)庫(kù)表字段的驗(yàn)證需求.
通過使用mysqli 擴(kuò)展,你可以利用 mysqlirealescapestring() 函數(shù)來 escape包含在 SQL 查詢中的所有數(shù)據(jù).PostgresSQL 的 pgsql 擴(kuò)展提供 pgescapebytea()、 pgescapeidentifier()、 pgescapeliteral() 和 pgescape_string() 函數(shù).Mssql(微軟 SQL 服務(wù)器)不提供 escaping 功能,而經(jīng)常被推薦的 addslashes() 方法并不夠用——你實(shí)際上需要一個(gè)定制功能http://stackoverflow.com/questions/574805/how-to-escape-strings-in-mssql-using-php.
再告訴你一件頭疼的事,你絕對(duì)絕對(duì)不能在 escape 進(jìn)入 SQL 查詢數(shù)據(jù)上出錯(cuò).一旦失手,可能就會(huì)引發(fā) SQL 注入攻擊.
基于以上原因,并不推薦使用 escaping.它可以用來救急,如果你用來抽象的數(shù)據(jù)庫(kù)程序庫(kù)不強(qiáng)制參數(shù)綁定就能進(jìn)行 SQL 查詢,可能就需要使用它.否則你應(yīng)該避免使用 escape.它很混亂,容易出錯(cuò),而且因數(shù)據(jù)庫(kù)擴(kuò)展不同而存在差異.
參數(shù)化或參數(shù)綁定是構(gòu)建 SQL 查詢的推薦方法,而且所有優(yōu)秀的數(shù)據(jù)庫(kù)程序庫(kù)都默認(rèn)使用這種方法.以下是使用 PHP 的 PDO 擴(kuò)展的一個(gè)實(shí)例.
if(ctype_digit($_POST['id']) && is_int($_POST['id']))
{
$validatedId = $_POST['id'];
$pdo = new PDO('mysql:store.db');
$stmt = $pdo->prepare('SELECT * FROM transactions WHERE user_id = :id');
$stmt->bindParam(':id', $validatedId, PDO::PARAM_INT);
$stmt->execute();
} else {
// reject id value and report error to user
}
PDO 語句可用的bindParam() 方法讓你可以給預(yù)處理語句中出現(xiàn)的占位符綁定參數(shù),并且接受基本的數(shù)據(jù)類型參數(shù),例如 PDO::PARAMINT、 PDO::PARAMBOOL、 PDO::PARAMLOB 和 PDO::PARAMSTR.這種方法默認(rèn)使用 PDO::PARAM_STR,因此記得對(duì)其他數(shù)值做相應(yīng)調(diào)整!
不同于手動(dòng) escape,這種方式下的參數(shù)綁定(或者你的數(shù)據(jù)庫(kù)使用的方法)會(huì)自動(dòng)正確地 escape 綁定的數(shù)據(jù),因此你不需要回憶之前用了哪種 escape 函數(shù).持續(xù)使用參數(shù)綁定要比記著手動(dòng) escape 所有東西要可靠得多.
制止已經(jīng)發(fā)生的 SQL 注入攻擊跟從一開始就防御同樣重要.一旦攻擊者獲得執(zhí)行 SQL 查詢的能力,他們就會(huì)以一個(gè)數(shù)據(jù)庫(kù)用戶的身份進(jìn)行查詢.可以通過確保所有數(shù)據(jù)庫(kù)用戶只得到完成各自任務(wù)必需的權(quán)限,來執(zhí)行最小特權(quán)原則.
如果一個(gè)數(shù)據(jù)庫(kù)用戶擁有很大的權(quán)限,攻擊者就可能刪除數(shù)據(jù)表,操縱其他用戶的權(quán)限,從而發(fā)起其他 SQL 注入攻擊.你絕對(duì)不能以超級(jí)用戶、其他權(quán)限較高或管理員層級(jí)的用戶身份訪問網(wǎng)絡(luò)應(yīng)用程序的數(shù)據(jù)庫(kù),從而杜絕這種情況發(fā)生.
最小特權(quán)原則的另外一個(gè)變體是區(qū)別數(shù)據(jù)庫(kù)的讀數(shù)據(jù)和寫數(shù)據(jù)權(quán)限.你可以設(shè)置一個(gè)擁有寫數(shù)據(jù)權(quán)限的用戶,和另一個(gè)只有讀數(shù)據(jù)權(quán)限的用戶.這種角色區(qū)分可以確保在 SQL 注入攻擊目標(biāo)為只讀用戶時(shí),攻擊者無法寫數(shù)據(jù)或操縱表數(shù)據(jù).這種生物隔離區(qū)劃可以延伸到進(jìn)一步限制訪問權(quán)限,這樣就可以將 SQL 注入攻擊的影響最小化.
很多網(wǎng)絡(luò)應(yīng)用程序,尤其是開源應(yīng)用程序,特別被設(shè)計(jì)成只有一個(gè)數(shù)據(jù)庫(kù)用戶,而且?guī)缀鯊膩聿粫?huì)有人檢查該用戶是不是高度特免的.記住以上觀點(diǎn),忍住誘惑,不要在一個(gè)管理員用戶下運(yùn)行這樣的網(wǎng)絡(luò)應(yīng)用程序.
代碼注入攻擊指的是任何允許攻擊者在網(wǎng)絡(luò)應(yīng)用程序中注入源代碼,從而得到解讀和執(zhí)行的方法.這并不適用于對(duì)應(yīng)用程序客戶端的代碼注入攻擊,例如 Javascript,那屬于跨站腳本攻擊(XSS).
源代碼可以通過不可信的輸入直接注入,或者網(wǎng)絡(luò)應(yīng)用程序在通過本地文件系統(tǒng)或類似 URL 這樣的外部來源加載代碼時(shí)被操縱.包含遠(yuǎn)程文件導(dǎo)致代碼注入攻擊的情況通常被稱為遠(yuǎn)程文件包含漏洞,雖然遠(yuǎn)程文件包含攻擊本身的目的就是為了注入代碼.
造成代碼注入攻擊的初始原因包括輸入驗(yàn)證失敗,包含可能被當(dāng)做 PHP 代碼、任何語境下的不可信輸入,未能保障源代碼庫(kù)的安全,在下載第三方程序庫(kù)時(shí)不夠謹(jǐn)慎,服務(wù)器配置不當(dāng)導(dǎo)致非 PHP 文件通過網(wǎng)絡(luò)服務(wù)器被傳送到 PHP 解釋程序.最后一點(diǎn)尤其要加以注意,因?yàn)樗馕吨豢尚庞脩羯蟼鞯椒?wù)器的所有文件都可能帶來極大的風(fēng)險(xiǎn).
眾所周知,PHP 涉及無數(shù)代碼注入攻擊目標(biāo),因此任何一位程序員都要高度關(guān)注代碼注入攻擊問題.
代碼注入攻擊最明顯的目標(biāo)就是 include()、 includeonce()、 require() 和 requireonce() 函數(shù).如果不可信輸入被允許來決定傳輸給這些函數(shù)的路徑參數(shù),它就可能影響被包含的本地文件.應(yīng)該注意的是,被包含的文件不一定是一個(gè)真正的 PHP 文件,任何能夠攜帶文字?jǐn)?shù)據(jù)(例如,幾乎所有的)的被包含文件都有可能.
路徑參數(shù)也可能遭受目錄遍歷攻擊或遠(yuǎn)程文件包含攻擊.在路徑中使用 ../ 或 ..(dot-dot-slash) 字符串會(huì)讓攻擊者能夠觸及 PHP 流程能夠訪問的所有文件.除非 XXX 被禁用,否則以上函數(shù)還能接受 PHP 默認(rèn)設(shè)置中的 URL.
PHP 的 eval() 函數(shù)接收 PHP 代碼字符串并執(zhí)行.
PHP 中 PCRE 的 pregreplace() 函數(shù)允許“e”(PREGREPLACE_EVAL)修飾符,這就意味著替換字符串在替換后將被當(dāng)成 PHP.用于替換字符串的不可信輸入可能會(huì)注入即將執(zhí)行的 PHP 代碼.
按照定義,網(wǎng)絡(luò)應(yīng)用程序會(huì)包含滿足各種需求所需的各類文件.通過操縱請(qǐng)求路徑或請(qǐng)求參數(shù),它可以利用服務(wù)器路由的缺陷邏輯、依賴管理、自動(dòng)加載或其他流程,導(dǎo)致服務(wù)器包含非預(yù)期的本地文件.
這些超出網(wǎng)絡(luò)應(yīng)用程序設(shè)計(jì)初衷的操縱可能帶來無法預(yù)料的影響.比如說,一個(gè)應(yīng)用程序可能無意中暴露了只用于命令行用法的路徑.該應(yīng)用程序可能還暴露了構(gòu)造函數(shù)用來執(zhí)行任務(wù)的其他類(雖然并不推薦這種設(shè)計(jì)類的方法,不過還是有人這么做).兩種場(chǎng)景都有可能干擾應(yīng)用程序的后臺(tái)運(yùn)行,導(dǎo)致本來不應(yīng)該被直接訪問的資源密集型運(yùn)行活動(dòng)遭受數(shù)據(jù)操縱或拒絕服務(wù)攻擊(DOS).
由于代碼注入攻擊允許攻擊者選擇任意 PHP 代碼來執(zhí)行代碼注入攻擊的目標(biāo)極其廣泛.
原文地址:Injection Attacks
轉(zhuǎn)載請(qǐng)注明本頁(yè)網(wǎng)址:
http://www.fzlkiss.com/jiaocheng/4541.html