Java JSP/Servlet web应用中的XSS防范
如何在JSP/Servlet web应用程序中防止XSS攻击?如何防止XSS已经被问了好几次了。您将在StackOverflow中找到大量信息。还有,你应该通过Java JSP/Servlet web应用中的XSS防范,java,security,jsp,servlets,xss,Java,Security,Jsp,Servlets,Xss,如何在JSP/Servlet web应用程序中防止XSS攻击?如何防止XSS已经被问了好几次了。您将在StackOverflow中找到大量信息。还有,你应该通过 在要使用的库上,具有java风格。你应该试试看。除此之外,您使用的每个框架都有一些针对XSS的保护。同样,OWASP网站上有关于大多数流行框架的信息,因此我建议浏览他们的网站。在JSP中,当(重新)显示用户控制的输入时,可以使用标记或EL函数来防止XSS。这包括请求参数、头、cookie、URL、正文等。从请求对象提取的任何内容。此外,
在要使用的库上,具有java风格。你应该试试看。除此之外,您使用的每个框架都有一些针对XSS的保护。同样,OWASP网站上有关于大多数流行框架的信息,因此我建议浏览他们的网站。在JSP中,当(重新)显示用户控制的输入时,可以使用标记或EL函数来防止XSS。这包括请求参数、头、cookie、URL、正文等。从请求对象提取的任何内容。此外,在重新显示期间,需要转义存储在数据库中的来自先前请求的用户控制输入 例如:
这将把可能使呈现的HTML格式错误的字符转义为
,“
,”
和&
,例如
,,”
,&apos代码>和&代码>
注意,您不需要在Java(Servlet)代码中转义它们,因为它们在那里是无害的。有些人可能会选择在请求处理期间(如在Servlet或过滤器中所做的)转义它们,而不是在响应处理期间(如在JSP中所做的),但这种方式可能会导致数据不必要地被双重转义(例如,&
变成&;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp。你也将失去社会控制,因为你不再知道用户实际填写了什么。作为网站管理员,你很想知道哪些用户/IP正在尝试执行XSS,这样你就可以轻松地跟踪他们并采取相应的行动。请求处理期间的转义只应并且仅当你我们确实需要在尽可能短的时间内修复开发糟糕的遗留web应用程序的故障。不过,您最终应该重写JSP文件,使其成为XSS安全的
如果您想将用户控制的输入重新显示为HTML,其中只允许HTML标记的特定子集,如
,
,
,等等,那么您需要通过白名单来清理输入。您可以使用类似的HTML解析器。但是,最好引入一种人性化的标记语言,如s标记(这里也用于堆栈溢出)。然后您可以使用类似的标记解析器。它还具有内置的HTML清理功能。另请参阅
服务器端关于数据库的唯一问题是预防。您需要确保从不在SQL或JPQL查询中直接串接用户控制的输入,并且始终使用参数化查询。在JDBC术语中,这意味着您应该使用而不是语句
。在JPA术语中,使用
另一种方法是从JSP/Servlet迁移到JavaEE的MVC框架全面预防。另请参见。我建议定期使用自动化工具测试漏洞,并修复发现的任何漏洞。建议使用库来帮助解决特定漏洞要比一般所有XSS攻击容易得多
是一个来自谷歌的开源工具,我一直在研究它:它发现了很多东西,似乎值得使用。我个人的意见是,你应该避免使用JSP/ASP/PHP/etc页面。相反,输出到一个类似SAX的API(只用于调用而不是处理)通过这种方式,只有一个层必须创建格式良好的输出。我很幸运在我所有的Spring控制器上都安装了OWASP Anti-Samy和AspectJ advisor,阻止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;
}
}
您可以从
我认为这是一种比c:out更好的方法,特别是如果你使用大量javascript。没有简单的、现成的解决方案来对付XSS。OWASP ESAPI对转义有一些非常有用的支持,并且它们有标记库
我的方法基本上是通过以下方式扩展stuts2标签
修改s:property标记,使其可以接受额外的属性,说明需要何种类型的转义(escapehtmlatAttribute=“true”等)。这包括创建新的属性和PropertyTag类。属性类使用OWASP ESAPI进行转义
更改freemarker模板以使用新版本的s:property并设置转义
如果您不想在步骤1中修改类,另一种方法是将ESAPI标记导入freemarker模板并根据需要转义。然后,如果您需要在JSP中使用s:property标记,请使用和ESAPI标记将其包装
我在这里写了更详细的解释
我同意转义输入并不理想。如果您想自动转义所有
JSP变量,而不必显式地包装每个变量,您可以使用EL解析器,并进行了更详细的讨论:
例如,通过使用上述EL解析器,您的JSP代码将保持原样,但解析器将自动转义每个变量
...
<c:forEach items="${orders}" var="item">
<p>${item.name}</p>
<p>${item.price}</p>
<p>${item.description}</p>
</c:forEach>
...
。。。
${item.name}
${item.price}
${item.description}
...
如果你想强制默认在施普灵河逃逸,你也可以考虑这个问题,但是它不能逃避EL表达式,只是标签输出,我想:
注意:另一种使用XSL转换预处理JSP文件的EL转义方法可以在这里找到:管理XSS需要多次验证,数据来自t
@WebListener
public class EscapeXmlELResolverListener implements ServletContextListener {
private static final Logger LOG = LoggerFactory.getLogger(EscapeXmlELResolverListener.class);
@Override
public void contextInitialized(ServletContextEvent event) {
LOG.info("EscapeXmlELResolverListener initialized ...");
JspFactory.getDefaultFactory()
.getJspApplicationContext(event.getServletContext())
.addELResolver(new EscapeXmlELResolver());
}
@Override
public void contextDestroyed(ServletContextEvent event) {
LOG.info("EscapeXmlELResolverListener destroyed");
}
/**
* {@link ELResolver} which escapes XML in String values.
*/
public class EscapeXmlELResolver extends ELResolver {
private ThreadLocal<Boolean> excludeMe = new ThreadLocal<Boolean>() {
@Override
protected Boolean initialValue() {
return Boolean.FALSE;
}
};
@Override
public Object getValue(ELContext context, Object base, Object property) {
try {
if (excludeMe.get()) {
return null;
}
// This resolver is in the original resolver chain. To prevent
// infinite recursion, set a flag to prevent this resolver from
// invoking the original resolver chain again when its turn in the
// chain comes around.
excludeMe.set(Boolean.TRUE);
Object value = context.getELResolver().getValue(
context, base, property);
if (value instanceof String) {
value = StringEscapeUtils.escapeHtml4((String) value);
}
return value;
} finally {
excludeMe.remove();
}
}
@Override
public Class<?> getCommonPropertyType(ELContext context, Object base) {
return null;
}
@Override
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base){
return null;
}
@Override
public Class<?> getType(ELContext context, Object base, Object property) {
return null;
}
@Override
public boolean isReadOnly(ELContext context, Object base, Object property) {
return true;
}
@Override
public void setValue(ELContext context, Object base, Object property, Object value){
throw new UnsupportedOperationException();
}
}
}