【发布时间】:2011-02-16 23:13:03
【问题描述】:
我正在使用 php、mysql 和 smarty 以及用户可以放置 cmets 等的地方。在插入数据库进行 SQL 注入之前,我已经对字符进行了转义。我还需要做什么?
【问题讨论】:
标签: sql-injection security xss
我正在使用 php、mysql 和 smarty 以及用户可以放置 cmets 等的地方。在插入数据库进行 SQL 注入之前,我已经对字符进行了转义。我还需要做什么?
【问题讨论】:
标签: sql-injection security xss
XSS 主要是关于 HTML 转义(*)。每当您将纯文本字符串放入 HTML 页面时,无论该文本来自数据库、直接来自用户输入、来自文件还是完全来自其他地方,您都需要对其进行转义。
最小的 HTML 转义是将所有 & 符号转换为 & 并将所有 < 符号转换为 <。当您将某些内容放入属性值时,您还需要转义用于分隔属性的引号字符,通常是" 到"。总是转义两个引号(" 和单引号撇号')并没有什么坏处,有些人也将> 转义为>,尽管这仅在 XHTML 中的一个极端情况下是必需的。
任何好的面向网络的语言都应该提供一个功能来为你做这件事。例如在 PHP 中是 htmlspecialchars():
<p> Hello, <?php htmlspecialchars($name); ?>! </p>
在 Smarty 模板中,它是 escape 修饰符:
<p> Hello, {$name|escape:'html'}! </p>
真的,因为 95% 的时间都需要 HTML 转义(允许包含原始 HTML 标记相对较少),这应该是默认设置。较新的模板语言已经认识到,选择加入 HTML 转义是一个巨大的错误,会导致无限的 XSS 漏洞,因此默认情况下 HTML 转义。
您可以通过将 default modifiers 更改为 html 来使 Smarty 表现得像这样。 (不要像他们建议的那样使用htmlall,除非你真的知道你在做什么,否则它可能会搞砸你所有的非ASCII字符。)
无论您做什么,都不要在输入的 HTML 被处理或放入数据库之前陷入常见的 PHP 错误,即 HTML 转义或“清理”输入。这是执行输出级编码的错误位置,会给您带来各种问题。如果您想验证您的输入以确保它是特定应用程序所期望的,那很好,但在此阶段清除或转义“特殊”字符是不合适的。
*:XSS 的其他方面存在于 (a) 您实际上 想要 允许用户发布 HTML,在这种情况下,您必须将其缩减为可接受的元素和属性,这是复杂的过程通常由 HTML Purifier 之类的库完成,即使这样也有漏洞。另一种更简单的标记方案可能会有所帮助。 (b) 当您允许用户上传文件时,这很难保证安全。
【讨论】:
关于 SQL 注入,转义是不够的 - 您应该尽可能使用数据访问库和参数化查询。
对于 XSS(跨站脚本),从 html 编码输出数据开始。同样,反 XSS 库是您的朋友。
当前的一种方法是只允许非常有限数量的标签进入并清理流程中的标签(白名单 + 清理)。
【讨论】:
您需要确保人们不能在他们的 cmets 中发布 JavaScript 代码或可怕的 HTML。我建议您禁止使用非常基本的标记。
如果 cmets 不应该包含任何标记,则做一个
echo htmlspecialchars($commentText);
应该足够了,但它非常粗糙。最好在将所有输入放入数据库之前对其进行清理。 PHP strip_tags() 函数可以帮助您入门。
如果您想允许 HTML cmets,但要确保安全,您可以试试 HTML Purifier。
【讨论】:
您不应在将用户输入的数据放入数据库之前对其进行修改。修改应该在您将其输出到网站时进行。您不想丢失原始数据。
当您将其发送到网站时,您希望使用 htmlspecialchars("my output & stuff", ENT_QUOTES, 'UTF-8') 之类的方式将特殊字符转义为 HTML 代码——确保指定您正在使用的字符集。该字符串将被翻译成my output &amp; stuff 供浏览器读取。
【讨论】:
防止 SQL 注入的最佳方法就是不使用接受用户输入的动态 SQL。相反,将输入作为参数传递;这样它将是强类型的并且不能注入代码。
【讨论】: