WEB安全新玩法 [6] 防范图形验证码重复使用

在完成关键业务操作时,要求用户输入图形验证码是防范自动化攻击的一种措施。为安全起见,即使针对同一用户,在重新输入信息时也应该更新图形验证码。iFlow 业务安全加固平台可以加强这方面的处理。


某网站系统在登录时要求用户输入图形验证码。如果账号信息错误并得到系统提示后,用户重新输入账号信息时,仍可使用原来的图形验证码。我们看看如何利用 iFlow 使得图形验证码每次都得到更新。




一、原始网站


1.1 正常用户访问

用户在登录时输入了正确的图形验证码字符,如果提交的账号信息有误,系统提示登录错误。

WEB安全新玩法 [6] 防范图形验证码重复使用_第1张图片

用户仍使用原来的图形验证码字符,提交了正确的账号信息后,系统提示登录成功。

WEB安全新玩法 [6] 防范图形验证码重复使用_第2张图片

HTTP 交互流程如下:

正常用户 浏览器 Web服务器 账号、错误的密码、验证码 请求:登录 返回:登录失败 显示:登录失败 账号、正确的密码、原来的验证码 请求:登录 返回:登录成功 显示:登录成功 正常用户 浏览器 Web服务器


1.2 攻击者访问

用户登录失败,网站没有主动更新图形验证码,而是一段时间内仍接受这个验证码。这个特性具有用户友好性,但增加了安全风险。

这样,攻击者即使没有使用图形验证码识别工具,也可以在人工识别出验证码后,在验证码过期时间之内,使用工具进行多次的撞库请求,并记录下成功登录的账号密码组合。

WEB安全新玩法 [6] 防范图形验证码重复使用_第3张图片

HTTP 交互流程如下:

攻击者 浏览器 攻击工具 Web服务器 账号、错误的密码、验证码 请求:登录 返回:登录失败 显示:登录失败 不同的账号/密码对 请求:登录 返回:登录结果 记录登录成功的账号/密码对 loop [验证码超时时间内] 攻击者 浏览器 攻击工具 Web服务器



二、iFlow虚拟补丁后的网站

我们在 Web 服务器前部署 iFlow 业务安全加固平台,它有能力拦截、计算和修改双向 HTTP 报文并具备存储能力,成为 Web 应用的虚拟补丁。在本例中,iFlow 记录所有出现过的验证码,不允许用户重复使用这些验证码。


2.1 正常用户访问

iFlow 不允许使用重复的验证码。正常用户登录失败后,需要刷新页面或刷新验证码再进行登录。用户如果使用相同的验证码,iFlow 会自动刷新页面并产生新的验证码,用户需要输入新的验证码进行登录。

正常用户的 HTTP 交互流程如下:

正常用户 浏览器 iFlow Web服务器 账号、错误的密码、验证码 请求:登录 验证码不在used_vcode中 将验证码加入到used_vcode中 请求:登录 返回:登录失败 显示:登录失败 账号、正确的密码、旧的验证码 请求:登录 验证码在used_vcode中 返回:重定向页面 请求:新登录页面 返回:新验证码的登录页面 显示:新验证码的登录页面 账号、正确的密码、新的验证码 请求:登录 验证码不在used_vcode中 将验证码加入到used_vcode中 请求:登录 返回:登录成功 显示:登录成功 正常用户 浏览器 iFlow Web服务器


2.2 攻击者访问

如前所示,攻击者首次人工识别出验证码后,用攻击工具连续发出相同验证码的不同账号/密码组合去尝试登录。iFlow 拦截这些请求,发现验证码已使用过,则返回 302 重定向响应。鉴别过程并未在 Web 服务器上进行,攻击者得不到鉴别结果。

攻击者的 HTTP 协议交互过程如下:

攻击者 浏览器 攻击工具 iFlow Web服务器 账号、错误的密码、验证码 请求:登录 验证码不在used_vcode中 将验证码加入到used_vcode中 请求:登录 返回:登录失败 显示:登录失败 不同的账号/密码对 请求:登录 验证码在used_vcode中 返回:重定向页面 得不到登录是否成功的信息 loop [验证码超时时间内] 攻击者 浏览器 攻击工具 iFlow Web服务器


2.3 代码

iFlow 内置的 W2 语言是一种专门用于实现 Web 应用安全加固的类编程语言。它介于配置和通用语言之间,具备编程的基本要素和针对 HTTP 协议的特有扩展,能为业务系统编写涉及复杂判断和动态修改的逻辑。

考虑到安全产品的使用者通常为非程序员,他们习惯面对配置文件而非一段代码。因此,W2 语言虽包含语言要素,仍以规则文件方式呈现,并采用可以体现层次结构和方便词法校验的 JSON 格式。

用 W2 语言实现上述虚拟补丁的代码如下:

{
     
    "if": [
        "streq(REQUEST_FILENAME, '/shopx/index.php')",
        "streq(@ARGS.s, '/index/user/login.html')"
    ],
    "then": {
     
        "if": "contain(SESSION.used_vcode, @ARGS.verify)",
        "then": {
     
            "verdict": {
     
                "action": "redirect",
                "param": "/shopx/index.php?s=/index/user/logininfo.html",
                "log": "user ${SESSION.user} reuse verify code."
            }
        },
        "else": "SESSION.used_vcode@600 = SESSION.used_vcode .. ',' .. @ARGS.verify"
    }
}

示例代码只有一条规则,它使用存储变量 used_vcode 记录所有已使用的验证码。当有登录请求时,规则判断验证码请求参数 verify 是否在本会话 (SESSION) 的存储变量 used_vcode 中存在:

  1. 如果存在:表明此请求重用了验证码,直接返回重定向到登录页面的响应。
  2. 如果不存在:表明此请求使用新的验证码,将验证码加入到本会话 (SESSION) 的存储变量 used_vcode 中,继续进行实际的登录鉴别过程。

注意:上述会话中的 used_vcode 是保存在服务器端的 iFlow 存储中的,攻击者在浏览器端是看不到数据更无法进行修改的。




三、总结

iFlow 使用一条规则就可以在不改动后端程序的情形下,避免用户使用重复的验证码。

需要说明的是,文中的解决方案仅是一个示例,其一定程度上影响了人机交互的流畅性。而 iFlow 是一种灵活的类编程语言,使用它应该能写出更完善的处理流程。

你可能感兴趣的:(WEB安全,WEB安全新玩法,web,安全,运维)