V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
laziji
V2EX  ›  分享创造

普通网站防暴力破解登录密码的新设计

  •  1
     
  •   laziji · 2018-07-17 12:57:03 +08:00 · 16590 次点击
    这是一个创建于 2103 天前的主题,其中的信息可能已经有所发展或是发生改变。

    shield

    前端防暴力破解的一个设计

    Demo 地址

    https://github.com/GitHub-Laziji/shield

    描述

    传统的防范暴力破解的方法是在前端登录页面增加验证码, 虽然能有一定程度效果, 但是用户也跟着遭罪, 验证码越复杂, 用户登录的失败率越高

    于是最近我想了一个新的设计, 前端在登录时采用解密的方式获取密钥, 把密钥与表单以前发往后端, 用密钥来代替验证码

    具体细节如下

    设计

    • 用户在登录页面输完用户名密码, 点击登录
    • js 向后端请求密文
    • 后端生成一个随机字符串和一个指定范围内的随机数
    • 正向拼接 随机字符串 和 随机字符串随机数的加密 得到密文rstr+MD5(rstr+rint)
    • 反向拼接 得到 密钥 MD5(rint+rstr)
        randomString = Utils.getUUID();
        randomNumber = Utils.randomInt(range);
        privateText =  randomString + Utils.md5(randomString+randomNumber);
        privateKey = Utils.md5(randomNumber+randomString);
    
    • 将密文传给前端
    • 前端通过循环破解随机数
        let randomString = result.substring(0, 32)
        let valueString = result.substring(32)
        let answerString
        for (let i = 0; i < range; i++) {
            let s = crypto.createHash("md5").update(randomString + i).digest('hex')
            if (s == valueString) {
                answerString = crypto.createHash("md5").update(i + randomString).digest('hex')
                break
            }
        }
    
    • 把得到的密钥和表单一起传个后端
    • 后端验证密钥的真假

    测试

    经过测试 10000 次内 md5 加密前端用时不超过 300ms, 用户察觉不到, 但是暴力破解的难道确增加了几千倍, 这意味这本来一个小时能破解的网站, 现在可能要一年才能破解

    优势

    • 整个流程对后端带来的压力几乎为 0
    • 用户无需输入验证码
    • 前端延时极小(对人来说)
    • 对暴力破解影响极大
    • 只需添加部分代码, 无需更改现有的代码
    • 条件可控, 随机数的范围完全由后端决定
    第 1 条附言  ·  2018-07-17 13:52:51 +08:00
    好多人的关注点都是 "我知道加密方式, 我可以模拟"

    这没错 , 这个设计的目的就是让破解的人来模拟这个步骤啊 , 加密方式完全是公开的,

    但是你要提交密码就必须 尝试 数千次 的加密 才能获取到密钥 才能提交一次密码

    这样是不是就把可尝试密码的频率降到原来的数千分之一了 ?
    第 2 条附言  ·  2018-07-17 14:29:43 +08:00
    同一回复

    有的人的观点是
    "在后端直接延时 1 秒不就好了吗"
    "延时令牌之类的"

    这些直接通过多线程直接解决了 , 后端对一个回话的延时是没有用的 ,
    这个算法限制的是攻击者电脑的算力,
    第 3 条附言  ·  2018-07-17 14:52:48 +08:00
    这篇文章主要是探讨这种设计的可行性

    以及使用的这种设计所带来安全性的提升

    这个算法的优点之一是服务器的运行验证的压力非常小 , 既不需要查询数据库 已不需要复杂的运算

    请在同等情况下比较性能

    类似这些观点没有价值
    "黑客用 N 台肉鸡 请求服务器 照样会蹦 照样可以破解" ---- 如果没有的话可能一台好的计算机就把服务器搞挂了吧
    "延时请求, 延时回复之类" --- 攻击者开多线程 , 延时形同虚设 , 无谓的增加服务器的负担
    125 条回复    2018-07-21 15:56:26 +08:00
    1  2  
    carlclone
        101
    carlclone  
       2018-07-18 07:34:52 +08:00 via iPhone
    简单问题复杂化,楼主可能缺 star 面试了
    chuanqirenwu
        102
    chuanqirenwu  
       2018-07-18 08:46:38 +08:00
    请给出严格的数学证明,否则有可能存在一种方法使得你的方案与原方案没有差别。
    master13
        103
    master13  
       2018-07-18 09:02:16 +08:00
    我有个问题,可能是我没看明白……
    我暴破的时候,你这段前台循环碰密钥的方法已经给我了,我在本地碰好了在提交不行么……没必要通过提交来碰吧……具体比如用个 selenium 或者 phantomjs,应该很容易就可以在本地算出那个密钥吧
    qdwang
        104
    qdwang  
       2018-07-18 09:08:39 +08:00 via iPhone
    lz 你的想法是可以的,现代不少防暴力破解的密钥生成技术就是需要大量时间或者内存。只是你的想法需要再精细一些,或者用一些现成可靠的密钥生成技术。
    Antidictator
        105
    Antidictator  
       2018-07-18 09:19:59 +08:00
    喜欢这个帖子,有理有据的讨论,收藏了。
    mcluyu
        106
    mcluyu  
       2018-07-18 09:27:02 +08:00
    楼主这个貌似就是给请求 body 加个签名? 然而方法还是暴露的貌似,这种方式可以用在 APP 上,因为加签方法隐藏在代码里看不到(反编译也可以针对这快代码做防止反编译的处理),但是对于前端页面没意思了吧,你的解密方法大家都可以看到了,人家模拟一遍就行了啊,你前端页面 JS 可以做到的事情,破解的人也可以啊。。。
    Cheez
        107
    Cheez  
       2018-07-18 09:30:24 +08:00 via Android
    大哥,你的想法不错,但是直接限制 10 分钟内只能输入 3 次密码好像更好一点
    SelFree
        108
    SelFree  
       2018-07-18 09:36:14 +08:00
    web 前端慢 hash 了解一下?
    LeeSeoung
        109
    LeeSeoung  
       2018-07-18 09:41:30 +08:00
    1、楼主的加密没任何意义,前端能做到的加密流程,任何程序都能模仿出来。
    2、延时令牌方式 多线程下基本也没区别->改为限制 IP 时间段内访问次数
    3、限制 IP 访问次数可以通过代理 IP 解决
    4、引入页面人体行为检测(鼠标轨迹,按键等),发现机器行为不给接入,参考现在的拖动滑块验证码。
    5、蜜罐,让攻击者以为正确获取到信息,实际上并没有,在蜜罐上多设陷阱,这种考验攻击者耐心。
    lxy
        110
    lxy  
       2018-07-18 09:48:48 +08:00
    算力验证码。老东西了。
    wenzhoou
        111
    wenzhoou  
       2018-07-18 09:50:14 +08:00 via Android
    楼主是说:我不管我不管,我不听我不听。我这个就是有用,我这个就是好。😂
    Clarencep
        112
    Clarencep  
       2018-07-18 10:09:43 +08:00
    Clarencep
        113
    Clarencep  
       2018-07-18 10:15:34 +08:00
    似乎改进下,顺便还能挖挖矿……
    Citrus
        114
    Citrus  
       2018-07-18 10:16:42 +08:00 via iPhone
    大概看明白了楼主的意思,想通过强制前端进行高强度 MD5 计算来拖慢登陆重试频率。
    想法简单来看没啥大问题,但是要知道 MD5 计算现在并不慢,如果用 GPU 集群的话,枚举延迟可能并不大。所以实际效果可能没有想象中那么美好,起码没比验证码好太多。。。
    msg7086
        115
    msg7086  
       2018-07-18 10:36:52 +08:00
    只看你的描述:
    1. 你的服务器端必须要保存生成的密钥,而且密钥无法防止离线破解。
    也就意味着我可以先生成 1000 个密钥,统一计算完,然后一次发 1000 个登录请求上去。
    2. 你的服务器端必须保存密钥,意味着可以直接进行 DDoS 攻击,直接打爆你生成密钥的存储系统。

    所以到最后,你还是得在密钥生成系统上加上延时和保护。
    那么也就回到一开始的解决方案:直接给登录系统加上延时和保护了。
    338ccom
        116
    338ccom  
       2018-07-18 10:53:50 +08:00
    tumblr 的登录方式很不错
    killerv
        117
    killerv  
       2018-07-18 11:09:17 +08:00
    看了楼主的帖子和其他网友的跟帖,说下自己的理解。①有不少人理解错了,楼主的密钥算法是公开的,并不是靠这个来防止攻击,这点和常规 App 接口的签名算法并不是一个意思。②虽然如此,楼主这个还是意义不大,因为现在暴力破解网站用户名密码的瓶颈不在于计算,而在于 IO,打个比方,一个 web 应用的登录接口能承受的最大 QPS 是 1 万,计算机可以轻易做到 1s 内超过 1 万次的计算。
    remnet
        118
    remnet  
       2018-07-18 11:41:57 +08:00
    这就是一个 PoW 算法,几年前作为防止电子邮件垃圾的手段已经出现了。
    Refer: https://en.wikipedia.org/wiki/Hashcash
    009694
        119
    009694  
       2018-07-18 11:51:03 +08:00 via iPhone   ❤️ 1
    bcrypt 了解一下。 前端将原始密码 bcrypt 加密 后端用其他快速加密方案。 同样能解决
    snw
        120
    snw  
       2018-07-18 12:35:17 +08:00
    @jq8778
    你这个设计体验极差的。我们公司有个同事输错了 N 次开机密码(全盘加密的),由于每次输错都会比上一次多等几倍时间,等他想到求助 IT 时下次输入密码要等十几个小时,于是当天就没法工作了。

    最关键是攻击者完全可以对其他用户提交几次错误密码,导致其他用户无法登陆。
    zhangyuting
        121
    zhangyuting  
       2018-07-18 13:43:15 +08:00
    @laziji 发现自己的想法是已有且被证实可用的,是一件很愉快的事情。
    leoleoasd
        122
    leoleoasd  
       2018-07-18 13:44:10 +08:00
    @LeeSeoung 要的就是被模仿 拖慢别人的效率
    @master13 要的就是需要计算 算需要时间 大规模试密码需要的成本很大
    @msg7086 md5 之前的原文可以不储存 加密且带时间戳签名 后传给前端,前端登陆的时候再提交上去就可以 做好防重放就 ok
    galenzhao
        123
    galenzhao  
       2018-07-18 14:06:25 +08:00
    pow 注册轮子
    iyangyuan
        124
    iyangyuan  
       2018-07-18 14:17:15 +08:00
    这个就是慢 hash 嘛,故意增加算法难度,将 hash 的过程变慢,别忘了加上私有盐。
    据我所知,这个好像是避免脱裤之后暴力破解的
    keventseng
        125
    keventseng  
       2018-07-21 15:56:26 +08:00
    连续输入错误 X 次限制 X 分钟或者连续错误 X 次冻结,等用户重改密码恢复。会不会更简单些?
    1  2  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1092 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 23:31 · PVG 07:31 · LAX 16:31 · JFK 19:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.