代码注入

代码注入（）是因处理无效数据的而引发的程序错误。代码注入可被攻击者用来导入代码到某特定的电脑程式，以改变程式的执行进程或目的。代码注入攻击的结果可以是灾难性的。例如说：代码注入可作为许多电脑蠕虫繁殖的温床。
概说及例子.
举例说，有一间公司的网页伺服器上有一个签名簿的程式码，用来让用户发表简短的口信，例如：
不过，这个程式码原来有跨网站指令码漏洞。一个意图入侵者得悉这间公司采用了有问题的程式码，于是试图透过留下一条附带有程式码的口信，例如：
如果另一个用户检视了该页，被注入的代码即执行。该代码可让攻击者扮装成另一个用户。然而这个相同的软体臭虫可被使用者意外的触发，亦即造成该网站暴露 HTML 代码。
在这个案例里表情符号可造成 HTML 代码不对称，因为不对称的HTML标签被注入到代码里。
大部分这类的问题与哪些可能输入资料，或者特殊资料效果的错误假设相关。一些软体开发员可能犯下危险假设的经典范例如下：
代码注入的用途.
蓄意的用途.
恶意使用.
代码注入的使用一般被视为心怀恶意的举动，而它确实常常如此。透过代码注入技术在黑或者破解系统上，以取得信息、提权、或者非法存取某系统是相当流行的。
恶意用途的代码注入可包括：
善意使用.
某些人可能会出于善意而使用代码注入。例如，透过代码注入以改变或者调试某程式或者系统的行为可以「摆弄」系统以某种方式表现其行为而不怀任何恶意。打比方说：
这些人诉诸此种替代手段大致是下面几种原因之一：
一般开发社群对以此为目的的代码注入不表欢迎。他们称这种行为为三脚猫、半调子、或者骇 / 黑程式。(kludge or hack)
某些开发者允许或者甚至表扬代码注入的使用来「加强」他们的软体；通常是因为该方案提供了较不昂贵的方式来实现新的或者特殊化的功能。不幸的是，其副作用与无法列管的蕴含式可能相当危险。
一般来说，即使相当善意的代码注入使用都不被建议使用。
非蓄意的用途.
某些用户可能会不经意进行代码注入，因为他们对程式提供的输入，没列在当初开发系统者的考虑中。例如：
避免代码注入.
要避免代码注入的种种问题，得充分发挥输入输出处理保全，例如：
代码注入范例.
SQL注入.
SQL注入是种乘SQL语法之利，注入可读取或者修改资料库、或者扭曲原始查询意义的命令。
以一个网页有两个栏位让用户输入用户名与密码为例，在该网页幕后工作的代码会产生SQL查询以检查密码是否与用户名称密码列表相符：
SELECT UserList.Username
FROM UserList
WHERE UserList.Username = 'Username'
AND UserList.Password = 'Password'
如果这查询有回应行数，便允许该存取。然而，如果恶意用户键入合法用户名，并且在密码栏注入某些合法代码 (codice_2)，查询结果便如下所示：
SELECT UserList.Username
FROM UserList
WHERE 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程式(这里包含了个档案可因应需求改变)：
&lt;?php
 $color = 'blue';
 if (__isset( $_GET['COLOR'] ) )
 $color = $_GET['COLOR'];
 require( $color . '.php' );
&lt;form method="get"&gt;
 &lt;select name="COLOR"&gt;
 &lt;option value="red"&gt;red&lt;/option&gt;
 &lt;option value="blue"&gt;blue&lt;/option&gt;
 &lt;/select&gt;
 &lt;input type="submit"&gt;
&lt;/form&gt;
开发者认为这样大概可以保证只有 blue.php 和 red.php 可被载入。不过随著任何人可在codice_11轻易的插入随意值，造成以下档案注入的可能性：
Shell注入.
Shell注入又称命令行界面注入，它命名源于Unix Shell，不过可套用到大部分允许软体程式化地执行命令列介面的系统上。常见的Shell注入资源有codice_17、codice_18、codice_19、codice_20以及类似的应用程式介面。
考虑下面的简短PHP程式。它执行一段叫做funnytext的外部程式，以置换用户送出的许多其他单字：
&lt;?php
passthru ( " /home/user/phpguru/funnytext " 
 . $_GET['USER_INPUT'] );
该程式可以以多种方式被注入：
注：命令指的是命令行介面下可供输入执行的命令，例如视窗平台的 dir、UNIX 平台的 ls 等等。
PHP提供codice_21和codice_22以在呼叫方法以前进行编码。然而，实际上并不建议相信这些方法是安全的 - 同样必须对输入确认 / 消毒。
HTML注入/脚本注入 (跨网站指令码).
HTML注入/脚本注入是个炒得相当热的话题，一般专业术语为跨网站指令码（Cross-site scripting，通常简称为XSS）。XSS指的是一种依靠用户输入到网页脚本，或者某些像代码行被置于输出HTML，而没有检查HTML代码或脚本的注入漏洞。
这种注入有两个基本型如下：
于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" ) ) 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") &amp; vbCrLf
 f.close
 Set f = nothing
 Set fso = Nothing
 &lt;h1&gt;List of logged users:&lt;/h1&gt;
 &lt;pre&gt;
 Server.Execute( "userlog.txt" )
 &lt;/pre&gt;
 Else
 &lt;form&gt;
 &lt;input name="username" /&gt;&lt;input type="submit" name="submit" /&gt;
 &lt;/form&gt;
 End If
在这个范例中，用户可用命令而非用户名取代输入。