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