用于XSS预防的ESAPI不起作用

我正在我们的代码中主要在JSPS中修复Cross站点脚本问题。

以下是原始代码

//scriplet code  

他们拥有相同的Jsp

  <input type = hidden name = "userID" value = "" /> 

我做了更改,在lib和ESAPI.properties中包含esapi-2.1.0.jar,在classpath中包含validation.properties。 然后在下面更改scriplet代码以修复上面的代码

  //scriplet code  

我认为这可以解决问题,但是当我使用Fortify扫描我的代码时,这些行再次突出显示为有XSS问题。 如果你们对如何处理这个问题有任何想法,请帮忙。 谢谢。

——-更新

非常感谢@avgvstvs。 这是非常有见地的.Follwd指南,不确定我是否有点想念。 代码 –

  String userSID=ESAPI.encoder().encodeForHTMLAttribute(request.getHeader("janus_sid")); session.setAttribute("username",userSID);<input type=hidden name="USERNAME" value="" 

对于另一个varibale调试,下面是用法

  String debugFlag = ESAPI.encoder().encodeForJavaScript(request.getParameter("debug"));var debugFlag = "";if(debugFlag == "y"){ document.title= title + " (" + host + ")"; defaultAppTitle = title + " (" + host + ")"; } 

最新的Fortify扫描仍然将它们列为漏洞:-(

你需要问的第一个问题应该是“我将这个值交给了什么代码解释器?”

不幸的是,防止XSS不是一个基于配方的任务,从它的外观来看 – 你的应用程序使用的是scriptlet, 除了糟糕的Java实践之外 ,使得像Fortify这样的静态代码扫描工具给你带来的困难要大得多准确的结果。 JSP在运行时编译,但Fortify仅扫描源。 您应该注意到,应该有未来的任务/故事提交给JSTL重构Scriptlet – 您将在以后感谢我。 那么你可以使用esapi taglibs来处理这些用例。 Fortify可以很好地扫描纯Java代码,而taglibs可以帮助你。

  1. ESAPI.encoder().encodeForHTML(userId)只会在有问题的变量放在标签之间的用例中保护您免受XSS的攻击,例如<%= userId %>这不是你的情况。

  2. ESAPI.encoder().encodeForHTMLAttribute(userId)就是您想要的特定的狭义用例。 这是因为转义规则在Html属性中与在标记中放置的数据不同。 这应该可以解决你的问题。

  3. 如果该值将由JavaScript专门使用,那么您需要ESAPI.encoder().encodeForJavaScript(userId)

  4. 如果值是可渲染的HTML,则发送到将呈现标记的javascript函数,如element.innerHTML = “ Tags and markup”; 你想要<%=Encoder.encodeForJS(Encoder.encodeForHTML(userId))%>

这只是一些例子, 这里还有一些例子 – 但我的答案的首要任务是:你需要知道应用程序中每个变量的完整数据流,并始终编码适当的输出上下文。 在安全领域,“上下文”意味着“数据正在传递给新的代码解释器”。 如果你很好地实现这种理解,你将不再需要Fortify! 🙂

====增加了复杂性====

在您的评论中,您注意到该值后来被JavaScript使用。 因此,在这种情况下,正确的解决方案可能是分叉两个不同的变量,每个变量都设置为正确的编码。 对于HTML属性案例:

String escapedHtmlUserId = ESAPI.encoder().encodeForHTMLAttribute(userId);

对于Javascript案例:

String escapedJSUserId = ESAPI.encoder().encodeForJavaScript(userId);

然后适当地使用这些值。 如果您使用了JSTL / taglib,则可以在正确的位置使用正确的esapi taglib,而不是分成两个单独的scriptlet变量。

===还有一件事===

来自对OP的评论:

我们有一个初始的scriptlet声明:

<% String userId = ESAPI.encoder().encodeForHTML(request.getParameter("sid")); ...%>

它稍后在javascript函数中使用:

<%= ESAPI.encoder().encodeForJavascripl(userId)%>

只是要指出, userIduserId变量在初始化时不再是原始文本。 实际上,javascript的编码变为:

  <% ESAPI.encoder().encodeForJavascript(ESAPI.encoder().encodeForHTML(request.getParameter("sid"))); ...%> 

如果javascript将使用* .innerHTML()或* .outerHTML()呈现HTML,这很好。 否则,请注意输入已从原始状态更改。

另外,请注意一些JavaScript可以撤消您已完成的操作,并确保您的JavaScript没有做类似的事情。

==========更多添加代码,更多问题========

所以我们已经跟踪了我们所有的数据路径,我们已经仔细检查过我们的JSP没有被包含在一个不同的JSP中,这个JSP为我们引入了新的上下文来防范,这是我闻到的“误报,“但如果我是你,我会联系惠普支持并提出这个问题,以防误报。 除非我能够访问完整的源代码,否则我不太了解您的应用程序的具体内容对您真正有用。 因为你正在处理scriptlet – 可能Fortify无法跟踪从变量实例化到最终输出的完整数据路径,所以它很快就会失败,所以它至少可以警告你到目前为止发现了什么。

谢谢你的帮助。 最后找出了一个防止XSS问题并通过Fortify静态代码分析的解决方案。 我已经将ESAPI和Anitsamy库一起使用了。 以下是所需的3个主要更改。

  1. 实施Anitsamyfilter

    添加新的filter并覆盖请求方法getParameter,getParameterValues以去除请求中的任何可疑标记。 filter加载策略文件,我们在其中定义规则

    一个。 需要从请求中删除的标签(标签等)

    湾 常用属性的正则表达式,如href,align等。

filter的实现示例在http://barrypitman.com/2011/04/14/using-input-validation-XSS/

  1. 使用ESAPI库执行输入validation

      String reportName = request.getParameter("reportName"); ESAPI.validator().getValidInput("Report Name", reportName, "ReportNamePattern", 100, false); 

    在上面的代码中,

    1. “报告名称”是上下文
    2. reportName是数据字段
    3. ReportNamePattern是ESAPI.properties中定义的正则表达式模式,为Validator.ReportNamePattern = ^ [a-zA-Z] {1} [0-9] {6} $
    4. 100是数据字段reportName的最大长度
    5. false是一个标志,表示不允许使用null值。
  2. 执行输出编码
    正如@avgvstvs指出的那样,输出编码也是必须的。

    如果要在HTML中使用reportName字段,则下面是如何编码

       Report : <%=ESAPI.encoder().encodeForHTML(reportName)%>   

    如果要在javascript代码中使用reportName字段,则下面是如何编码

      var reportName = "<%= ESAPI.encoder().encodeForJavaScript(reportName)%>"; 

    如果要在HTML属性中使用reportName字段,则下面是如何编码