修复J2EE漏洞:1. ESAPI_WAF

ESAPI WAF配置文件

ESAPI WAF由XML策略文件驱动,该文件告诉应用程序在应用程序中执行哪些规则,这些规则可以做很多事情,从简单的虚拟补丁到使用BeanShell脚本复杂授权

该文档描述了策略文件的结构,每一个规则及其工作原理。这里也会提供一些示例去引导整个实验过程,下图直观展示了XSD策略文件,这里策略文件的正式规范 如图所示,策略文件的根元素是”policy”,并且没有任何属性。在”policy”根元素里面有很多规则标签,这些只是帮助组织策略文件的规则类别。如图所示,只有标签”aliases”和”settings”是必要的,考虑到这一点,下面是一个没有任何规则的框架示例

<?xml version="1.0" encoding="UTF-8"?>

<policy>  
   <aliases></aliases>
   <settings>
      <mode>block</mode>
      <session-cookie-name>JSESSIONID</session-cookie-name>
    <error-handling>
         <default-redirect-page>/error.jsp</default-redirect-page>
         <block-status>500</block-status>
      </error-handling>
   </settings>
</policy>  

如果你正在编写自己的策略文件,从这个空文件开始是最好的选择。每一条规则都有一个可选的ID属性,可用于每个规则的唯一标识。虽然id属性也不是必须的,不过你可以在日志中搜索它,来发现具体触发了哪些规则。

下面的内容即专门讨论上述的每个规则细节。

Aliases标签

<aliases>标签为在整个策略文件定义公用的字符串,该标签中可以用0个或多个子标签。

想象一下,在/admin目录中发现了若干漏洞,由于有很多规则会引用网站的这一部分,因此需要有一个配置来定义它。它减少了错误的规则,并有助于使规则更有条理。示例如下:

<aliases>  
   <alias name="ADMIN_PATH" type="regex">^/admin/.*</alias>
</aliases>  

属性”name”是必须的,用于之后在策略中引用的别名,所以应使用便于理解的单词。 属性”type”是可选项,用于告诉WAF该字符串是一个JAVA正则表达式。若没有指定,默认为普通字符串,建议使用”regex”

settings标签

标签是WAF的全局配置,本节内容主要讲解了WAF的两个基本内容:WAF的运行模式和error-hadling执行。示例如下:

<settings>  
   <mode>redirect</mode>
   <error-handling>
    <default-redirect-page>/security/error.jsp</default-redirect-page>
      <block-status>403</block-status>
   </error-handling>
</settings>  
子标签<mode>

子标签是必须的,”mode”表示高等级该如何处理严重的安全事件。安全事件发生在某些规则与传入的请求相匹配时,例如,如果用户访问规则时,应用应执行该模式配置的内容。然而,一条规则企图在每一个请求上触发,通常安全性的最佳实践是不依赖于其它操作。

“Mode”有三个配置可选项:redirect,block,log。

<mode>log</mode>配置为log时,WAF仅执行记录日志,并且在安全规则被触发时不执行任何其它操作。此模式可用于测试生产环境中的规则,以便在短时间调整安全规则。设置为其它任何值与设置成log相同,指定为log只是告诉WAF不要执行任何其它操作

<mode>redirect</mode>配置为redirect时,应用程序会重定向至302或者JavaScript客户端重定向的错误页面,具体取决于触发规则时应用程序的状态。用户被重定向的目标URL配置在<error-handling>标签中

<mode>block</mode> 当配置为block时,应用程序在发生严重的安全错误时会简单的停止处理请求,并且返回一个空响应

子标签<session-cookie-name>

子标签<session-cookie-name>是可选的,该值告诉WAF应用程序容器中session的cookie名称是什么,如果为空,则默认值为JSESSIONID。该标签尚为实验功能,不推荐使用。

子标签<error-handling>

在该项中配置两个值:<default-redirect-page>(默认重定向URL)和<block-status>(状态值)。

<default-redirect-page> 配置的是WAF处于<mode>redirect</mode>是发生严重安全事件后重定向的地址。它可以是一个相对或者绝对的URL地址,应用于客户端的302跳转和JavaScript中。建议将此值设置为通用错误页面

<block-status> 配置的是WAF处于<mode>block</mode>发生严重安全事件时要使用的HTTP状态码,常见的值为:401,302和500。当mode为log或者redirect时,此值不起作用。

Authentication-rules标签

<authentication-rules>标签允许WAF执行典型的J2EE认证请求。

典型的J2EE应用程序认证模式需确保session变量存在于某些基础action类中,如果该变量不存在,即表示该请求被认为是未经认证的并作适当的处理。但是,由于应用程序支持广泛的功能与服务,在保护所有需要认证的功能方面经常出现配置错误。

