PHP网站中的安全策略:SQL注入、XSS攻击和二阶SQL注入
Posted
技术标签:
【中文标题】PHP网站中的安全策略:SQL注入、XSS攻击和二阶SQL注入【英文标题】:Security strategies in PHP website: SQL Injection, XSS attack and 2nd order SQL Injection 【发布时间】:2014-02-16 08:03:46 【问题描述】:我是网络安全领域的专家,已经研究了两天。根据 OWSAP,SQL 注入和 XSS 攻击是 Internet 上最常见的攻击,至少每个程序员都必须处理。
所以我理解的保护它们的内容如下(如果我错了,请您更正或添加):
Use PDO and prepared statements to prevent SQL Injection
PDO 和预处理语句足以防止(一阶)SQL 注入,我们不需要在驱动程序处理时对输入数据进行任何转义。
但是这可能会导致您容易发生二阶 SQL 注入 (see this for more),其中像 ' OR '1'='
这样的数据可能会在通过 PDO 和准备好的语句存储后存储到数据库中原始数据并防止这种情况让我觉得首先要转义字符串,因此
use $pdo->quote($string) before passing it to prepared statement for storage
但由于我还想防止 XSS 攻击,我也应该使用htmlentities()
(或htmlspecialchars()
,在最小情况下)。我应该在输出端执行此操作,但如果我的输出端我可能更喜欢在输入端使用仅针对 HTML
总而言之,我的步骤是
$string ='raw input from user';
$escaped_string=$pdo->quote(htmlentities($string));
$pdo->execute('query to store $escaped_string into the database');
输出时
只需从数据库中回显存储的字段。
我想知道我的方法是否安全?
【问题讨论】:
这是一个问题吗..? 是的,我想知道我的方法是否安全? @InsaneCoder 你的方法是一团糟......我在任何地方的代码中一次又一次地看到一个常见的错误。有关一些信息,请参阅我的回答,如果您对此有任何疑问,请具体询问。 还有:***.com/a/7810880/362536 【参考方案1】:如果您的代码容易受到二阶攻击,则说明您没有正确使用准备好的查询,并且根本不了解您在做什么。
在查询中转义数据的目的是消除命令中的数据歧义。在查询中使用参数的目的是从根本上将数据与命令分开。这两者都与数据在数据库中的存储方式完全无关。
每个查询都应该使用参数来表示其中使用的任意数据。如果您不这样做,您可能根本就没有保护,并且毫无疑问会在您的应用程序中出现错误。 始终对任意数据使用参数化查询(并实际使用这些参数),即使它来自您自己的数据库。谁在乎它来自哪里...如果您无法预测数据是什么,那么您就知道它不能直接在查询中使用。
关于 XSS 攻击...如果您正在输出 HTML 页面,您可以通过正确转义数据以在 HTML 上下文中使用来防止其中一些攻击。这允许您在保留文本的 HTML 上下文中使用任意字符串。这会转义 HTML 的数据,这意味着文本不会被解析为 HTML 标记。您应该只在输出时执行此转义...而不是在此之前,否则您会提前破坏数据并使其无法用于其他目的。
【讨论】:
感谢您的支持。但也许我不能在输出中使用htmlentities()
,因为我的数据库中以 HTML 形式存储了文章,例如`文章标题这是一篇文章
所以我想解析这样的标签。 考虑使用 BBCode 来避免使用 html 标签 @InsaneCoder 在这种情况下,您没有转义问题。 (您在 HTML 上下文中使用 HTML...不需要转义。)您有一个不同的问题,您需要将哪些标签列入白名单,但您需要非常小心,不要让语法错误可执行代码潜入。查看这篇文章:***.com/questions/5512712/sanitizing-html-input 不,您不一定需要使用 BBCode...更改语法并不能解决此问题。【参考方案2】:但这可能会导致您容易发生二阶 SQL 注入
这实际上可能不是。没有像“二阶 SQL 注入”这样的东西。只有 SQL 注入。为了防止它,您必须使用参数化查询。就这么简单。
总而言之,您的步骤是
$string ='whatever string';
$pdo->prepare('any query that uses ? placeholder for any data');
$pdo->execute([$string]);
在输出时,让您的 模板 默认对任何值进行 html 转义,或者在明确告知时应用任何其他格式 - 即,为 html 格式的文本设置原始格式。
【讨论】:
【参考方案3】:如果您无法避免从用户那里获取原始输入,这是标准程序,如果可能的话,请避免使用来自用户的原始输入。例如:
最好对这些类型的事情使用存储过程。
<?php
if(isset($_POST['submit']))
if($_GET['sort'] == 'alphad')
$sort = 'alphad'; //not = $_GET['sort']
//Your query
?>
【讨论】:
当然,如果您的应用程序什么都不做,那么请继续执行并且不接受来自用户的数据。而且,存储过程不是解决这个问题的合适方法。 不要相信我曾经说过不允许来自用户的数据,这是处理此类任意数据时的最佳程序。 不是。实际上,您的代码示例对处理任意数据没有任何作用。您将一组特定的数据列入白名单。虽然我同意白名单很棒,但它很少适用。我是说准备好的查询绝对是您应该使用的。以上是关于PHP网站中的安全策略:SQL注入、XSS攻击和二阶SQL注入的主要内容,如果未能解决你的问题,请参考以下文章
如何实现php的安全最大化?怎样避免sql注入漏洞和xss跨站脚本攻击漏洞