我想在我的网络应用程序中阻止XSS攻击。我发现HTML编码输出可以真正防止XSS攻击。现在的问题是我如何对我的应用程序中的每个输出进行HTML编码?我有办法实现自动化吗?
我很欣赏JSP,ASP.net和PHP的答案。
答案 0 :(得分:9)
你不应该做的一件事是过滤输入数据。人们经常建议这样做,因为它是最简单的解决方案,但它会导致问题。
输入数据除了作为HTML输出外,还可以发送到多个地方。例如,它可能存储在数据库中。过滤发送到数据库的数据的规则与过滤HTML输出的规则非常不同。如果您对输入中的所有内容进行HTML编码,则最终会在数据库中使用HTML。 (这也是为什么PHP的“魔术引号”功能是一个坏主意。)
您无法预测输入数据将传输的所有位置。安全的方法是准备之前的数据。如果您要将其发送到数据库,请转义单引号。如果要输出HTML,请转义HTML实体。一旦它被发送到某个地方,如果您仍然需要处理数据,请使用原始的未转义版本。
这是更多工作,但您可以通过使用模板引擎或库来减少它。
答案 1 :(得分:4)
您不想对所有HTML进行编码,您只想对要输出的任何用户输入进行HTML编码。
对于PHP:htmlentities和htmlspecialchars
答案 2 :(得分:3)
对于JSP,您可以使用c:out标记来获取蛋糕并使用它,默认情况下它会转义为XML。这意味着您可以将您的属性绑定为原始元素:
<input name="someName.someProperty" value="<c:out value='${someName.someProperty}' />" />
当绑定到字符串时,someName.someProperty将包含XML输入,但在输出到页面时,它将自动转义以提供XML实体。这对于页面验证的链接特别有用。
答案 3 :(得分:1)
我用来逃避所有用户输入的好方法是为smarty编写一个修饰符,以逃避传递给模板的所有变量;除了附有| unescape的那些。这样,您只能对您明确授予访问权限的元素进行HTML访问。
我不再拥有那个修饰符;但是可以在这里找到相同的版本:
http://www.madcat.nl/martijn/archives/16-Using-smarty-to-prevent-HTML-injection..html
在新的Django 1.0版本中,这种方式完全相同,jay:)
答案 4 :(得分:1)
您可以在自己的方法中包装echo / print等,然后可以使用它们来转义输出。即代替
echo "blah";
使用
myecho('blah');
如果你需要的话,你甚至可以拥有第二个关闭逃脱的参数。
在一个项目中,我们在输出函数中使用了调试模式,这使得通过我们的方法的所有输出文本都不可见。然后我们知道屏幕上剩下的任何东西都没有被逃脱!跟踪那些顽皮的非转义位非常有用:)
答案 5 :(得分:1)
我个人的偏好是努力编码来自数据库,业务层或来自用户的任何。
在ASP.Net中,这是通过使用Server.HtmlEncode(string)
完成的。
因此编码任何内容的原因是,即使是您可能认为是布尔值或数字的属性也可能包含恶意代码(例如,复选框值,如果它们执行不当可能会以字符串形式返回。如果您不是在将输出发送给用户之前编码它们,然后你就有了一个漏洞。
答案 6 :(得分:0)
如果您对每个输出实际进行HTML编码,则用户将看到&amp; lt; html&amp; gt;的纯文本。而不是一个正常运行的网络应用程序。
编辑:如果您对每个输入进行HTML编码,则接收包含&lt;的外部密码时会遇到问题。等。
答案 7 :(得分:0)
真正保护自己免受此类攻击的唯一方法是严格过滤您接受的所有输入,特别是(尽管不是唯一的)来自应用程序的公共区域。我建议你看看Daniel Morris的PHP Filtering Class(一个完整的解决方案)以及Zend_Filter包(你可以用来构建自己的过滤器的类集合)。
在Web开发方面,PHP是我的首选语言,所以对我的答案中的偏见表示道歉。
基兰。
答案 8 :(得分:0)
Joel在软件上写了一篇好文章(我认为错误的代码看起来错了,我在手机上,否则我会为你提供一个URL),其中涵盖了正确使用匈牙利符号的方法。简短的版本将是:
Var dsFirstName, uhsFirstName : String;
Begin
uhsFirstName := request.queryfields.value['firstname'];
dsFirstName := dsHtmlToDB(uhsFirstName);
基本上为变量添加前缀为“us”表示不安全字符串,“ds”表示数据库安全,“hs”表示HTML安全。您只想编码和解码实际需要的地方,而不是一切。但是通过使用它们可以推断出有用意义的前缀来查看代码,如果出现问题,你会很快看到它们。而且无论如何你将需要不同的编码/解码功能。
答案 9 :(得分:0)
输出编码是迄今为止最好的防御。验证输入很多很多原因,但不是100%防御。如果数据库通过攻击(即ASPROX)感染了XSS,则错误或恶意输入验证不会执行任何操作。输出编码仍然有效。
答案 10 :(得分: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响应时)。< / p>