如果这种模式不能用于您的应用程序对用户进行认证操作,你可以不使用它。下面是一个<authentication-rules>标签的使用实例,它保护应用程序所有的URL,除了一些公开的静态内容和首页:

<authentication-rules path="/.*" key="UserAuthKey" >  
   <path-exception>/</path-exception>
   <path-exception>/index.html</path-exception>
   <path-exception>/login.jsp</path-exception>
   <path-exception>/index.jsp</path-exception>
   <path-exception type="regex">/images/.*</path-exception>
   <path-exception type="regex">/css/.*</path-exception>
   <path-exception type="regex">/help/.*</path-exception>
</authentication-rules>  

属性”path”是必须的,告诉WAF哪些URL是需要经过认证的,属性值为正则表达式。在上述的实例中,path的值为”/.*”,意思是对任何请求都将强制进行认证。

属性”key”是必须的,告诉WAF应该检查存在的session属性,如果此session属性具有任何非空值,即表示该用户已认证。

子标签<path-exception>

有很多规则可以嵌套在<path-exception>中,意思是告诉WAF不要将给定的规则应用于特定的URL中,即白名单。如果该标签的type属性设置为”regex”,才解析以正则表达式形式出现的路径URL。这些路径通用应用于放行静态资源文件,和其它任何用户不用登陆就能访问到的页面。

Authorization-rules标签

<authorization-rules> 标签允许WAF执行典型的J2EE授权请求。该标签支持两种不同类型的规则:<restrict-source-ip><must-match>

子标签<restrict-source-ip>

大多数应用都有普通用户和管理员用户,由于它们部署在同一个应用程序中,普通用户可以访问管理员页面,只要保险公司能够得到正确的URL或者窃取管理员的cookie/session。

<restrict-source-ip>规则通过IP限制对某些URL的访问来解决这个问题,通过这种方法有助于缩减暴露的管理员证书/登陆凭证带来的危害,允许颗粒度的网络策略来请求不同层次的应用程序。

<authorization-rules>  
   <restrict-source-ip
      type="regex"
      ip-header="X-ORIGINAL-IP"
      ip-regex="(192\.168\.1\..*|127.0.0.1)">/admin/.*</restrict-source-ip>
</authorization-rules>  

<restrict-source-ip>规则允许访问”/admin/.”的任何URL只能是本地局域网IP(192.168.1.)或是服务器本身。

属性”type”被设置为”regex”,告诉WAF被保护的路径是正则表达式形式的字符串

属性”ip-header”告诉WAF请求头将控制用户原始的IP地址,应用程序通常设置在一个或多个代理服务器的下游,这将掩盖请求的真实原始IP,这种情况下,应用通常会使用请求的真实IP填充请求头。在上述实例中,用户的IP地址可以在"X-ORIGINAL-IP"中找到,若不指定该字段,默认在HttpServletRequest对象中查找IP地址。

属性”ip-regex”,应该包含一个正则表达式,当匹配到一个传入的请求IP时,即表明该请求已被授权。

子标签<must-match>

规则是功能强大的标签,可以用来实现诸多不同的功能,特别是授权(基于角色的访问控制核查)
从技术上来讲必须规则是这样的: 在执行授权检查时,J2EE应用会在两个地方查询用户的角色:session或请求头。在下面的例子中,WAF将会在”x-roles”的请求头中查找是否包含字符串”admin”。

<authorization-rules>  
   <must-match
      path="^/admin/.*"
      variable="request.headers.X-ROLES"
      operator="contains"
      value="admin" />
</authorization-rules>  

下面是一个备用的示例,当用户角色存储在org.acme.user.roles这个session变量中

<authorization-rules>  
   <must-match
      path="^/admin/.*"
      variable="session.org.acme.user.roles"
      operator="inList"
      value="admin" />
</authorization-rules>  

这个例子中,”operator”为设置成”inList”,它将检查”variable”中设置的session变量。WAF知道如何检查包含所有基本列表对象的java.util.Collection, java.util.Enumerationjava.util.Map的任何子类,因此,如果您将用户角色存储在这些子类中的任何一个中,WAF可以在其中搜索”value”属性所指定的值。

属性”path”是必须的,它是一个正则表达式,它决定规则将应用于哪个路径。

属性”variable”是必须的,告诉WAF在哪里搜索”value”属性以授予访问权限 有五个地方可提供查找 属性”operator”是必须的,告诉WAF对于在”variable”属性中对”value”值执行什么样的操作,共四个可选项 属性”value”是必须的,表示需要通过测试的值。

Url-rules标签

<url-rules>标签允许开发者在HTTP状态行(请求的第一行)数据执行检查,在该标签中,您可以根据请求的文件扩展名(restrict-extension),请求的HTTP方法(restrict-method)和是否通过SSL(enforce-https)限制访问。

