设计无状态验证码,大家看下是否可行,有没有什么漏洞? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
guyskk
V2EX    Python

设计无状态验证码,大家看下是否可行,有没有什么漏洞?

  •  
  •   guyskk
    guyskk 2016-03-30 11:49:05 +08:00 8296 次点击
    这是一个创建于 3497 天前的主题,其中的信息可能已经有所发展或是发生改变。

    无状态验证码不需要在 SESSION 中保存数据,流程如下:

    1. 服务端先配置一个密钥 KEY
    2. 客户端请求验证码 TOKEN, 服务端生成一个随机字符串 TEXT ,再生成一个 SALT ,用 KEY 和 SALT 对 TEXT 进行加密 加密后的 TEXT 和 SALT 拼接到一起,作为 TOKEN 返回给客户端
    3. 客户端请求验证码图片,携带验证码 TOKEN, 服务端根据 KEY 和 TOKEN 中的 SALT ,解密出 TEXT ,用这个 TEXT 生成一幅图片
    4. 客户端发送业务请求,携带验证码 TOKEN 和用户输入的 CODE, 服务端根据 KEY 和 TOKEN 中的 SALT ,解密出 TEXT ,和 CODE 比对

    代码 https://github.com/guyskk/kkblog/blob/master/kkblog/captcha.py

    大家看下是否可行,有没有什么漏洞?

    31 条回复    2016-06-23 13:18:38 +08:00
    jedyu
        1
    jedyu  
       2016-03-30 11:55:03 +08:00
    把 Session 中的数据挪到了 Token 中而已
    cxh116
        2
    cxh116  
       2016-03-30 11:56:39 +08:00
    你要明白 session 的 id 不过是存在 cookie 里面的一个 token 而已.
    guyskk
        3
    guyskk  
    OP
       2016-03-30 11:58:05 +08:00
    @jedyu 是的,这样服务器就不需要保存 Session ,客户端也可以不用 Cookie
    Archangel_SDY
        4
    Archangel_SDY  
       2016-03-30 11:59:08 +08:00   4
    这个验证码没有有效期,并且可以多次使用? 那我始终拿一组 Token 和 Code 去刷就可以了呗.
    loading
        5
    loading  
       2016-03-30 12:01:01 +08:00 via Android
    jugelizi
        6
    jugelizi  
       2016-03-30 12:04:17 +08:00   1
    哈后 4L 一脚踢坏了楼主的轮子
    guyskk
        7
    guyskk  
    OP
       2016-03-30 12:06:53 +08:00
    @Archangel_SDY 确实是。在第 2 步中,随机字符串 TEXT 后面再加上有效期应该可以。验证码在有效期内可以重复使用。
    ybdhjeak
        8
    ybdhjeak  
       2016-03-30 12:10:13 +08:00
    直接把 code 加密写进 cookie 不就行了,下次让客户端带着 cookie 和验证码一起来
    guyskk
        9
    guyskk  
    OP
       2016-03-30 12:11:40 +08:00
    @guyskk 有效期 1~3 分钟
    ybdhjeak
        10
    ybdhjeak  
       2016-03-30 12:12:11 +08:00
    你的 token 和 cookie 没啥区别吧,只不过是传递方式不同, session id 也可以用参数形式传递啊
    xiaolanglang
        11
    xiaolanglang  
       2016-03-30 12:14:17 +08:00   1
    @guyskk 不加仅能使用一次的限制,验证码就形同虚设,对于暴力提交请求的程序来说, 1 分钟识别一次验证码相当于没有验证码
    keller
        12
    keller  
       2016-03-30 12:17:14 +08:00
    有效期内这个验证码不就可以无限使用啊?
    ty0716
        13
    ty0716  
       2016-03-30 12:18:09 +08:00
    应该携带一个应用的 id,有效时间是多少,当下次刷新时,自动将该应用 id 的验证码删掉,
    反正就是要保证验证码只能用一次。 不然还叫什么验证码
    dndx
        14
    dndx  
       2016-03-30 12:20:55 +08:00
    目测有效期内可以重放,对机器人来说还是很方便的。
    knightdf
        15
    knightdf  
       2016-03-30 13:03:13 +08:00
    这不是一次性的验证码。。。
    menc
        16
    menc  
       2016-03-30 13:25:33 +08:00
    没有漏洞,而且是业界一直在采用的方案。。
    不过业界把这个东西叫做 csrf token ,因为这样一次性的 token 可以防止 csrf 攻击,
    事实上,如果 token 用后即扔的话,用不着对 token 这么大张旗鼓的做手脚
    knightdf
        17
    knightdf  
       2016-03-30 13:30:01 +08:00
    @menc 大哥,你是混哪个业界的?好
    flowfire
        18
    flowfire  
       2016-03-30 14:22:46 +08:00
    何必呢。。。
    cheneydog
        19
    cheneydog  
       2016-03-30 14:42:48 +08:00
    1. 服务端的密钥 KEY 是全局的所有用户所有请求都一样
    2. 加密后的 TEXT 和 SALT 拼接到一起返回,相当于暴漏了 SALT
    有一定的被猜解的可能性。


    也不觉得比加密后写入 cookie 有什么优势。
    wlsnx
        20
    wlsnx  
       2016-03-30 14:58:16 +08:00
    有点奇怪,为了避免保存数据,所以每次都生成新数据,逻辑更复杂了。
    qiyuey
        21
    qiyuey  
       2016-03-30 16:18:33 +08:00
    你只是做了一个简化版的 session
    shade
        22
    shade  
       2016-03-30 18:44:33 +08:00
    OAuth 也是这样的吧
    cevincheung
        23
    cevincheung  
       2016-03-30 18:47:15 +08:00
    @wlsnx web 集群解决 session 一致性
    Abirdcfly
        24
    Abirdcfly  
       2016-03-30 19:29:18 +08:00 via iPhone
    @knightdf 我觉得他说的没错啊。默认是 cookie 来做这些事情。有的禁止 cookies ,不就用的是这个方案?
    zwzmzd
        25
    zwzmzd  
       2016-03-30 19:39:37 +08:00   1
    ddou
        26
    ddou  
       2016-03-30 20:08:06 +08:00
    @zwzmzd 内容不错,非常感谢。
    shade
        27
    shade  
       2016-03-31 13:19:59 +08:00
    webhook 是什么?
    guyskk
        28
    guyskk  
    OP
       2016-03-31 16:04:05 +08:00
    @shade kkblog 代码里面的吗,那个是 github 的开放接口
    playsoso
        29
    playsoso  
       2016-06-23 11:26:17 +08:00
    我觉得可以使用 jwe 方案 ,也就是 jwt 其中客户端内容加密过 , 请求验证码同时 发放 token , 提交验证码时携带 token
    通过 token 里 签发时间和过期时间来判断是否有效 , token 内容与验证码结果做比对
    playsoso
        30
    playsoso  
       2016-06-23 13:01:33 +08:00
    @playsoso 因为涉及到重放攻击,而且验证码有状态 服务端需要记录是否发放过验证码 和 验证码是否已验证过,所以还是需要依赖服务端 状态保存
    guyskk
        31
    guyskk  
    OP
       2016-06-23 13:18:38 +08:00 via Android
    @playsoso 要保证验证码只能用一次,服务端必需要有状态,所以无解。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2444 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    Wold is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 05:16 PVG 13:16 LAX 22:16 JFK 01:16
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86