图形验证码的常见安全问题

验证码的英文缩写是CAPTCHA,即:

Completely Automated Public Turing test to tell Computers and Humans Apart

译作”全自动人机区分的图灵测试”。

时下图形验证码的应用已经非常广泛了,无论是在web应用还是客户端软件中。主要是用来防止字典攻击(或称暴力猜解)、机器注册等。

可惜的是,大多数开发者不得要领,敷衍了事。验证码设计中常见的安全问题是:

  1. 验证码有逻辑缺陷,可被绕过,可被逆向
  2. 验证码太简单,容易被机器识别

下面分别说明。

问题一  把验证码是否出现的判断逻辑放在客户端浏览器

有些系统默认不显示验证码,而是在用户校验错误一定次数之后再出现。

那如何判断用户已经错误几次了呢?没有经验的开发可能这样做:

  1. 在cookie中写入一个标记,比如loginErr = 1,后续错误累加
  2. 在session中写入一个标记,例如loginErr = 1,后续错误累加

问题在于,要是攻击者不带Cookie提交HTTP请求呢?或者是,攻击者不更新Cookie中的loginErr的值反复提交呢?

程序因为无从获取Cookie/sessionID,会认为攻击者是首次访问。无论什么时候,验证码都不会出现!

问题二 验证码不过期,单个验证码反复可用

多数时候,验证码在web服务器上对应一个session值。

如果完成一次校验,不标记这个session已失效,就会造成同一验证码反复可用。

此时,验证码将不再有用。

攻击者在cookie中带固定的sessionID和固定的一个验证码字符串,即可轻松爆破。

还有一种很常见的代码实现,更新session的工作是通过重新下载验证码达到的。

而开发人员容易犯的一个失误,是把更新session的任务交给客户端浏览器。

比如302重定向,甚至是通过js、meta refresh重定向页面,来引导用户重新下载验证码。

这些做法实际是错误的,要是用户拦截了重定向,没有发出新的下载请求呢? 这样,上次的验证码是否还可以使用?

基本的认识是: 一张验证码,只能使用一次。使用之后,立即过期,不可再次使用。

问题三   将验证码内容输出到客户端

无论出于什么考虑,都不应该把验证码的内容发送到客户端cookie、或输出到response headers的其他字段。

比如,写入验证码的MD5值、 Base64转码等,太容易被攻击者逆向破解,得到原值。

即便是加固定salt后输出,都是很不好的。

问题四  验证码太弱

一般,出现逻辑错误的验证码,同样存在太弱的通病,使用开源的tessertact OCR引擎,不经任何训练,

不人工去噪处理,能识别互联网上的大部分验证码!

修改建议:

1) 强制要求输入验证码,否则,必须实施IP策略。 注意不要被X-Forwaded-For绕过了!

2) 验证码只能用一次,用完立即过期!不能再次使用

3) 验证码不要太弱。扭曲、变形、干扰线条、干扰背景色、变换字体等。

4) 大网站最好统一安全验证码,各处使用同一个验证码接口。

以上为后生粗浅的认识,请批评指正。

《图形验证码的常见安全问题》上有4条评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注