如何在JSP/Servlet Web应用程序中防止XSS攻击?
当(重新)显示用户控制的输入时,可以通过使用JSTL
标记或fn:escapeXml()
EL函数来防止JSP中的XSS .这包括请求参数,标题,cookie,URL,正文等.您从请求对象中提取的任何内容.此外,在重新显示期间,需要转储存储在数据库中的先前请求的用户控制输入.
例如:
这将逃脱这可能malform渲染HTML,如人物<
,>
,"
,'
和&
成HTML/XML实体,如<
,>
,"
,'
和&
.
请注意,您不需要在Java(Servlet)代码中转义它们,因为它们在那里是无害的.有些人可能会选择在逃避他们的请求处理(如你在Servlet或者过滤器一样),而不是响应处理(如你在JSP做),但这种方式,您可能会冒这个险的数据不必要获得双重逸出(如&
变&
的,而不是&
和最终,最终用户将看到&
被呈现),或者DB存储的数据变得不可移植(例如,当将数据导出到JSON,CSV,XLS,PDF等,根本不需要HTML转义).您也将失去社交控制,因为您不再了解用户实际填写的内容.您作为网站管理员真的想知道哪些用户/ IP正在尝试执行XSS,以便您可以轻松跟踪他们并采取相应的行动.在您真正需要在尽可能短的时间内修复严重开发的遗留Web应用程序的列车残骸时,请求处理期间的转义应该仅用作最新的手段.但是,您最终应该重写JSP文件以使其成为XSS安全的.
如果你想重新显示用户控制输入为HTML,其中你想只允许像HTML标签的特定子集,
,
,等等,那么你需要通过一个白名单来净化输入.您可以使用像Jsoup这样的HTML解析器.但是,更好的是引入一种人性化的标记语言,例如Markdown(也在Stack Overflow中使用).然后你可以使用像CommonMark这样的Markdown解析器.它还内置了HTML清理功能.另请参阅我正在寻找Java HTML编码器.
服务器端关于数据库的唯一问题是SQL注入预防.您需要确保在SQL或JPQL查询中不会直接串联连接用户控制的输入,并且您一直在使用参数化查询.在JDBC术语中,这意味着您应该使用PreparedStatement
而不是Statement
.在JPA术语中,使用Query
.
另一种方法是从JSP/Servlet迁移到Java EE的MVC框架JSF.它已在所有地方内置了XSS(和CSRF!)预防.另请参阅JSF中的CSRF,XSS和SQL注入攻击防护.
已经多次询问了如何预防xss.您将在StackOverflow中找到大量信息.此外,OWASP网站有一个XSS预防备忘单,你应该通过.
在要使用的库上,OWASP的ESAPI库具有java风格.你应该尝试一下.除此之外,您使用的每个框架都有一些针对XSS的保护.OWASP网站再次提供了大多数流行框架的信息,因此我建议您浏览他们的网站.
我很幸运OWASP Anti-Samy和我的所有Spring控制器上的AspectJ顾问阻止XSS进入.
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; } }
您可以从此stackoverflow帖子中获取AspectJ顾问程序
我认为这是一个更好的方法然后c:特别是如果你做了很多javascript.
管理XSS需要多次验证,来自客户端的数据.
在服务器端输入验证(表单验证).有多种方法可以解决这个问题.您可以尝试JSR 303 bean验证(hibernate验证器)或ESAPI输入验证框架.虽然我自己还没有尝试过,但是有一个注释可以检查安全的html (@SafeHtml).事实上你可以使用Hibernate验证器和Spring MVC进行bean验证 - > Ref
转义URL请求 - 对于所有HTTP请求,请使用某种XSS过滤器.我已经将以下内容用于我们的Web应用程序,它负责清理HTTP URL请求 - http://www.servletsuite.com/servlets/xssflt.htm
转义数据/ html返回给客户端(见上面的@BalusC解释).