注入攻擊-SQL注入和代碼注入

注入攻擊

OWASP將注入攻擊和跨站腳本攻擊(XSS)列入網絡應用程序十大常見安全風險。實際上,它們會一塊兒出現,由於 XSS 攻擊依賴於注入攻擊的成功。雖然這是最明顯的組合關係,可是注入攻擊帶來的不只僅是 XSS。php

注入攻擊代指一類攻擊,它們經過注入數據到一個網絡應用程序以期得到執行,亦或是經過非預期的一個方式來執行惡意數據。這種類別的攻擊包括跨站腳本攻擊(XSS)、SQL 注入攻擊、頭部注入攻擊、日誌注入攻擊和全路徑暴露。固然限於篇幅,這裏只是一個簡單的介紹。html

這類攻擊是每一個程序員的夢魘。它們數量龐大、攻擊範圍廣,而且有時候防護措施很複雜,所以是最多見、成功率最高的網絡攻擊。全部的應用程序都須要從某個地方獲取數據來運行。跨站腳本攻擊和界面假裝漏洞最爲常見,而且它們自己就已經很是重要,一般與注入攻擊分開歸類。接下來的一章我將單獨介紹它們。mysql

OWASP 對注入攻擊的定義以下:git

相似SQL、OS、LDAP注入攻擊等注入攻擊會在不可信數據做爲命令或請求的一部分被髮送到解釋程序時發生。攻擊者的惡意數據會迷惑解釋程序去執行非計劃的命令,或訪問非受權的數據。程序員

SQL 注入攻擊

目前最多見的注入攻擊形式是臭名昭著的 SQL 注入攻擊。SQL 注入攻擊不只常見,並且致命。我要特別強調,瞭解這種攻擊、實現攻擊的條件以及防護攻擊須要採起的措施極爲重要。sql

SQL 注入攻擊經過將數據注入網絡應用程序,而後被用於 SQL 請求來操做。數據一般來自相似網頁表單的不可信來源。不過,數據也可能來自包括數據庫自己在內的其餘來源。程序員一般會信任來自本身數據庫的數據,覺得它們是很是安全的,卻沒有意識到,在一種用法中安全,不表明它在全部其餘用法中都是安全的。來自數據庫在通過證實(好比說,經過驗證流程)以前,應該被視爲不可信。數據庫

若是攻擊成功,SQL 注入攻擊可以操縱受攻擊的 SQL 請求,從而進行非程序員意願的數據庫操做。api

看一下這條請求:瀏覽器

git·$db = new mysqli('localhost', 'username', 'password', 'storedb'); $result = $db->query( 'SELECT * FROM transactions WHERE user_id = ' . $_POST['user_id'] ); ·git安全

上面的請求中存在多處問題。首先,咱們尚未驗證 POST 數據來確保這是個有效的 user_id。其次,咱們容許一個不可信來源告訴咱們要使用哪一個 user_id——攻擊者能夠任意設置一個有效 user_id。也許 user_id 包含在一個隱藏的表單字段,由於網絡表單不容許編輯,咱們就覺得安全了(殊不知道攻擊者能夠提交任何信息)。第三,咱們並無 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 命令的目標包含如下幾種:

  1. 信息泄露

  2. 披露存儲數據

  3. 操縱存儲數據

  4. 避開權限管理

  5. 客戶端 SQL 注入攻擊

信息泄露

披露存儲數據

操縱存儲數據

避開權限管理

防護 SQL 注入攻擊

防護 SQL 注入攻擊可採用深度防護原則。在將數據用於 SQL 命令以前,應該進行驗證,以確保它是咱們指望的正確格式,而且在將數據包含在請求或綁定參數前,應該將其 escape。

驗證

第二章講述輸入驗證,並且正如我在其中提到的,咱們應該假設不是由當前請求的 PHP 源代碼直接生成的全部數據都不可信。對其嚴格驗證,而且拒絕全部未經過驗證的數據。不要嘗試「修復」數據,除非只是簡單修正數據格式。

常見的驗證錯誤包括只驗證數據當下用途(例如,展現或計算),卻不考慮數據最終存儲位置的數據庫表字段的驗證需求。

Escaping

經過使用mysqli 擴展,你能夠利用 mysqli_real_escape_string() 函數來 escape包含在 SQL 查詢中的全部數據。PostgresSQL 的 pgsql 擴展提供 pg_escape_bytea()、 pg_escape_identifier()、 pg_escape_literal() 和 pg_escape_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::PARAM_INT、 PDO::PARAM_BOOL、 PDO::PARAM_LOB 和 PDO::PARAM_STR。這種方法默認使用 PDO::PARAM_STR,所以記得對其餘數值作相應調整!

不一樣於手動 escape,這種方式下的參數綁定(或者你的數據庫使用的方法)會自動正確地 escape 綁定的數據,所以你不須要回憶以前用了哪一種 escape 函數。持續使用參數綁定要比記着手動 escape 全部東西要可靠得多。

強制實施最小特權原則

