V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
userKamtao
V2EX  ›  程序员

盼大佬解答,前端加密到底是不是脱裤子放屁?

  •  
  •   userKamtao ·
    lewkamtao · 2024-03-20 16:16:27 +08:00 · 34607 次点击
    这是一个创建于 374 天前的主题,其中的信息可能已经有所发展或是发生改变。

    闲暇之余,探索了一个小伙伴的开源网站,无意中发现了他的修改密码接口,是明文传输的,如下图。

    6361710921930_.pic_bvfob1_.jpeg

    后来我跟他反应了这个问题,我的观点是应该在前端 md5 加密一下,他说,他在后端做了加密处理,明文传输没问题,网站是 https ,前端加密不就等于脱裤子放屁吗?

    和他几番讨论之后,无果,也有几个小伙伴觉得前端加密等于自己骗自己。

    我经验比较单薄,以至于没有什么实际上的论点去论证,希望有大佬解答一下,这种场景在前端加密有没有意义。

    第 1 条附言  ·  2024-03-20 18:02:55 +08:00
    讨论相当激烈,很多大佬说 md5 是摘要算法不是加密算法,加密这方面确实是我的知识盲区。

    其实 md5 不可逆,我觉得用 md5 没问题,就是要不可逆,后端只负责存储和验证 md5 之后的字符串。
    第 2 条附言  ·  2024-03-20 18:49:39 +08:00
    感觉讨论的方向,有点脱离了我起初建立这个帖子的意义,我就是想表达,用户的密码不应该明文到达服务端,这就是我所说的“前端加密”,而不是底下大佬说的那种暴露前端的可逆“前端加密”,暴露在前端的可逆加密算法的确是脱裤子放屁,但是 md5 这种不可逆的算法,暴露无所谓,至少用户的密码已经得到了保护。至于密码难度规则校验,可以在前端实现,
    第 3 条附言  ·  2024-03-21 10:08:41 +08:00
    很多兄弟给出了更加安全的做法,但是其实这个帖子的初衷,就是讨论前端加密有没有意义,其实前端加密也就几行代码,不见得多大的成本,但只要有能说得出来的意义,那其实还是值得去放这个屁的。
    第 4 条附言  ·  2024-03-21 12:32:11 +08:00
    此话题终结吧,讨论了 3 页了,总结一下双方的观点。

    有必要加密:
    1 、防止无意泄露和二次伤害。(打 debug 日志无意间把用户输入打到日志)
    2 、隐私合规问题,参差不齐的员工可以拿到密码加用户手机号,登录任何设置此密码的网站。

    无必要加密:
    1 、https + 后端加密入库足够安全。
    2 、后端需要验证密码复杂度(业务场景)
    3 、增加开发成本,没必要。
    4 、加密后导致密码强度的下降(因为密文的信息熵下降了)
    336 条回复    2024-05-23 17:52:17 +08:00
    1  2  3  4  
    mengpp
        301
    mengpp  
       2024-03-21 16:38:42 +08:00
    后端直接存储前端的计算结果,跟明文不是没区别吗,都是可重放的,你的后端接口只认 md5 ,截获 md5 跟截获密码没区别,要加密就得加盐,加盐就得解密,就不能像你说的直接存
    dcdlove
        302
    dcdlove  
       2024-03-21 16:42:10 +08:00
    @wentx 后端为什么要知道用户的密码?正常就不该知道,你只需这个 md5 字符串匹配对不对就行了,后端只需要能判断密码字符串能否匹配正确就行,参与过等保要求的项目吗?
    1018ji
        303
    1018ji  
       2024-03-21 16:42:38 +08:00
    别的我不知道,你不加密不处理下咋上传用户隐私,明文搞?
    wentx
        304
    wentx  
       2024-03-21 16:44:41 +08:00
    @dcdlove #302 中间人拿到 md5 不也就能正常访问了嘛?跟密码不一样嘛?
    gerefoxing
        305
    gerefoxing  
       2024-03-21 16:48:56 +08:00
    需要的,因为现在很多同个用户在各网站密码都差不多,可以防止撞库,而且越来越多的个人敏感信息也需要加密或者***显示
    ap010gi2e
        306
    ap010gi2e  
       2024-03-21 17:04:30 +08:00
    防人用的。你明文那么你的服务端同学是可以看到密码的。企业中对于用户信息的合规是不可以暴露的。传输过程 HTTPS 确实可以保证。甚至浏览器觉得就算是浏览器自己丢掉都是可以的。但是你的密码明文传递给了提供你服务的人。并不能保证不会被乱用。核心就是你把你的密码直接告诉了第三个人。这个人不属于网络安全环节。
    dcdlove
        307
    dcdlove  
       2024-03-21 17:05:10 +08:00
    @wentx 用户表单输入密码:123456
    请求前 非对称加密:jk06U1oTYAoEhvbJVRrBFfhDzweWw7GQVkxmPUnuUWAFCKAFTZkX8vDwu6ewjxcvWwoO3D5l7sapmeDm+dyQIA==
    实际请求参数(用户名,密码,一次性 token ,参数签名字符串)
    后端接口会对请求签名和是否过期验证,请求后端处理过一次就会过期,如果中间人劫持,他首先无法修改请求内容,再加上每个请求只能验证一次,所以无法完成重放攻击
    jhdxr
        308
    jhdxr  
       2024-03-21 17:22:24 +08:00
    @liuidetmks #222 你说的是数据库里存放的数据应该做哈希。对于这一点我完全同意。

    我说的是服务器被黑指的是黑客已经完全掌握了服务器的权限。在这种情况下,哪怕你原有的设计是前端哈希后再进行发送,我作为黑客我也可以把它改成了发明文然后在服务器端进行拦截。
    aababc
        309
    aababc  
       2024-03-21 17:49:54 +08:00
    @dcdlove 不懂这么折腾的目的是啥,是直接使用加密之后的作为密码,还是需要解出来原始内容作为密码,就是为了防止研发在日志里输出密码?或者说就是为了防止没有私钥的人窥探密码?
    dhb233
        310
    dhb233  
       2024-03-21 17:59:31 +08:00
    @aababc #309 还真就要防止研发在日志里输出密码,不过这只是一种泄露密码的原因。

    总的来说就是要防止用户的明文密码泄露。
    lqbk
        311
    lqbk  
       2024-03-21 18:01:33 +08:00
    肯定是加密好。
    第一 密码强度校验在前端就能做,
    第二 做一次 hash 很简单,没什么工作量和资源消耗,
    第三 防止中间人攻击
    第四 服务器接收密码不需要知道明文,本着安全原则,不需要知道信息就不该知道。
    loveDiu4ever
        312
    loveDiu4ever  
       2024-03-21 18:02:19 +08:00
    只能说大多数程序员的水平 配得上他的工资
    liuidetmks
        313
    liuidetmks  
       2024-03-21 18:57:47 +08:00
    @jhdxr
    0.掌握服务器的全部权限,
    1.黑客同时修改前端代码使得明文传输,
    2.修改后端代码各个接口都能兼容,业务正常。这样才能不让发现。
    3.应对站长每次程序更新(防止被发现潜伏,保证站长的业务正常运行,保证黑客代码正常运行)
    4.潜伏足够久,让足够多用户重新登录,这样才能拿到可观数量的密码明文

    这样门槛已经很高了,属于高级持续性威胁「 APT 」范畴了,
    发动这种攻击成本是很大的,一般是需要有巨大商业或者政治上的回报。

    而不获取用户密码明文这一个操作,已经是前向安全的措施了,先前的用户密码明文不会泄露。
    也不会因为你网站泄露导致其他网站牵连受害。

    现实中的黑客攻击,更多的是一次打包取数据库,日志文件等有价值的数据,顺道挖个矿,然后站长发现异常登录,然后修复漏洞,打系统补丁。

    技术上来讲,现在服务一般不是一台电脑,不是一个程序,用户的数据在不同主机上不同程序之间流动,
    你永远不知道其他数据节点的程序会对你的数据做什么操作,有些可能是你的同事,有些可能是云平台(上面说的,网关日志,还有 各种 XaaS ,他们的日志你甚至无法关闭 )

    密码当然是越少人知道越好,最好是只有用户自己
    用户的密码明文永远只存在于用户的内存中。
    ryanlid
        314
    ryanlid  
       2024-03-21 20:07:48 +08:00
    @userKamtao #259 莫名其妙,加密后, “阴暗和邪恶的人” 就动不了手脚了吗
    codehz
        315
    codehz  
       2024-03-21 21:18:34 +08:00
    要讨论这个问题,得先设定一个威胁模型吧,不如就来一个直接拉满的模型:
    攻击者方面
    1. 攻击者完全了解该协议。
    2. 攻击者可以访问大量常用密码字典(并且有足够多的时间离线破解)。
    3. 攻击者可以窃听客户端和服务器之间的所有通信。
    4. 攻击者可以拦截、修改和伪造客户端和服务器之间的任意消息。
    5. 没有相互信任的第三方。
    最后攻击者的目标是冒充客户认证,这里不考虑“在线”暴力破解的情况,也不考虑注册过程中客户被冒充的情形。

    这个模型下,所有基于固定密码的 web 认证方案都是无效的,因为攻击者只需要伪造登录页面就可以直接偷到正确密码。( WebAuthn 是终极解决方案)
    那我们可以弱化其中一个攻击条件,假设 webapp 已经事先作为 pwa 部署到用户设备上了,因此攻击者无法篡改登录页面(*),这种情况下,可以继续讨论前端加密的意义。

    1. 首先排除单纯的摘要算法,因为只要把摘要本身认定为登录密码即可冒充用户
    2. 我们可以考虑单纯的预先共享密钥的方案,也就是对称加密,这条基本上也可以 pass ,因为攻击者也能拿到预共享密钥(什么,你说一次一密?那攻击者伪造一个假的给客户端不就可以了)
    3. 至于非对称加密的方案,尽管这次攻击者拿不到服务端私钥,没办法直接偷到密码,但是由于第二条,攻击者可以离线破解密码
    。。。剩下的方案,基本也就是排列组合,在上面那个威胁模型下能起到的作用顶多是减缓攻击者的破解速度

    那有没有完美的算法解决这个问题呢?答案是有的,只要从一开始,就不发送任何关于密码的信息给服务器即可
    通过零知识证明,客户端和服务端分别向对方证明自己拥有密码,但服务端却无需得到密码的原文(或者任何衍生信息)
    将零知识证明用到认证领域的协议就是(非对称的) PAKE ,一个常见的具体协议是 OPAQUE 协议。协议内容在这里不细说,可以在 https://blog.cloudflare.com/opaque-oblivious-passwords 里看到细节,但在理论上它是能抵御前面所提到的所有威胁的。
    yougotme
        316
    yougotme  
       2024-03-21 21:23:54 +08:00 via iPhone
    按理来说,网站就不应该直接拿到用户的明文密码,顶多是浏览器将密码加盐再 hash 提交,这样就算网站被人爆了也不怕被撞库。虽然 99%用户不关心这个,但我觉得这种“明文”把密码提交上去的做法,我用着会非常不放心,鬼知道你拿我的明文密码是不是也明文保存在服务器上了。
    BaiLinfeng
        317
    BaiLinfeng  
       2024-03-21 21:33:08 +08:00
    肯定前端加密啊,如果被黑客拿到账户和明文密码就可以撞库了,必须可以前端加密
    BaiLinfeng
        318
    BaiLinfeng  
       2024-03-21 21:34:11 +08:00
    肯定前端加密啊,如果被黑客拿到账户和明文密码就可以撞库了,也可以根据你的账户收集你的密码和各种信息,以及社工学等。。。。必须可以前端加密
    mightybruce
        319
    mightybruce  
       2024-03-21 22:14:07 +08:00
    看了这贴,表示原来计算机的民科这么多,v2ex 上不少人水平不如知乎, 如果连基本的密码学都没学过,真的没必要讨论了。


    前端代码都是直接可以看到的"(即算法是公开的), 你再怎么加密, 如果服务器直接存前端加密后的结果和明文传输没有区别, 黑客并不需要知道你的原密码。md5, sha1 本身是 hash 散列函数,其信息熵本身就是下降的。

    首先前端怎么知道这个服务器不是伪造的, 你直接发给伪造的服务器,加密的这一串直接就是白费功夫, 这是第一个要解决的问题就是 Authenticity.

    我也不想太多费工夫,我就参考一下知乎密码学博士的文章再说一下。

    Web 前端密码加密有意义,又没有意义。
    密码学经典人物 Alice, Bob Oscar

    Alice (浏览器前端)和 Bob (服务器后端)到底可以怎么幽会。这个问题又会涉及到以下这些问题:

    Alice 怎么知道 Bob 是 Bob ?
    Bob 怎么知道 Alice 是 Alice?
    Alice 和 Bob 幽会中的窃窃私语如何不被 Eve 偷听到,甚至被 Oscar 串改呢?
    密码学三兄弟 CIA 登场了
    前两个问题被统称归为 Authenticity (认证),第三个问题可以被归为 Confidentiality (保密)和 Integrity

    有兴趣的同学可以去搜搜基础的 Schnorr identification protocol ( Schnorr 鉴别协议)以及 Diffie–Hellman key exchange (迪菲-赫尔曼密钥交换)。后续的工作主要是在安全性和性能上的提升。对于一般人而言,以上三个问题的成熟解决方案实现现有 SSH 和 mTLS 。我相信这两项技术在当今已经普遍应用了。

    有了这些基础设施和密码学协议,我们就能让 Alice 和 Bob 之间建立安全信道,并通讯。在安全信道的基础上,Alice 再对内容加密就毫无意义。或者你仔细想想,你在用 SSH 远程连接到服务器,输入数据库密码的时候你会在的笔记本上加密码?以上内容为 Mutual Authentication (双向认证)。我们一般遇到的是 HTTPS 即 HTTP over TLS (在 TLS 安全信道上 HTTP 通讯)。TLS 建立成功并通过 PKI 认可服务器证书后,对用于用户认证的用户密码进行加密操作并没有意义,如果只考虑通信安全。也就是说你你可以在 HTTPS 下安全使用 Basic Authentication 。

    然而,HTTPS 还是有很多问题。

    使用 TLS 会导致客户端和服务端的性能下降。这些性能瓶颈在 IoT 设备,RFID 设备上较为明显。
    我们无法完全信任服务器。

    对于问题 2 ,我们只保证了通讯的安全,并没有保证服务器端的安全,因为服务器的储存可能被攻陷。我们储存在服务器上的数据,特别是用户认证信息怎么办?用户数据可以加密存储(可以考虑 IND-CCA2 安全的混合加密)。用户认证信息可以使用加盐( Salt )的密码散列函数( Cryptographic Hash Function )。服务器窃取用户认证信息怎么办?可以考虑使用成熟的 OAuth2 方案。服务器不正确的计算我想要的内容怎么办?等等更多,等你成为密码学家来研究吧!

    IND-CCA2 全称是 Indistinguishable chosen ciphertext attack 2 , 这个安全数学模型我就不展开了。
    参考链接: https://www.zhihu.com/question/25539382/answer/547509246
    userKamtao
        320
    userKamtao  
    OP
       2024-03-21 23:26:19 +08:00
    @ryanlid 请问怎么动手脚呢?他能知道我的明文密码吗?这里动不了手脚指的是,无法得到我的原始密码去尝试登陆其他应用或者网站吧?搞清楚上下文。
    param
        321
    param  
       2024-03-22 06:09:41 +08:00 via Android
    https 做的是加密,传输过程中虽然加密,但还是包含原文的。通过某种方式,比如说得到密钥,还是能够逆向解回来的,例如拥有服务器权限的服务器管理人员,他就可以偷偷把用户密码记录下来卖钱。

    有人说:我都有服务器权限了,你就算前端做了 hash ,我也能把前端改成无 hash 的版本来取得明文啊。
    但这样明目张胆地修改前端,大家都能看到,会被发现的,服务器管理人员不敢这么做,他只敢偷偷记录。就算普通用户不知道前端被改过,前端开发者也会发现说:怎么我写的 hash 不生效了???

    前端做 hash 还是有点用的,那么多大的作用呢?从 google 这些大厂都没做就能看出,这个作用并不大。也许一些对安全性要求更高的系统,比如说银行之类的可能会做吧,有些政府项目也是要求前端不能传明文密码。

    不过 google 没做 hash ,也有一种可能是,本来开发者做了 hash ,但是被服务器管理人员改掉了,偷偷记录了密码,而我们以为 google 没做。
    param
        322
    param  
       2024-03-22 06:14:58 +08:00 via Android
    我以前写过的前端 hash 是拿固定字符串+用户名两个因素作为盐,也就是说固定字符串、用户名、密码三个因素连起来做 hash ,包括登录时、用户修改密码时都是如此。
    这种只适合用户名无法修改的场景,就算没有用户名,拿一个固定字符串来作盐也是更加可靠的做法,毕竟这也多不了几行代码。
    这样一来,传输过程中是完全不会包换密码的,密码只会停留于用户的浏览器,出了浏览器谁都不知道密码。
    dcdlove
        323
    dcdlove  
       2024-03-22 08:25:40 +08:00
    @dhb233 在整个系统层面,完全不需要解出来,就算后端接出来也是一个不可逆不可撞库的随机字符串毫无意义,因为在网页提交后端之前就已经被处理了,真正的密码只有用户才知道,系统层面只需要存储整个脱敏后的随机字符串用于匹配用户输入密码是否正确
    param
        324
    param  
       2024-03-22 09:19:29 +08:00 via Android
    @param 修正一下自己。用户名作为盐的一部分,也不是不
    param
        325
    param  
       2024-03-22 09:20:36 +08:00 via Android
    @param 修正一下自己。用户名作为盐的一部分,也不是不能修改用户名。只是每次修改用户名时,要求再输入一次密码。
    kanel
        326
    kanel  
       2024-03-22 09:36:50 +08:00
    我觉得前端加密可以减低后端泄漏的风险,但如果后端是一个 api 接口,有不同的调用方,就没办法检验调用方传送的数据(例如密码)符不符合强度要求了。

    我想到的是在所有接收密码前,进行加密/hash ,只保留修改密码的时候进行明文进输,用作校验。 这样的做法是否恰当,或者有没有更好的方法?
    wentx
        327
    wentx  
       2024-03-22 09:49:43 +08:00
    @dcdlove #307 你说的这些我都知道,看我回复的上下文 。 单纯对比字符串,md5 或者 明文到后端没有任何区别。

    再说你提到的非对称加密:公钥怎么取放在哪儿?算法写在 JS 里面?
    realJamespond
        328
    realJamespond  
       2024-03-22 10:13:34 +08:00
    @wentx 公钥放 u 盘,每次登录提示用户通过表单打开公钥?
    jhdxr
        329
    jhdxr  
       2024-03-22 10:45:49 +08:00
    @liuidetmks #313 你想的太麻烦了,实际上你只需要改一下前端代码,在不改变现有逻辑的情况下,额外增加一条请求发送明文密码即可。

    既然这么多人都提日志的问题,我也来提个异议。登录请求应该是 POST 请求(这个应该没有异议吧)。难道你们的日志都会记录 request body 吗?业务数据里就没有敏感数据了?
    alittlehj
        330
    alittlehj  
       2024-03-22 11:06:26 +08:00
    叫你们公司负责信息安全的同事过来,看看吊不吊他
    userKamtao
        331
    userKamtao  
    OP
       2024-03-22 11:14:07 +08:00
    @jhdxr 不记录 body ,无法排查入参是什么,我公司做政务系统的敏感的信息(身份证,电话)都会脱敏,比如 158****4278 。
    ExplodingFKL
        332
    ExplodingFKL  
       2024-03-22 14:27:43 +08:00
    直接明文 ... 有 tls 了也不怕啥,出了问题也是客户设备被装了 ca ,不影响其他用户,最多交换公钥加上签名防止简单的重放和伪造 ,http 下咋加密都没用, 中间人啥都能改
    ExplodingFKL
        333
    ExplodingFKL  
       2024-03-22 14:34:43 +08:00
    DH 和后续的 ECDH 在浏览器上没法实现 ... 毕竟在 b/s 下 b 端密钥交换和协商都是 s 端给的
    blackshow
        334
    blackshow  
       2024-03-22 15:40:29 +08:00
    评论太逗了
    dcdlove
        335
    dcdlove  
       2024-03-22 16:03:19 +08:00
    @wentx #327 例如用户密码如果是生日,明文传输给后端,首先开发人员会知道,如果数据库被黑客攻击泄漏了,将用这个密码去撞库其他平台,如果用户各种账号都是这个密码那用户是不是很悲剧,
    但是如果 前端将生日处理成一个无意义的不可匿的字符串,就能规避开发人员和系统数据库被攻击后造成的安全隐患。这些都是前端职责范围内要做好的,你要说电脑又病毒监听了网页或键盘活动的情况那我就没法给你答案了,至于公钥存储,鉴于最终代码是公开的,目前做法是对公钥内容进行复杂的加密存储,核心算法和引用链进行执行代码的加密,可以核心执行加密算法写入到 png 图片中,就算公钥被拔出来, 也不用担心密码字符串被解出来,因为对称加密前已经做 MD5+sate 不可逆计算,安全要求高的会结合硬件设备比如 u 盘或手机,2FA 在做计算。
    zhangdp
        336
    zhangdp  
       310 天前
    @shakoon 请问你要怎么实现诸如密码必须 8 位到 16 位字符,密码不能包含中文 emoji 等特殊字符,密码必须包含字母、数字、符号等任意两种以上,修改密码时不能跟最近 3 次密码一样等需求
    1  2  3  4  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3137 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 00:13 · PVG 08:13 · LAX 17:13 · JFK 20:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.