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