echo("<body><form id=\"myFrom\" action=\"" . $_SERVER['PHP_SELF'] .
"\" method=\"post\">");
echo("<div><input type=\"text\" name=\"fileName\" value=\"");
echo(isset($_REQUEST['fileName']) ? $_REQUEST['fileName'] : '');
echo("\" />");
echo("<input type=\"submit\" value=\"Download\" name=\"submit\" /></div>");
echo("</form></body></html>");
}[/php]
正如您所见,清单 1
中比较危险的脚本将处理 Web 服务器拥有读取权限的所有文件,包括会话目录中的
“
”
文件(请参阅
保护会话数据 ),甚至还包括一些系统文件(例如 /etc/passwd)。为了进行演示,这
个示例使用了一个可供用户键入文件名的文本框,但是可以在查询字符串中轻松地提供文件名。
同时配置用户输入和文件系统访问权十分危险,因此最好把应用程序设计为使用数据库和隐藏生成的文件名
来避免同时配置。但是,这样做并不总是有效。清单 2 提供了验证文件名的示例例程。它将使用正则表达
式以确保文件名中仅使用有效字符,并且特别检查圆点字符:..。
清单 2. 检查有效的文件名字符
[php]
function isValidFileName($file) {
/* don't allow .. and allow any "word" character \ / */
return preg_match('/^(((?:\.)(?!\.))|\w)+$/', $file);
}[/php]
保护数据库
2008
年 4
月,美国某个州的狱政局在查询字符串中使用了 SQL 列名,因此泄露了保密数据。这次泄露
允许恶意用户选择需要显示的列、提交页面并获得数据。这次泄露显示了用户如何能够以应用程序开发人员
无法预料的方法执行输入,并表明了防御 SQL 注入攻击的必要性。
清单 3
显示了运行 SQL 语句的示例脚本。在本例中,SQL 语句是允许相同攻击的动态语句。此表单的所
有者可能认为表单是安全的,因为他们已经把列名限定为选择列表。但是,代码疏忽了关于表单欺骗的最后
—
一个习惯
代码将选项限定为下拉框并不意味着其他人不能够发布含有所需内容的表单(包括星号
[*])。
清单 3.
执行 SQL 语句
[php]
<html>
<head>
<title>SQL Injection Example</title>
</head>
<body>
<form id="myFrom" action="<?php echo $_SERVER['PHP_SELF']; ?>"
method="post">
<div><input type="text" name="account_number"
value="<?php echo(isset($_POST['account_number']) ?
$_POST['account_number'] : ''); ?>" />
<select name="col">
<option value="account_number">Account Number</option>
<option value="name">Name</option>
<option value="address">Address</option>
</select>
<input type="submit" value="Save" name="submit" /></div>
</form>
<?php
if ($_POST['submit'] == 'Save') {
/* do the form processing */
$link = mysql_connect('hostname', 'user', 'password') or