在 java Web 应用程序中防止 xss 攻击,同时在数据库中保存实际值

Preventing xss attack in java web app while saving actual values in database

最近通过 AppScan 扫描了我们基于 java 的 Web 应用程序,发现该应用程序容易受到 XSS 攻击。 我做了研究,发现 ServletFilter 可能是保护应用程序的最简单方法。 我在扩展 HttpServletRequestWrapper 的地方引入了过滤器(因为 java 不允许更改请求参数,所以没有 request.setParam 方法)。我在那里介绍了一种消毒方法,这是它的作用

result = ESAPI.encoder().canonicalize( input);

// Avoid null characters
result = result.replaceAll("[=11=]", "");

// Clean out HTML
result = Jsoup.clean( result, Whitelist.none() );

Post这个改动,不错,我自己测试了XSS漏洞,大部分都修复了。但这带来了另一个问题。假设我有一个用于创建产品的表单,用户在产品名称中输入类似

的内容
<script>alert('somethingStupid')</script>

现在理想情况下,我应该能够将其保存到数据库中,但仍然可以免受 XSS 攻击。不确定要在我的过滤器或其他任何地方做什么才能实现这一目标。

跨站脚本 (XSS) 是一个安全问题,当没有验证用户输入的机制时会发生,因此结果通常是可利用的 javascript 代码。

3 种类型的 XSS 是已知的:自反 XSS、基于 DOM 的 XSS 和持久性 XSS。

在你的情况下,因为你使用的是 OWASP ESAPI,所以规范化输入是不够的,确保它是防御 SRC 或 HREF 属性中不受信任 URL 的好方法,但这还不够。

您应该遵循这些规则:来源 (XSS (Cross Site Scripting) Prevention Cheat Sheet of OWASP)(这里有一些规则供进一步阅读遵循 link):

1- HTML 在将不受信任的数据插入 HTML 元素内容之前进行转义:参见示例:

 String safe = ESAPI.encoder().encodeForHTML( request.getParameter( "input" ) );

2- 将不受信任的数据插入 HTML 公共属性之前进行属性转义:

String safe = ESAPI.encoder().encodeForHTMLAttribute( request.getParameter( "input" ) );

3- JavaScript 在将不受信任的数据插入 JavaScript 数据值之前进行转义:

 String safe = ESAPI.encoder().encodeForJavaScript( request.getParameter( "input" ) );

HTML-注入是一个输出阶段的问题,是由于在将文本注入到字符特殊的上下文中时忘记对文本进行编码而引起的。正如@Zakaria 所讨论的,ESAPI 为各种上下文提供了编码器。如果你始终如一地使用它们,每一个都在正确的上下文中,你就解决了与注入相关的 XSS 问题。

如果您使用像 <c:out> 这样的纯 JSTL 标签作为模板,这些标签也会默认 HTML-escape。通常,最好使用可以自动为您转义 HTML 的模板系统生成 HTML,因为否则您可能会偶尔忘记手动 encodeForHTML。

(另外:在我不得不使用最糟糕的 owasp-esapi-java 库的项目中,我更喜欢 encodeForXML 而不是 HTML 编码器,因为它产生的输出对于 HTML 内容和引用的属性值是安全的,同时不会不必要地尝试为非 ASCII 字符产生实体引用。我通常会尽量避免注入 JavaScript 字符串文字;它通常是将 运行 时间的内容注入 HTML data- 属性并从单独的 JavaScript DOM 代码中读取它们更容易且更易于维护。)

试图在输入阶段过滤掉 HTML 是一种令人遗憾的仍然流行但完全被误导的方法。它会阻止您在需要时输入类似 HTML 的输入——正如您在 <script> 示例中发现的那样。事实上,如果 Whosebug 使用这样的输入过滤器,我们将无法进行此对话。

更重要的是,它没有弹性:有很多方法可以通过输入过滤器走私潜在的注入。要使过滤器有效,您必须考虑阻止几乎所有标点符号,这通常被认为是不可接受的。此外,任何通过请求参数以外的方式进入您的应用程序的数据都不会被审查。

输入验证非常适合在特定输入字段的格式上执行业务规则,并且可用于过滤掉您不需要的输入,例如控制字符。但担心转义或删除 HTML 是错误的地方。执行此操作的时间是在创建 HTML.