今天早些时候,有人问了一个关于input validation strategies in web apps的问题.

在 compose 本文时,最重要的答案是建议在PHP中只使用htmlspecialcharsmysql_real_escape_string.

我的问题是:这总是足够吗?还有更多我们应该知道的吗?这些功能在哪里失效?

推荐答案

当涉及到数据库查询时,总是try 使用预先准备好的参数化查询.mysqliPDO个库支持这一点.这比使用转义函数(如mysql_real_escape_string)安全得多.

是的,mysql_real_escape_string实际上只是一个字符串转义函数.这不是一颗神奇的子弹.它所做的一切就是对危险字符进行转义,以便在单个查询字符串中可以安全地使用这些字符.但是,如果您不事先清理您的输入,那么您将容易受到某些攻击媒介的攻击.

想象一下下面的SQL:

$result = "SELECT fields FROM table WHERE id = ".mysql_real_escape_string($_POST['id']);

您应该能够看到,这很容易被利用

1 OR 1=1

那里没有危险的字符需要编码,所以它会直接通过转义过滤器.留给我们:

SELECT fields FROM table WHERE id= 1 OR 1=1

这是一个可爱的SQL注入向量,允许攻击者返回所有行.

1 or is_admin=1 order by id limit 1

产生

SELECT fields FROM table WHERE id=1 or is_admin=1 order by id limit 1

这使得攻击者可以在这个完全虚构的示例中返回第一位管理员的详细信息.

虽然这些功能很有用,但必须小心使用.您需要确保所有web输入都在一定程度上得到验证.在本例中,我们发现我们可以被利用,因为我们没有判断作为数字使用的变量是否是数字.在PHP中,您应该广泛使用一组函数来判断输入是否为整数、浮点数、字母数字等.但在SQL中,最重要的是要注意准备好的语句的值.如果上面的代码是一条预先准备好的语句,那么它是安全的,因为数据库函数会知道1 OR 1=1不是有效的文本.

至于htmlspecialchars().那是它自己的雷区.

PHP中存在一个真正的问题,它有一整套不同的html相关转义函数可供 Select ,但对于哪些函数做什么没有明确的指导.

首先,如果你在一个HTML标签中,你会遇到真正的麻烦.看看

echo '<img src= "' . htmlspecialchars($_GET['imagesrc']) . '" />';

We're already inside an HTML tag, so we don't need < or > to do anything dangerous. Our attack vector could just be javascript:alert(document.cookie)

现在生成的HTML看起来像

<img src= "javascript:alert(document.cookie)" />

攻击直接进行.

情况变得更糟了.为什么?因为htmlspecialchars(这样调用时)只编码双引号,而不是单引号.所以如果我们有

echo "<img src= '" . htmlspecialchars($_GET['imagesrc']) . ". />";

我们邪恶的攻击者现在可以注入全新的参数

pic.png' onclick='location.href=xxx' onmouseover='...

给了我们

<img src='pic.png' onclick='location.href=xxx' onmouseover='...' />

在这些情况下,没有灵丹妙药,您只需自己删除输入即可.如果你试图用过滤剔除坏人,你肯定会失败.采用白名单的方法,只让好的字符通过.请看XSS cheat sheet个示例,了解向量的多样性

即使使用htmlspecialchars($string)个HTML标记之外的标记,也仍然容易受到多字节字符集攻击向量的攻击.

最有效的方法是结合使用mb_convert_编码和htmlentities,如下所示.

$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');
$str = htmlentities($str, ENT_QUOTES, 'UTF-8');

即使这样,IE6也很脆弱,因为它处理UTF的方式.然而,在IE6使用率下降之前,您可以退回到更有限的编码方式,如ISO-8859-1.

有关多字节问题的更深入研究,请参见https://stackoverflow.com/a/12118602/1820

Php相关问答推荐

Woocommerce显示特定产品的自定义 checkout 字段

在WooCommerce中执行一次银行电汇确认付款代码

WooCommerce数量减号和加号图标未显示

WordPress插件和JSON不是有效的响应错误

当配置的URL为空时禁用Laravel Slack日志(log)记录

在WordPress中从CPT中删除插件

WooCommerce在收据页面获取产品下载URL

Symfony框架锁定和.env设置

如何在PHP中根据会话将用户重定向到不同的页面?

$this->;db->;update();CodIgnitor中的功能不工作

无法读取某些 WordPress 主机上的 cookie

PHP 简单 XML Xpath 上移树(带有名称的父级)

注册命名空间后如何获取xml node 值?

基于WooCommerce中的产品变体自定义感谢页面跳转

如何在WooCommerce中为访客购买者分配自定义客户代码

PHP 合并/合并多维数组

如何使用相同的变量使函数参数对于数组和字符串都是可选的

为什么在解压缩具有混合字符串和 int 键的关联数组时出现错误消息无法使用位置参数...?

按前 3 列对二维数组中的行数据进行分组,然后用逗号连接每组中的其余列

为什么可以从 PHP 类访问 PHP Trait 的私有成员?