jsp 输入标签的跨站脚本问题

Cross Site Scripting issue on jsp input tag

我是 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/>
<%          } %>

为了安装 url,我使用 query = request.getQueryString();,其中附加了 chkId_0 的值 (?...&chkId_0=203_908434'():;998649&...)

到目前为止,我正在使用过滤器并覆盖 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("[=13=]", "");

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

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

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

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

您放入周围 HTML 上下文中的每个文本字符串 必须 HTML-转义。

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

如果您没有 JSP 2.0 的 c: 标签可以执行此操作,那么您将需要一个单独的转义函数。例如:

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

但是,查看错误:

The input is reflected inside Javascript code between single quotes.

它不是抱怨 HTML-injection 而是 JS-injection。您可能在接收表单提交的页面上有这样的内容:

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

这里我们将文本插入到 JavaScript 字符串文字中,所以我们需要使用 JS-string-literal-escaping 这样如果值中有单引号,它就会作为 JS 输出\' 转义:

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

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

I'm using a filter and overriding getParameter() and getParameterValues() from HttpServletRequestWrapper to avoid some other XSS issues

这完全行不通。有许多方法可以解决您的黑名单模式。为了使其捕获所有可能的攻击,您必须禁止所有在 HTML、JS 或您要注入的任何其他格式中的特殊字符——基本上阻止所有标点符号,这很少被接受。

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