制止已經發生的 SQL 注入攻擊跟從一開始就防護一樣重要。一旦攻擊者得到執行 SQL 查詢的能力,他們就會以一個數據庫用戶的身份進行查詢。能夠經過確保全部數據庫用戶只獲得完成各自任務必需的權限,來執行最小特權原則。

若是一個數據庫用戶擁有很大的權限,攻擊者就可能刪除數據表,操縱其餘用戶的權限,從而發起其餘 SQL 注入攻擊。你絕對不能以超級用戶、其餘權限較高或管理員層級的用戶身份訪問網絡應用程序的數據庫,從而杜絕這種狀況發生。

最小特權原則的另一個變體是區別數據庫的讀數據和寫數據權限。你能夠設置一個擁有寫數據權限的用戶,和另外一個只有讀數據權限的用戶。這種角色區分能夠確保在 SQL 注入攻擊目標爲只讀用戶時,攻擊者沒法寫數據或操縱表數據。這種生物隔離區劃能夠延伸到進一步限制訪問權限,這樣就能夠將 SQL 注入攻擊的影響最小化。

不少網絡應用程序,尤爲是開源應用程序,特別被設計成只有一個數據庫用戶,並且幾乎歷來不會有人檢查該用戶是否是高度特免的。記住以上觀點,忍住誘惑,不要在一個管理員用戶下運行這樣的網絡應用程序。

代碼注入攻擊(也叫Remote File Inclusion)

代碼注入攻擊指的是任何容許攻擊者在網絡應用程序中注入源代碼,從而獲得解讀和執行的方法。這並不適用於對應用程序客戶端的代碼注入攻擊,例如 Javascript,那屬於跨站腳本攻擊(XSS)。

源代碼能夠經過不可信的輸入直接注入,或者網絡應用程序在經過本地文件系統或相似 URL 這樣的外部來源加載代碼時被操縱。包含遠程文件致使代碼注入攻擊的狀況一般被稱爲遠程文件包含漏洞,雖然遠程文件包含攻擊自己的目的就是爲了注入代碼。

形成代碼注入攻擊的初始緣由包括輸入驗證失敗,包含可能被當作 PHP 代碼、任何語境下的不可信輸入,未能保障源代碼庫的安全,在下載第三方程序庫時不夠謹慎,服務器配置不當致使非 PHP 文件經過網絡服務器被傳送到 PHP 解釋程序。最後一點尤爲要加以注意,由於它意味着不可信用戶上傳到服務器的全部文件均可能帶來極大的風險。

代碼注入攻擊範例

衆所周知,PHP 涉及無數代碼注入攻擊目標,所以任何一位程序員都要高度關注代碼注入攻擊問題。

文件包含攻擊

代碼注入攻擊最明顯的目標就是 include()、 include_once()、 require() 和 require_once() 函數。若是不可信輸入被容許來決定傳輸給這些函數的路徑參數,它就可能影響被包含的本地文件。應該注意的是,被包含的文件不必定是一個真正的 PHP 文件,任何可以攜帶文字數據(例如,幾乎全部的)的被包含文件都有可能。

路徑參數也可能遭受目錄遍歷攻擊或遠程文件包含攻擊。在路徑中使用 ../ 或 ..(dot-dot-slash) 字符串會讓攻擊者可以觸及 PHP 流程可以訪問的全部文件。除非 XXX 被禁用,不然以上函數還能接受 PHP 默認設置中的 URL。

評估

PHP 的 eval() 函數接收 PHP 代碼字符串並執行。

正則表示式注入攻擊

PHP 中 PCRE 的 preg_replace() 函數容許「e」(PREG_REPLACE_EVAL)修飾符,這就意味着替換字符串在替換後將被當成 PHP。用於替換字符串的不可信輸入可能會注入即將執行的 PHP 代碼。

缺陷文件包含邏輯攻擊

按照定義,網絡應用程序會包含知足各類需求所需的各種文件。經過操縱請求路徑或請求參數,它能夠利用服務器路由的缺陷邏輯、依賴管理、自動加載或其餘流程,致使服務器包含非預期的本地文件。

這些超出網絡應用程序設計初衷的操縱可能帶來沒法預料的影響。好比說,一個應用程序可能無心中暴露了只用於命令行用法的路徑。該應用程序可能還暴露了構造函數用來執行任務的其餘類(雖然並不推薦這種設計類的方法,不過仍是有人這麼作)。兩種場景都有可能干擾應用程序的後臺運行,致使原本不該該被直接訪問的資源密集型運行活動遭受數據操縱或拒絕服務攻擊(DOS)。

服務器配置不當

代碼注入攻擊的目標

因爲代碼注入攻擊容許攻擊者選擇任意 PHP 代碼來執行代碼注入攻擊的目標極其普遍。

防護代碼注入攻擊

命令注入攻擊

命令注入攻擊範例

防護命令注入攻擊

原文地址:Injection Attacks

本文系 OneAPM 工程師編譯整理。OneAPM 是應用性能管理領域的新興領軍企業,能幫助企業用戶和開發者輕鬆實現:緩慢的程序代碼和 SQL 語句的實時抓取。想閱讀更多技術文章,請訪問 OneAPM 官方博客

本文轉自 OneAPM 官方博客

相關文章
相關標籤/搜索