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实体(诸如<
, "
, '
, &
字符。
请注意,您不需要在Java(Servlet)代码中转义它们,因为它们在那里是无害的。 有些人可能会select在请求处理期间(如在Servlet或Filter中所做的那样)转义它们,而不是响应处理(就像在JSP中那样),但是这样可能会导致数据不必要地被双重转义(例如&
变成&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,来自客户端的数据。
- inputvalidation (表单validation)在服务器端。 有多种方式去实现它。 您可以尝试JSR 303的beanvalidation( hibernate validator )或ESAPIinputvalidation框架 。 虽然我还没有尝试过,但还是有一个注释来检查安全的html (@SafeHtml) 。 你实际上可以使用Spring MVC的Hibernatevalidation器进行beanvalidation – > Ref
- 转义URL请求 – 对于所有的HTTP请求,使用某种XSSfilter。 我用我们的networking应用程序以下,它负责清理HTTP URL请求 – http://www.servletsuite.com/servlets/xssflt.htm
- 转义数据/ html返回给客户端(请看上面的@BalusC解释)。
我会build议定期使用自动化工具testing漏洞,并修复所发现的任何漏洞。 一般来说,build议一个图书馆来帮助解决一个特定的漏洞,然后对所有的XSS攻击,要容易得多。
Skipfish是我一直在研究的一个来自Google的开源工具:它发现了很多东西,似乎值得使用。
对XSS没有简单的开箱即用的解决scheme。 OWASP ESAPI API有一些非常有用的转义支持,它们有标签库。
我的方法是基本上以下列方式扩展Stut 2标签。
- 修改s:property标签,这样就可以获得额外的属性,说明需要什么types的转义(escapeHtmlAttribute =“true”等)。 这涉及到创build一个新的Property和PropertyTag类。 Property类使用OWASP ESAPI API进行转义。
- 更改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/