6

我想在我的 Web 应用程序中防止 XSS 攻击。我发现 HTML Encoding 输出确实可以防止 XSS 攻击。现在的问题是我如何对应用程序中的每个输出进行 HTML 编码?我有办法自动化吗?

我感谢 JSP、ASP.net 和 PHP 的答案。

4

11 回答 11

9

您不应该做的一件事是在输入数据进入时对其进行过滤。人们经常建议这样做,因为它是最简单的解决方案,但会导致问题。

输入数据可以发送到多个地方,除了作为 HTML 输出。例如,它可能存储在数据库中。过滤发送到数据库的数据的规则与过滤 HTML 输出的规则有很大的不同。如果您在输入时对所有内容进行 HTML 编码,那么您最终会在数据库中使用 HTML。(这也是为什么 PHP 的“魔术引号”功能是个坏主意的原因。)

您无法预测输入数据将经过的所有地方。安全的方法是在数据发送到某个地方之前准备好数据。如果要将其发送到数据库,请转义单引号。如果要输出 HTML,请转义 HTML 实体。一旦它被发送到某个地方,如果您仍然需要处理数据,请使用原始的未转义版本。

这是更多的工作,但您可以通过使用模板引擎或库来减少它。

于 2008-09-13T17:02:05.707 回答
4

您不想对所有 HTML 进行编码,您只想对您输出的任何用户输入进行 HTML 编码。

对于 PHP:htmlentitieshtmlspecialchars

于 2008-09-12T11:31:31.390 回答
3

对于 JSP,您也可以使用 c:out 标签,它默认转义 XML。这意味着您可以将属性绑定为原始元素:

<input name="someName.someProperty" value="<c:out value='${someName.someProperty}' />" />

当绑定到字符串时, someName.someProperty 将包含 XML 输入,但是当输出到页面时,它会自动转义以提供 XML 实体。这对于页面验证的链接特别有用。

于 2008-09-16T02:48:24.890 回答
1

我用来转义所有用户输入的一个好方法是为 smarty 编写一个修饰符,它转义传递给模板的所有变量;附有 |unescape 的除外。这样,您只授予对您明确授予访问权限的元素的 HTML 访问权限。

我没有那个修饰符了;但在这里可以找到大约相同的版本:

http://www.madcat.nl/martijn/archives/16-Using-smarty-to-prevent-HTML-injection..html

在新的 Django 1.0 版本中,它的工作方式完全相同,杰伊 :)

于 2008-09-12T11:57:59.487 回答
1

您可以将 echo / print 等包装在您自己的方法中,然后您可以使用这些方法来转义输出。即代替

echo "blah";

采用

myecho('blah');

如果需要,您甚至可以设置第二个参数来关闭转义。

在一个项目中,我们在输出函数中有一个调试模式,它使通过我们方法的所有输出文本不可见。然后我们知道屏幕上留下的任何东西都没有逃脱!追踪那些顽皮的未转义位非常有用:)

于 2008-09-12T12:11:28.347 回答
1

我个人的偏好是认真编码来自数据库、业务层或来自用户的任何内容。

在 ASP.Net 中,这是通过使用Server.HtmlEncode(string).

对任何内容进行编码的原因是,即使您可能认为是布尔值或数字的属性也可能包含恶意代码(例如,复选框值,如果它们执行不当可能会以字符串形式返回。如果您之前没有对它们进行编码将输出发送给用户,那么你就有了漏洞)。

于 2008-09-12T13:23:44.007 回答
0

如果您确实对每个输出进行了 HTML 编码,用户将看到 <html> 的纯文本。而不是一个正常运行的网络应用程序。

编辑:如果你对每一个输入进行 HTML 编码,你将无法接受包含 < 等的外部密码。

于 2008-09-12T11:18:23.717 回答
0

真正保护自己免受此类攻击的唯一方法是严格过滤您接受的所有输入,特别是(但不完全是)来自应用程序公共区域的输入。我建议您看一下 Daniel Morris 的PHP 过滤类(一个完整的解决方案)以及Zend_Filter包(您可以用来构建自己的过滤器的类的集合)。

在 Web 开发方面,PHP 是我选择的语言,因此对我的回答中的偏见表示歉意。

基兰。

于 2008-09-12T14:19:54.887 回答
0

Joel 有一篇关于软件的好文章(我认为让错误的代码看起来不正确,我在手机上,否则我会有一个 URL 给你),其中涵盖了匈牙利符号的正确使用。简短的版本将类似于:

Var dsFirstName, uhsFirstName : String;

Begin

uhsFirstName := request.queryfields.value['firstname'];

dsFirstName := dsHtmlToDB(uhsFirstName);

基本上用“us”作为不安全字符串的前缀,“ds”作为数据库安全的前缀,“hs”作为 HTML 安全的前缀。您只想在实际需要的地方进行编码和解码,而不是全部。但是通过使用它们的前缀来推断有用的含义,查看您的代码,如果有什么不对劲,您会很快发现。无论如何,您将需要不同的编码/解码功能。

于 2008-09-13T17:54:51.040 回答
0

输出编码是迄今为止最好的防御。验证输入的好处有很多,但不是 100% 的防御。如果数据库通过攻击(即 ASPROX)感染了 XSS,错误或恶意输入验证将不起作用。输出编码仍然有效。

于 2011-02-01T00:06:02.160 回答
0

OWASP 有一个很好的 API 来编码 HTML 输出,既可以用作 HTML 文本(例如段落或<textarea>内容),也可以用作属性的值(例如<input>拒绝表单后的标签):

encodeForHTML($input) // Encode data for use in HTML using HTML entity encoding
encodeForHTMLAttribute($input) // Encode data for use in HTML attributes.

该项目(PHP 版本)托管在http://code.google.com/p/owasp-esapi-php/下,也可用于其他一些语言,例如 .NET。

请记住,您应该对所有内容(不仅是用户输入)进行编码,而且应该尽可能晚地进行编码(不是在存储在数据库中时,而是在输出 HTTP 响应时)。

于 2012-01-16T11:51:11.633 回答