JSP / Servlet Web应用程序中的XSS预防

如何防止JSP / Servlet Web应用程序中的XSS攻击?

在重新显示用户控制的input时,可以通过使用JSTL <c:out>标记或fn:escapeXml() EL函数在JSP中防止XSS。 这包括请求参数,头文件,cookie,URL,主体等。您从请求对象中提取的任何内容。 另外,在重新显示期间,存储在数据库中的来自先前请求的用户控制input需要被转义。

例如:

 <p><c:out value="${bean.userControlledValue}"></p> <p><input name="foo" value="${fn:escapeXml(param.foo)}"></p> 

这将转义可能使呈现的HTML(例如<>"'&变成HTML & XML实体(诸如&lt;&quot;&apos;&amp;字符。

请注意,您不需要在Java(Servlet)代码中转义它们,因为它们在那里是无害的。 有些人可能会select在请求处理期间(如在Servlet或Filter中所做的那样)转义它们,而不是响应处理(就像在JSP中那样),但是这样可能会导致数据不必要地被双重转义(例如&变成&amp;amp;而不是&amp;最终用户会看到&amp;被呈现),或者DB存储的数据变得不可移植(例如,当将数据导出到不需要HTML转义的JSON,CSV,XLS,PDF等等在所有)。 您也将失去社交控制权,因为您不知道用户实际填写了什么内容。您希望作为网站pipe理员真正想知道哪些用户/ IP正在尝试执行XSS,以便您可以轻松跟踪他们并采取相应的行动。 请求处理过程中的转义应该只能作为最新的手段,当你真的需要尽可能在最短的时间内修复一个糟糕的遗留Web应用程序的火车残骸。 不过,您最终应该重写您的JSP文件以变得XSS安全。

如果您希望重新显示用户控制的input为HTML,而您希望仅允许特定的HTML标签子集(如<b><i><u>等),则需要通过白名单。 你可以使用像Jsoup这样的HTMLparsing器。 但是,更好的是引入一个人性化的标记语言,如Markdown(在Stack Overflow中也使用)。 然后你可以使用像CommonMark这样的Markdownparsing器。 它也内置HTML消毒function。 另请参阅我正在寻找一个Java的HTML编码器 。

服务器端关于数据库的唯一问题是SQL注入预防。 您需要确保从不直接在SQL或JPQL查询中串连用户控制的input,并且始终使用参数化查询。 在JDBC术语中,这意味着您应该使用PreparedStatement而不是Statement 。 在JPA条款中,使用Query


另一种方法是从JSP / Servlet迁移到Java EE的MVC框架JSF 。 它内置了XSS(和CSRF!)预防function。 另请参阅JSF中的CSRF,XSS和SQL注入攻击防护 。

how-to-prevent-xss已经被问了好几次了。 你会在StackOverflow中find很多信息。 此外, OWASP网站有一个XSS预防备忘单 ,你应该通过。

在要使用的库上, OWASP的ESAPI库具有Java风格。 你应该尝试一下。 除此之外,您使用的每个框架都有一些针对XSS的保护。 再次,OWASP网站有最stream行的框架信息,所以我会build议通过他们的网站。

我在OWASP Anti-Samy和AspectJ顾问上运行了所有的阻止XSS进入的Spring控制器。

 public class UserInputSanitizer { private static Policy policy; private static AntiSamy antiSamy; private static AntiSamy getAntiSamy() throws PolicyException { if (antiSamy == null) { policy = getPolicy("evocatus-default"); antiSamy = new AntiSamy(); } return antiSamy; } public static String sanitize(String input) { CleanResults cr; try { cr = getAntiSamy().scan(input, policy); } catch (Exception e) { throw new RuntimeException(e); } return cr.getCleanHTML(); } private static Policy getPolicy(String name) throws PolicyException { Policy policy = Policy.getInstance(Policy.class.getResourceAsStream("/META-INF/antisamy/" + name + ".xml")); return policy; } } 

你可以从这个stackoverflowpost中获得AspectJ顾问

我认为这是一个更好的方法,然后C:特别是如果你做了很多的JavaScript。

pipe理XSS需要多个validation,来自客户端的数据。

  1. inputvalidation (表单validation)在服务器端。 有多种方式去实现它。 您可以尝试JSR 303的beanvalidation( hibernate validator )或ESAPIinputvalidation框架 。 虽然我还没有尝试过,但还是有一个注释来检查安全的html (@SafeHtml) 。 你实际上可以使用Spring MVC的Hibernatevalidation器进行beanvalidation – > Ref
  2. 转义URL请求 – 对于所有的HTTP请求,使用某种XSSfilter。 我用我们的networking应用程序以下,它负责清理HTTP URL请求 – http://www.servletsuite.com/servlets/xssflt.htm
  3. 转义数据/ html返回给客户端(请看上面的@BalusC解释)。

我会build议定期使用自动化工具testing漏洞,并修复所发现的任何漏洞。 一般来说,build议一个图书馆来帮助解决一个特定的漏洞,然后对所有的XSS攻击,要容易得多。

Skipfish是我一直在研究的一个来自Google的开源工具:它发现了很多东西,似乎值得使用。

对XSS没有简单的开箱即用的解决scheme。 OWASP ESAPI API有一些非常有用的转义支持,它们有标签库。

我的方法是基本上以下列方式扩展Stut 2标签。

  1. 修改s:property标签,这样就可以获得额外的属性,说明需要什么types的转义(escapeHtmlAttribute =“true”等)。 这涉及到创build一个新的Property和PropertyTag类。 Property类使用OWASP ESAPI API进行转义。
  2. 更改freemarker模板以使用新版本的s:属性并设置转义。

如果您不想在第1步中修改类,则另一种方法是将ESAPI标记导入到freemarker模板中并根据需要进行转义。 然后,如果您需要在JSP中使用as:property标记,请使用ESAPI标记进行包装。

我在这里写了一个更详细的解释。

http://www.nutshellsoftware.org/software/securing-struts-2-using-esapi-part-1-securing-outputs/

我同意逃避投入是不理想的。

我个人的意见是,你应该避免使用JSP / ASP / PHP /等网页。 而是输出到类似于SAX的API(仅用于调用而不是处理)。 这样就有一个单一的层面,必须创造良好的输出。

如果您想自动转义所有的 JSPvariables而不必显式地包装每个variables,那么可以使用一个ELparsing器,这里详细介绍了完整的源代码和一个示例(JSP 2.0或更高版本) ,并在此处进行了更详细的讨论:

例如,通过使用上面提到的ELparsing器,您的JSP代码将保持如此,但每个variables将被parsing器自动转义

 ... <c:forEach items="${orders}" var="item"> <p>${item.name}</p> <p>${item.price}</p> <p>${item.description}</p> </c:forEach> ... 

如果你想在Spring中默认强制转义,你可以考虑这个,但是它不会逃避ELexpression式,只是标记输出,我想:

http://forum.springsource.org/showthread.php?61418-Spring-cross-site-scripting&p=205646#post205646

注意:另一种使用XSL转换来预处理JSP文件的EL转义方法可以在这里find:

http://therning.org/niklas/2007/09/preprocessing-jsp-files-to-automatically-escape-el-expressions/