了解 CSRF 验证码的工作原理
跨站点请求伪造(Cross-site request forgery,又称:跨站点引用伪造)是一种针对Web应用的攻击形式。黑客通过伪装恶意请求,诱骗用户运行他们本不打算执行的任务。尽管CSRF可能听起来与XSS攻击类似,但它们的执行方式存在根本差异。 一、为什么需要有效的CSRF令牌? CSRF令牌通常被建议添加到所有状态更改(state-changing)的请求中,以便在后端被执行验证。由于只有应用服务器和客户端可以识别令牌,因此后端必须确保传入的请求包含有效的CSRF令牌,以避免XSS或跨站点请求伪造攻击的得逞。 二、CSRF令牌在防止攻击中的意义 由于令牌在生成过程中使用到了伪随机数(pseudo-random number)生成器、静态密钥、以及种子时间戳,因此CSRF令牌的值是不可预测的。同时,每个用户的令牌也是不同的,而且只会存储活动的用户会话。 三、如何使用CSRF令牌 尽管我们可以在URL查询字符串中放置令牌,但是查询的字符串记录会被留存在服务器和客户端的多条记录中。因此,查询字符串可以在客户端屏幕的浏览器上被访问到,甚至会在HTTP引用标头中,被传输给第三方应用程序。 四、如何在Java中实现CSRF令牌 由于Java应用缺乏了针对CSRF攻击的固有保护。因此,我们建议在Java中实现CSRF令牌的时候,请使用一个过滤器和一些辅助类,来启用令牌的创建、资源的分析、以及响应的构建。例如,您可以使用通用无状态(Generic Stateless)过滤器,来实现了双重提交(double-submit)的Cookie模式,以启用CSRF保护。同时,您可以采用如下工作流程:首先,如下面代码段所示,过滤器会在Java应用的web.xml文件中被定义: 复制 <filter> <filter-name>CSRFFilter</filter-name> <filter-class>com.github.adriancitu.csrf.GenericCSRFStatelessFilter</filter-class> <filter> <filter-mapping> <filter-name>CSRFFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> 该过滤器包括了两个可选的初始化变量: 1.csrfHeadername– 包含了令牌的标头名称 2.csrfCookieName– 用于存储CSRF令牌的Cookie的ID。 对于每个HTTP请求,过滤器都会提供一个ExecutionContext类的实例。它包含了CSRFcookie、以及HTTP请求与响应的Java对象。同时,该类也包含了ResourceCheckerHook、ResponseBuilderHook和TokenBuilderHook等辅助类的实现。 接着,过滤器会根据如下三种情况,去检查所请求的HTTP资源的保护状态: 1.MUST_NOT_BE_PROTECTED 2.MUST_BE_PROTECTED_BUT_NO_COOKIE_ATTACHED 3.MUST_BE_PROTECTED_AND_COOKIE_ATTACHED 对于状态为MUST_NOT_BE_PROTECTED和MUST_BE_PROTECTED_BUT_NO_COOKIE_ATTACHED的资源,过滤器会生成一个由TokenBuilderHook类提供的CSRF令牌的Cookie。对于带有标签MUST_BE_PROTECTED_AND_COOKIE_ATTACHED的资源,过滤器则使用ResourceCheckerHook去检查资源的CSRF保护状态,然后使用类ResponseBuilderHook向客户端返回一个响应。当然,上述代码只是一个参考示例,在实际运用中,还需要开发团队在源代码中进一步构建CSRF缓解机制。 五、如何在PHP中实现CSRF令牌 由于PHP使得开发人员能够创建具有交互功能的动态网站,因此它在内容管理系统领域备受欢迎。不过,我们需要在PHP联系人和用户输入的表单中,通过实现post处理程序,对传入请求予以验证,让网站免受CSRF的攻击。SecurityService会被写入这个用于验证请求的令牌,并将令牌加载到隐藏字段中。如下代码展示了典型的SecurityService.php配置: public function getCSRFToken() { if (empty($this->session[$this->sessionTokenLabel])) { $this->session[$this->sessionTokenLabel] = bin2hex(openssl_random_pseudo_bytes(32)); } if ($this->hmac_ip !== false) { $token = $this->hMacWithIp($this->session[$this->sessionTokenLabel]); } else { $token = $this->session[$this->sessionTokenLabel]; } return $token; } 左右滑动查看完整代码然后,页面上呈现PHP联系人表单,以便用户输入诸如主题、消息、姓名和电子邮件等详细信息。表单还应当在隐藏字段中包含已生成的标记--csrf-token。在用户单击提交按钮后,应用程序将执行JQuery表单验证,并将各种参数发布到PHP上。 (编辑:银川站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |