Tomcat 中的跨站点请求伪造防护过滤器

我们要演示的最后一个Tomcat 过滤器是跨站点请求伪造防护过滤器,在 org.apache.catalina.filters.CsrfPreventionFilter 类中实现。跨站点请求伪造(通常称为CSRF,发音为“sea-surf”)是一种黑客技术,用于通过以站点信任的用户身份向已知网站发出命令来利用网站的漏洞。攻击者利用URL的知识它使用用户的会话执行某些操作,如果会话仍然处于活动状态,它可以在用户不知情的情况下访问站点并执行有害操作。一个典型的 CSRF 场景是将已知的安全 URL 嵌入 HTML 图像标签,例如 <img src=”http://www.mybank/com/myaccount/sendmoney.html?toaccount=122121″>。如果毫无戒心的用户使用此 URL 加载恶意网页,同时用户具有与 www.mybank.com 网站的活动会话,则此图像标签将能够在用户不知情的情况下从用户帐户中转移资金。

Tomcat 的 CSRF 过滤器通过生成一个随机数(发出一次的随机数)来防止此类攻击,该随机数用于对请求 URL 进行编码,并且也存储在会话中。在每个请求上,都会将请求中的 nonce 与会话进行比较,如果它们不匹配,则请求将不会继续。这意味着来自恶意网站的请求将无法执行该操作,因为它没有与当前会话关联的随机数。

web.xml 文件中的 CsrfPreventionFilter 配置

<filter>

<filter-name>CSRFPreventionFilter</filter-name>

<filter-class>

org.apache.catalina.filters.CsrfPreventionFilter

</filter-class>

<init-param>

<param-name>entryPoints</param-name>

<param-value>/secure/index.jsp</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>CSRFPreventionFilter</filter-name>

<url-pattern>/secure/*</url-pattern>

</filter-mapping>

过滤器类必须引用CsrfPreventionFilter的完整类名. entryPoints 是Tomcat 的CSFR 过滤器唯一需要的初始化参数。它指定映射到过滤器的 URL,但不需要在请求中出现 nonce。这些 URL 是 Web 应用程序受保护部分的入口点,用于为第一次访问应用程序且在请求中没有随机数的用户生成随机数。必须至少存在一个入口点,否则生成的 nonce 将不会发送到客户端。entryPoints 参数的值是逗号分隔的 URL 列表。由于对此处配置的 URL 的访问将是免费的(入口点 URL 将不受 CSFR 过滤器的保护),因此这些 URL 不执行任何安全关键操作非常重要。此外,只有GET允许访问 entryPoints URL(禁止POST )。

最后,我们设置过滤器映射。配置的 entryPoints 与过滤器映射匹配很重要——否则将不会根据需要生成 nonce 值。让我们看看当用户尝试访问受保护的 URL 时这个过滤器做了什么。用户首先必须访问其中一个 entryPoints URL;您可以将这些视为网站主页。用户将被允许访问,但 CSRF 过滤器将拦截响应并为其生成一个随机字符串(nonce)。此 nonce 将被缓存并存储在用户会话中。同时,响应将使用相同的 nonce 值对 URL 进行编码。如果用户想要访问任何受保护的 URL(未配置为入口点),则需要将相同的 nonce 值作为请求参数提供。如果参数不存在,

将 nonce 作为必需参数的 URL 需要以编程方式计算,然后才能在页面上呈现为 HTML 的一部分。让我们根据上面清单中的配置看一个示例。URL /secure/showAccount.jsp 受 CSFR 过滤器保护,不是入口点。假设 /secure/showAccount.jsp 显示帐户信息,并且必须防止 CSRF 攻击。用户必须先访问入口点 URL (/secure/index.jsp),然后才能显示帐户页面。如果恶意网站试图直接访问账户页面(例如通过HTML 图像标签),请求中不会出现 nonce,访问将被禁止。

但是,如果用户直接在浏览器中键入显示的帐户 URL (/secure/showAccount.jsp) 会怎样?用户仍然会看到禁止访问页面!这是因为用户不知道已经生成的 nonce 值,必须作为请求参数传递。如果您使用 CSRF 预防过滤器,则必须通过单击连接页面的链接来访问所有页面,从入口点页面开始——您不能只在浏览器中键入 URL,因为您没有所需的随机数来传回到服务器!

下面显示了 /secure/index.jsp 页面,以及它如何链接到受保护的 /secure/showAccount.jsp 页面。

使用 JSP 页面中的 Nonce 参数对 URL 进行编码

<%

String url = response.encodeURL("apress/secure/showAccount.jsp");

%>

<a href="<%=url%>">Show Account</a>

我们通过在 JSP (#1) 中的响应对象上调用 response.encodeURL(...) 来生成带有 nonce 请求参数的 URL。正如我们之前所说,nonce 是在第一次访问入口点时生成的。此外,使用返回响应编码的 URL 将添加相同的 nonce 作为请求参数。我们使用编码后的 URL 作为锚点 HTML 标记中的链接。如果您在浏览器中查看生成页面的 HTML 源代码,您会看到 Show Account 链接指向以下 URL:

http://localhost:8080/apress/secure/showAccount.jsp?org.apache.catalina.filters.CSRF_NONCE=CB5C65E1D87A39D5557D6BCBC24E54A9。

Show Account URL 已通过添加 nonce 参数进行编码。nonce 参数名称是在 CsrfPreventionFilter – org.apache.catalina.filters.CSRF_NONCE 中定义的常量。它的长字符串值是实际随机生成的随机数。仅当作为参数传递的 nonce 值与会话缓存中存储的值匹配时,才会呈现受保护的 Show Account 页面。如果 nonce 值丢失,或与会话不匹配 -将呈现403 Forbidden 页面。除了需要的 entryPoints,CsrfPreventionFilter 还有两个可配置的初始化参数,randomClass 和 nonceCacheSize。

CSRF 过滤器配置的附加初始化参数

randomClass生成 nonce 值的类的完全限定名称。指定的类必须是 java.util.Random 的实例。如果未指定此参数,则 java.util.Random 是默认类。

nonceCacheSize为并行请求缓存的 nonce 值的数量,或者在使用返回和刷新按钮时,这可能导致 nonce 生成两次。默认值为 5。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值