jsp输入标记上的跨站点脚本问题

时间:2015-02-12 12:06:23

标签: jsp security servlets xss

我是Acunetix和XSS问题的新手,所以我在这里有点迷失。

问题是,我的报告说我的代码中可能容易受到跨站点脚本(XSS)攻击。

URL encoded POST input chkId_0 was set to 203_908434'():;998649
The input is reflected inside Javascript code between single quotes.

在我的JSP中,我有类似的东西:

<%          if (!someCondition) { %>                
            <input class="chkbox" type="checkbox" name="chkId_0" value="<%=office.getId()%>" <%=auxDisabled%> />
<%          } else { %>          
            <input class="chkbox" type="checkbox" name="chkId_0" value="    <%=office.getId()%>" <%=auxDisabled%> disabled/>
<%          } %>

要安装网址,我正在使用query = request.getQueryString();,其中附加了chkId_0的值(?...&amp; chkId_0 = 203_908434'():; 998649&amp; ...)

到目前为止,我正在使用过滤器并覆盖来自HttpServletRequestWrapper的getParameter()和getParameterValues()以避免其他一些XSS问题,但不知道如何解决这个问题。

@Override
public String getParameter(String parameter) {
    String value = super.getParameter(parameter);

    return stripXSS(value);
}

private static Pattern[] patterns = new Pattern[]{
    // Script fragments
    Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE),
    // src='...'
    Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
    Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
    // lonely script tags
    Pattern.compile("</script>", Pattern.CASE_INSENSITIVE),
    Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
    // eval(...)
    //...
};

public static String stripXSS(String value) {
    if (value != null) {           
        // Avoid null characters
        value = value.replaceAll("\0", "");

        // Remove all sections that match a pattern
        for (Pattern scriptPattern : patterns){
            value = scriptPattern.matcher(value).replaceAll("");
        }
    }
    return value;
}

我已经读过我可以使用JSTL(<c:out>)来解决这个问题,但不幸的是,这不是我的选择,因为代码是遗留的。

任何形式的帮助将不胜感激。 提前谢谢。

1 个答案:

答案 0 :(得分:2)

 <input class="chkbox" type="checkbox" name="chkId_0" value="<%=office.getId()%>"/>

您放入周围HTML上下文的每个文字字符串都必须进行HTML转义。

(这是为了正确性和安全性:值中的"应该在页面上显示为",而不是损坏的输入标记。为此,要实现此字符{{1必须写成HTML "。)

如果您没有JSP 2.0的c:标签可用,那么您将需要一个单独的转义功能。例如:

&quot;

然而,看错误:

  

输入反映在单引号之间的Javascript代码中。

它并不是在抱怨HTML注入而是JS注入。您可能在收到表单提交的页面上有类似的内容:

 <input class="chkbox" type="checkbox" name="chkId_0" value="<%= StringEscapeUtils.escapeHtml4(office.getId()) %>"/>

这里我们将文本插入到JavaScript字符串文字中,因此我们需要使用JS-string-literal-escaping,这样如果值中出现单引号,它就会成为JS {{1逃避:

<script>
    var chkId = '<%= request.getParameter("chkId_0") %>';
</script>

(这些例子使用StringEscapeUtils from Apache Commons Lang,这在很多方面都不令人满意,但足以达到这些目的。)

  

我使用过滤器并重写来自HttpServletRequestWrapper的getParameter()和getParameterValues()以避免其他一些XSS问题

这完全不可行。黑名单模式有很多种方法。为了捕获所有可能的攻击,你必须禁止所有特殊的HTML,JS或你注入的任何其他格式的字符 - 基本上阻止所有标点符号,这很少被接受。

而是专注于在输出端使用正确的转义形式。