最新消息:

验证码常见安全问题

安全知识 admin 1604浏览 0评论

0x00 前言

首先,我们来看下整个验证码实现的原理

jinglingshu_2015-05-06_13-05-34

  • 1.客户端发起一个请求
  • 2.服务端响应并创建一个新的SessionID同时生成一个随机验证码。
  • 3.服务端将验证码和SessionID一并返回给客户端
  • 4.客户端提交验证码连同SessionID给服务端
  • 5.服务端验证验证码同时销毁当前会话,返回给客户端结果

0x01 安全问题及案例

(1). 验证码在页面或者cookies中输出。这个时候只需要提取一下就能直接使用了。经过加密的也不行,也可以直接去替换密文。

(2). 验证码验证完成后没有销毁,导致验证码重复使用。 验证码的值是在session中存储的,每次提交之后对比判断是否正确。如果验证完成后,没有更换或者清除session中的值,这时,如果不重新请求验证码就能一直使用之前的那个值了。 这里有一个案例 http://wooyun.org/bugs/wooyun-2010-025053 还比如 https://github.com/tianyu0915/DjangoCaptcha/blob/1b43e2af98b055c2e4b55a724f772b352de9c914/DjangoCaptcha/init.py

def check(self,code):
    """ 
    检查用户输入的验证码是否正确 
    """
    _code = self.request.session.get(self.session_key) or ''
    if not _code:
        return False
    return _code.lower() == str(code).lower()

比如说这个验证码用在用户登录页面上,每次提交都需要验证码。我就可以把第一次显示验证码aeft设置的cookies记录下来,每次提交这个cookies和对应的验证码aeft就行了。这样就能绕过验证码了。 我后来基于这个自己改写的验证码逻辑是

def check(self, code):
        """
        检查用户输入的验证码是否正确
        """
        _code = self.request.session.get(self.session_key) or ''
        if not _code:
            return False
        expires_time = self.request.session.get(self.captcha_expires_time) or 0
        # 注意 如果验证之后不清除之前的验证码的话 可能会造成重复验证的现象
        del self.request.session[self.session_key]
        del self.request.session[self.captcha_expires_time]
        if _code.lower() == str(code).lower() and time.time() < expires_time:
            return True
        else:
            return False

(3). 验证码不过期 验证码应该是有过期时间的,验证的时候判断,如果超时就认为是输入错误。参考上面我的代码

(4). 各种脑残的判断是否需要验证码的逻辑问题

  • 是否需要验证码是放在cookies或者session中的。比如说你登录的时候,错误次数超过3就要出现验证码,每次输入错误都加1,这个值存 放在cookies或者session中,如果攻击者每次请求之前清除了本地的cookies,那服务器没办法识别了。这个情况下,应该是在数据库中对用 户名和是否需要验证码进行绑定。
  • 有的系统中,没有请求验证码的时候session中对应的值是空字符串或者固定值,这样的话,前端拦截了验证码请求之后,这个值就不会发生变化,验证码字段直接提交空字符串或者固定值就行了。

(5). 验证码太弱,容易被识别。 这个问题应该是安全和用户体验的平衡,常用的验证码识别技术参考 http://drops.wooyun.org/tips/4550 http://drops.wooyun.org/tips/141

(6).新型验证码的问题 比如说 https://www.v2ex.com/t/138479 这个验证码就是可以通过代码模拟得到几乎100%的通过率。还有图片验证码和语言验证码同时出现的那种,可能语音验证码就比图片验证码更好识别。

0x03修改建议


梳理清楚验证码实现逻辑。(包括不限于验证码会话及时销毁等) 验证码不要太简单。扭曲、粘连等。

推荐Google的ReCaptcha

0x04 参考


https://www.owasp.org/index.php/Testing_for_Captcha_(OWASP-AT-008) http://www.mcafee.com/uk/resources/white-papers/foundstone/wp-attacking-captchas-for-fun-profit.pdf http://www.lijiejie.com/safe-issues-of-captcha/ http://*.wooyun.org

 

——————————————————————————————————————–

安全问题及案例

根据上面的实现流程,我们大概可以从四个方面入手,客户端问题、服务端问题、验证码本身问题,还有一个验证码流程设计问题。

1. 客户端问题


客户端生成验证码

验证码由客户端js生成并且仅仅在客户端用js验证

WooYun: 南开大学信息门户网站设计不当可以爆破用户密码(利用密码猜用户)

验证码输出客户端

输出在html中(神一样的程序员)

WooYun: 索尼验证码实现缺陷

WooYun: 某会考报名系统验证码绕过可暴力破解(可导致用户信息泄露)

验证码输出在cookie中,这个在乌云中案例也是比较多的。

WooYun: 吉祥航空任意客票遍历

WooYun: 5173验证码可被绕过

2. 服务端


验证码不过期,没有及时销毁会话导致验证码复用

这个是最常见的,乌云上面有大量的案例。

WooYun: 苏宁易购某系统后台多个超级管理员弱口令(验证码可重复利用)

没有进行非空判断

很多时候,我们会遗留掉了验证过程中验证码为空的情况

比如去掉cookie中的某些值或者请求中验证码参数

WooYun: cmseasy后台暴力破解验证码绕过

WooYun: ecshop后台暴力破解验证码绕过

WooYun: ecshop绕过验证码暴利破解2

产生的验证码问题集内的答案非常有限

WooYun: 139邮箱图验证码绕过漏洞(目前图形验证码的可预测案例)

3. 其他类型验证码绕过


“调试功能”还是设计缺陷?

WooYun: 阿里巴巴某员工登录接口验证码绕过可撞弱密码

WooYun: 凡客某处验证码绕过漏洞

WooYun: 财付通商户版登录验证码绕过

WooYun: 正方教务管理系统设计错误,可绕过验证码进行暴破或扫弱口令

“逗你玩”类型

有验证码,你输入什么 ,它都给你过,不验证

WooYun: 网宿某站SQL注入漏洞及验证码绕过

万能验证码(后门?)

WooYun: 百度空间用户登录绕过验证码验证

4. 验证码太简单,容易被机器识别


直接引用猪猪侠的两个金融案例

WooYun: 银行业(招商银行)设计缺陷可被穷举攻击

WooYun: 光大证券交易系统资金账号可被穷举攻击

 

转自:http://drops.wooyun.org/web/5459

https://virusdefender.net/index.php/archives/176/

转载请注明:jinglingshu的博客 » 验证码常见安全问题


Warning: Use of undefined constant PRC - assumed 'PRC' (this will throw an Error in a future version of PHP) in /usr/share/nginx/html/wp-content/themes/d8/comments.php on line 17
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址