程式碼注入

程式碼注入是因處理無效資料的而引發的程式錯誤。程式碼注入可被攻擊者用來匯入程式碼到某特定的電腦程式，以改變程式的執行程序或目的。程式碼注入攻擊的結果可以是災難性的。例如說：程式碼注入可作為許多電腦蠕蟲繁殖的溫床。程式碼注入是對因處理無效資料而引起的計算機錯誤的利用。攻擊者使用注入將程式碼引入到易受攻擊的電腦程式中並更改執行過程。成功的程式碼注入的結果可能是災難性的，例如允許電腦病毒或電腦蠕蟲傳播。當應用程式向直譯器傳送不受信任的資料時，就會出現程式碼注入漏洞。注入缺陷最常見於 SQL、LDAP、XPath、NoSQL 查詢、作業系統命令、XML 解析器、SMTP 標頭、程式引數等。檢查原始碼時注入缺陷往往比透過測試更容易發現。[1]掃描器和模糊器可以幫助發現注入缺陷。注入可能導致資料遺失或損壞、缺乏責任或拒絕存取。注入有時會導致主機完全接管。概說及例子.舉例說，有一間公司的網頁伺服器上有一個簽名簿的程式碼，用來讓使用者發表簡短的口信，例如：不過，這個程式碼原來有漏洞。一個意圖入侵者得悉這間公司採用了有問題的程式碼，於是試圖透過留下一條附帶有程式碼的口信，例如：如果另一個使用者檢視了該頁，被注入的程式碼即執行。該程式碼可讓攻擊者扮裝成另一個使用者。然而這個相同的軟體臭蟲可被使用者意外的觸發，亦即造成該網站暴露 HTML 程式碼。在這個案例裡表情符號可造成 HTML 程式碼不對稱，因為不對稱的HTML標籤被注入到程式碼裡。大部分這類的問題與哪些可能輸入資料，或者特殊資料效果的錯誤假設相關。一些軟體開發員可能犯下危險假設的經典範例如下：程式碼注入的用途.蓄意的用途.惡意使用.程式碼注入的使用一般被視為心懷惡意的舉動，而它確實常常如此。透過程式碼注入技術在黑或者破解系統上，以取得資訊、提權、或者非法存取某系統是相當流行的。惡意用途的程式碼注入可包括：善意使用.某些人可能會出於善意而使用程式碼注入。例如，透過程式碼注入以改變或者除錯某程式或者系統的行為可以「擺弄」系統以某種方式表現其行為而不懷任何惡意。打比方說：這些人訴諸此種替代手段大致是下面幾種原因之一：一般開發社群對以此為目的的程式碼注入不表歡迎。他們稱這種行為為三腳貓、半調子、或者駭 / 黑程式。(kludge or hack)某些開發者允許或者甚至表揚程式碼注入的使用來「加強」他們的軟體；通常是因為該方案提供了較不昂貴的方式來實現新的或者特殊化的功能。不幸的是，其副作用與無法列管的蘊含式可能相當危險。一般來說，即使相當善意的程式碼注入使用都不被建議使用。非蓄意的用途.某些使用者可能會不經意進行程式碼注入，因為他們對程式提供的輸入，沒列在當初開發系統者的考慮中。例如：避免程式碼注入.要避免程式碼注入的種種問題，得充分發揮輸入輸出處理保全，例如：程式碼注入範例.SQL注入.SQL注入是種乘SQL語法之利，注入可讀取或者修改資料庫、或者扭曲原始查詢意義的命令。以一個網頁有兩個欄位讓使用者輸入使用者名稱與密碼為例，在該網頁幕後工作的程式碼會產生SQL查詢以檢查密碼是否與使用者名稱稱密碼列表相符：SELECT UserList.UsernameFROM UserListWHERE UserList.Username = 'Username'AND UserList.Password = 'Password'如果這查詢有回應行數，便允許該存取。然而，如果惡意使用者鍵入合法使用者名稱，並且在密碼欄注入某些合法程式碼 (codice_2)，查詢結果便如下所示：SELECT UserList.UsernameFROM UserListWHERE UserList.Username = 'Username'AND UserList.Password = 'password' OR '1'='1'在上面範例裡，"Password"被假定為空白或者某個無害的字串。"codice_3"邏輯式將永遠為真，並且找到多少行就回應多少行，因此存取就被允許了。該技術可被精練成允許執行多重陳述，甚或載入外部程式。PHP注入."PHP注入"、"ASP注入"、以及其他類似技術術語是創造來泛指其他種種允許攻擊者直接對伺服器指令碼引擎提供程式碼的程式碼注入攻擊。在"PHP注入"例項裡，伺服端指令碼引擎是PHP。實際上，PHP注入是「動態賦值安全隱患」、「包含檔案注入」、或者類似程式碼注入的安全隱患。動態賦值安全隱患.mitre.org的史蒂芬克利斯第 (Steven M. Christey)提議以這個名字作為這型別的程式碼注入安全隱患。動態賦值安全隱患 - Eval注入.eval注入安全隱患發生在攻擊者可控制所有或者部份作為「餵」給codice_4函式呼叫的輸入字串。$myvar = 'somevalue';$x = $_GET['arg'];eval('$myvar = ' . $x . ';');"codice_5"的引數將會視同PHP處理，所以額外的命令可被新增。例如：如果"arg"如果被設成"codice_6"，後面的"codice_7"程式碼將被執行，這等同在伺服器上執行開發者意料外的程式。在這範例裡頭是"codice_8"。動態賦值安全隱患 - 動態變數賦值.如在"Dynamic Evaluation Vulnerabilities in PHP applications"一文所定義的：PHP支援 "變數的變數"，意指變數或者表示式可以對其他變數名賦值。這種特性可用來於程式執行時期動態改變哪個變數被存取或給值。這種特性是把雙刃劍：強大、便利、同時也很危險。許多程式有下面類似程式碼：$safevar = "0";$param1 = "";$param2 = "";$param3 = "";foreach ($_GET as $key =&gt; $value) {$$key = $value;如果攻擊者在查詢字串中給定"codice_9"，那codice_10將會被設為值 "bad"。動態賦值安全隱患 - 動態函式賦值.下面PHP範例將按照請求的方式執行函式。$myfunc = $_GET['myfunc'];$myfunc();以及：$myfunc = $_GET['myfunc'];${"myfunc"}();包含檔案注入.考慮下面的PHP程式(這裡包含了個檔案可因應需求改變)：$color = 'blue';if (__isset( $_GET['COLOR'] ) )$color = $_GET['COLOR'];require( $color . '.php' );開發者認為這樣大概可以保證只有 blue.php 和 red.php 可被載入。不過隨著任何人可在codice_11輕易的插入隨意值，造成以下檔案注入的可能性：Shell注入.Shell注入又稱命令列介面注入，它命名源於Unix Shell，不過可套用到大部分允許軟體程式化地執行命令列介面的系統上。常見的Shell注入資源有codice_17、codice_18、codice_19、codice_20以及類似的應用程式介面。考慮下面的簡短PHP程式。它執行一段叫做funnytext的外部程式，以置換使用者送出的許多其他單字：passthru ( " /home/user/phpguru/funnytext ". $_GET['USER_INPUT'] );該程式可以以多種方式被注入：註：命令指的是命令列介面下可供輸入執行的命令，例如視窗平臺的 dir、UNIX 平臺的 ls 等等。PHP提供codice_21和codice_22以在呼叫方法以前進行編碼。然而，實際上並不建議相信這些方法是安全的 - 同樣必須對輸入確認 / 消毒。HTML注入/指令碼注入 (跨網站指令碼).HTML注入/指令碼注入是個炒得相當熱的話題，一般專業術語為跨網站指令碼。XSS指的是一種依靠使用者輸入到網頁尾本，或者某些像程式碼行被置於輸出HTML，而沒有檢查HTML程式碼或指令碼的注入漏洞。這種注入有兩個基本型如下：這種型態的XSS漏洞比較不危險，因為使用者輸入被置於動態產生的網頁。伺服器端沒有任何改變。這種型態比較危險，因為輸入是寫在靜態網頁上，故威脅是持續性的。於IE7透過感染的動態連結函式庫(DLL)實行HTML注入.根據英國技術網站"The Register"的出，HTML注入亦可發生在使用者本身被有問題的DLL感染過的系統身上。該用羅傑湯森 (Roger Thompson) 的說法：受害者的瀏覽器，實際上，訪問了PayPal或其他類似的網站，甚或某動態連結檔案將它自己插入IE，並試著在交易進行中讀取並修改HTML。該及使用這種手段的釣魚攻擊順利規避IE7與賽門鐵克嘗試偵測可疑網站的努力。ASP注入."ASP注入"、"PHP注入"、以及其他類似技術術語是創造來泛指其他種種允許攻擊者直接對伺服器指令碼引擎提供程式碼的程式碼注入攻擊。在"ASP注入"例項裡，伺服端指令碼引擎是微軟Active Server Pages，一種微軟IIS的外加元件。在實際上與PHP相似，ASP注入也是「動態賦值安全隱患」、「包含檔案注入」、或者類似程式碼注入的安全隱患。範例：If Not IsEmpty(Request( "username" ) ) ThenConst ForReading = 1, ForWriting = 2, ForAppending = 8Dim fso, fSet fso = CreateObject("Scripting.FileSystemObject")Set f = fso.OpenTextFile(Server.MapPath( "userlog.txt" ), ForAppending, True)f.Write Request("username") &amp; vbCrLff.closeSet f = nothingSet fso = NothingServer.Execute( "userlog.txt" )ElseEnd If在這個範例中，使用者可用命令而非使用者名稱取代輸入。