子标签<restrict-extension>

<restrict-extension>标签允许开发者限制访问服务器上的某些文件后缀名。评估经常发现在服务器上找到未受保护的静态资源,如代码,库。 下面的示例展示了如何预防任何到生产服务器上JAVA源代码的请求

<url-rules>  
  <restrict-extension deny=".java" />
</url-rules>  

属性”deny”和”allow”至少出现一个,且不能同时包含两个属性。但是可以有多个标签来实现预期的效果。属性值可以是一个正则表达式,如:.*\<value here>$

子标签<restrict-method>

默认情况下,大多数应用服务器允许用户滥用一些http方法,导致意外发生。<restrict-method>标签允许开发者预防无用的http方法请求应用程序。 下面的示例中展示了<url-rules>标签包含两个<restrict-method>子标签:

<url-rules>  
   <restrict-method deny="GET" path=".*\.do$" />
   <restrict-method allow="^(GET|POST|HEAD)$" />
</url-rules>  

属性”deny”和”allow”至少出现一个,且不能同时包含两个属性。但是可以有多个标签来实现预期的效果,属性值可以是一个正则表达式。

白名单(allow属性)和黑名单(deny 属性)有利也有弊,根据实际情况,同时使用可能效果会更好。 属性”path”是可选项,给WAF一个正则表达式来决定什么时候应用该规则,如果URL匹配path正则表达式,该规则即会执行。

子标签<enforce-https>

条件允许的情况下,WEB应用应该使用SSL,如果应用使用相对链接,则不强制使用SSL,攻击者可能会诱骗受害者去点击一个没有使用SSL的链接,可能会导致用户暴露敏感信息。

为了防止这种事件的发生,规则强制使用SSL。下面的示例中展示了如何在整个站点中强制使用SSL,并配置了一些静态非敏感内容的例外情况,如果用户用非SSL请求了匹配的URL,将会通过302跳转到使用SSL的对应URL页面。

<url-rules>  
   <enforce-https path="/.*">
     <path-exception>/index.html</path-exception>
     <path-exception type="regex">/images/.*</path-exception>
     <path-exception type="regex">/help/.*</path-exception>
   </enforce-https>
</url-rules>  

属性”path”是必须的,决定了网站哪部分使用SSL。所有例外情况都应该在子标签<path-exception>中列举出来。

子标签<path-exception>是可选的,可以有多个标签表明例外路径,当type=”regex”时,则支持正则匹配路径。

Header-rules标签

<header-rules>标签允许开发者对http请求头数据执行检查,在该标签中,您可以使用基于userAgent(restrict-user-agent)或contentType(restrict-content-type)来限制访问。

子标签<restrict-user-agent>

<restrict-user-agent>标签允许开发者根据用户UA来限制对网站的访问,有些UA表示它即为公开的不需要的流量,比如搜索引擎的robots。

<header-rules>  
   <restrict-user-agent deny=".*GoogleBot.*" />
   <restrict-user-agent allow=".*" />
</header-rules>  
子标签

<restrict-content-type>标签允许开发者根据请求内容类型限制对站点的访问。异常的content-types可以是CSRF攻击的指标,也可以用来绕过安全机制。

<header-rules>  
   <restrict-content-type deny=".*multipart.*" />
   <restrict-content-type allow=".*" />
</header-rules>  

Virtual-patchs标签

<virtual-patchs>允许开发者针对已知攻击实行虚拟补丁,如URL跳转,XSS,SQL注入等,您可以配置0个或多个<virtual-patch>规则。

子标签

<virtual-patch>规则是WAF 策略文件中最重要的规则之一,许多利用自动化工具的攻击都可以通过虚拟补丁修复。在下面的示例中简单修复了XSS漏洞 :

<virtual-patch  
   id="scr-15520"
   path="/foobar.jsp"
   variable="request.parameters.q"
   pattern="^[0-9a-zA-Z\s,\.]$"
   message="detected exploit of SCR #15520" />

属性”id”是<virtual-patch>的唯一标识,如果使用了唯一的ID,则在日志中可以区分哪条规则被触发。

属性”path”是应用到请求URI的正则表达式,若匹配则执行测试。

属性”variable”告诉WAF在分析哪个位置的属性值,有两个值可选: 属性”pattern”是一个正则表达式,如果匹配成功,则请求通过测试,若匹配失败,WAF会将它认为是严重的安全事件。

属性”message”是失败时要记录的文字字符串,日志会自动生成一些有价值的信息,这应该用来向人们指出这个规则失败的简单总结。

欢迎大家加入小密圈,一起交流进步

zhutougg

继续阅读此作者的更多文章