V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Torpedo
V2EX  ›  程序员

HTTPS 用明文传输密码的问题的引申——前端能不能做到比较完美的加密

  •  
  •   Torpedo · 23 天前 · 2936 次点击

    最近密码用不用明文传到后端的问题很火。前端不加密的很重要一个点是加密太容易暴露。因为 js 可以被用户比较轻易的看到,造成加密算法的泄露。

    不过开发过程中,还是有些加密需求的。比如防爬虫之类的。像客户端一般都是携带参数算出的 token 。而前端因为上述原因,很少采用类似的方案

    其实客户端也不是没法破解,只不过成本比较高。web 上我见过的接口,谷歌地图的接口也是加密过的。

    大家实践里有什么破译成本比较高的方案呢?

    50 条回复    2024-05-25 18:50:37 +08:00
    CloudMx
        1
    CloudMx  
       23 天前   ❤️ 2
    不管怎样,密码这种信息都不建议使用加密方法,而是使用 HASH 摘要算法进行处理后进行传输、存储。
    它不需要“解密”还原成密码明文。
    dzdh
        2
    dzdh  
       23 天前
    wasm
    cmdOptionKana
        3
    cmdOptionKana  
       23 天前   ❤️ 3
    安全、防爬,这是个无底洞,基本上就是八仙过海各显神通,攻防两端互相斗法,这是一场无休止的战争,没有一劳永逸的方法。
    adnoh
        4
    adnoh  
       23 天前 via Android   ❤️ 1
    要看防谁,客户端还是传输层
    wy315700
        5
    wy315700  
       23 天前
    任何加密系统都绕不开信任预置的问题。双方有一个共同信任的东西。。

    SSL 里的话这个东西就是根证书。



    ----因为 js 可以被用户比较轻易的看到,造成加密算法的泄露。----

    一个成熟的加密系统不应该依赖算法的保密,而是通过密钥管理来达到安全性的目的。



    如果是为了防止中间人抓包的话,Static SSL Pinning 就行了
    povsister
        6
    povsister  
       23 天前
    #3 概括的很清楚了,没有一劳永逸的方式。
    尤其是 Web 这种你前端代码都跑在用户端的情况下,更不可能有无懈可击的方案。

    更多时候是看你需要加强什么防护,从而针对性的采取一些措施:代码混淆,验签,wbi ,SSL pinning 都是侧重不同方面
    skyqiao
        7
    skyqiao  
       23 天前
    密码不需要解密吧
    busier
        8
    busier  
       23 天前 via iPhone
    前端加密要安全也不是不可能,既然前端算法和密钥都藏不住,那么在前端实现与 SSL 一样的 RSA 非对称加密即可。

    至于在前端 HASH 后在传输,恕我直言就是脱了裤子放屁。
    busier
        9
    busier  
       23 天前 via iPhone
    补充,当然可以考虑在前端代码中实现 PGP ,这样要容易些。
    CloudMx
        10
    CloudMx  
       23 天前
    使用 RSA 也需要防止中间人,这些都是相辅相成的安全策略,应对不同的攻击方式。
    我不同意 HASH 后传输是脱裤子放屁,因为密码这种敏感信息数据库是没必要存储明文信息或者加密后的信息的,只需要 HASH 后,存储,不管你从什么业务考虑。HASH 摘要算法你到后面的攻击方式想要对应的明文,无非就是去查字典或者自己生成字典跑。
    flyqie
        11
    flyqie  
       23 天前 via Android   ❤️ 1
    @CloudMx #10

    现在很少有厂商存明文了吧。

    hash 后传输算是为了防止在整个链路中看到原始密码。

    安全性上确实也是有些用的,起码看不到明文了,不算脱裤子放屁但很多时候意义不是特别大。
    BeautifulSoap
        13
    BeautifulSoap  
       23 天前
    @CloudMx 4202 年了,哪个厂商后端还会直接把拿到的原始密码直接入库,学后端开发自己手撸用户模块的话所有教程第一节课都会教你服务端要把密码 hash 后存储。用的如果是正经的现代框架的话,我反正没见过现在什么主流框架的用户模块会直接往 db 里存未处理的密码原文的(如果真有的话建议说出来让大家开开眼,估计这框架将会成为开源界的耻辱了)
    pkoukk
        14
    pkoukk  
       23 天前   ❤️ 2
    3 楼说的没错,看你要防谁。
    你是要防泄露,还是防滥用,还是防第三方客户端
    按你要防的具体的东西,再去选择适合的方案,虚头巴脑的讨论浪费口水
    CloudMx
        15
    CloudMx  
       23 天前
    @flyqie 就是密码这种东西,根本不需要传输明文到后端,不管你业务怎么使用,比如:验证密码,历史密码记录等。不可直接"逆向"成对应明文它最大的意义就是这。
    CloudMx
        16
    CloudMx  
       23 天前
    @BeautifulSoap 有啊,我想说的不是明文,而是任何加密形式的密码保存都不应该存在,密码对应的只能存储对应 HASH 。你非对称也好、对称也好,都可以解密。HASH 这种,稍微加点盐,你就只能自己跑字典。
    CloudMx
        17
    CloudMx  
       23 天前
    任何密码信息,都不应该存储明文、加密存储,而是 HASH 摘要存储。除非你说你要在后端验证密码复杂度。
    BeautifulSoap
        18
    BeautifulSoap  
       23 天前   ❤️ 7
    @CloudMx 对于后端来说,前端无论传的是密码原文还是 hash 后的值,在后端看来那都是“明文密码”,这点你能反应过来吗?比如用户密码 123456 ,sha256 一下就是 effff....16c 。那么对后端来说,effff......16c 就是明文密码。我是个攻击者,知道了你这串 effff....16c 直接用这个值请求登录 api 就登录进去了。前端你 hash 不 hash ,结果和明文密码并没任何不同


    然后这里还有个问题,你有没有考虑过加盐 hash 到底应该在哪一步才好?
    方法 1. 前端传密码原文,后端加盐 hash 入库
    方法 2. 前端加盐 hash ,然后直接将结果入库

    这里,比起方法 1 ,方法 2 是存在极其严重的安全漏洞的。加盐 hash 保证安全的前提是“盐是保密”这一点,前端加盐=盐被公开,当你盐被公开而后端又直接入库的话等同于用了方法 1 但后端的盐泄露了的情况。
    所以前端加盐 hash 为了保证安全,那么你后端必须要再用另外的盐再 hash 一次:
    方法 3. 前端加盐 hash ,后端再用另外一个盐 hash 入库
    这时候方法 3 本质上和方法 1 并没任何不同(因为对后端来说无论你前端传什么过来对后端来说都是密码原文),只不过从一次 hash 变成了两次 hash 。那么这就又有个问题了,你都搞了两次 hash 了,为什么不为了安全后端多来几次,3 次,4 次,10 次,100 次?所以仅从数据入库角度来看,前端 hash 不能说脱裤子放屁,那也是没用处的
    CloudMx
        19
    CloudMx  
       23 天前
    你说 HASH 化后的密码可以登录,这个是毋容置疑的,后端接收后就是验证这一串值的,你后端看见的就是你说的“明文密码”,它只要去跟数据库里面的去对比就行,不管你是什么。

    但是我这里表达的是,我前端 HASH 后,你后端接收是不可能反推出我的明文的,但是如果你用加密方式,你是有机会的,谁知道你会不解密我的密文干些啥。

    你说的在哪一步好,我的建议是方法 2 或者方法 3 ,理由就是上面说的,我不想也不愿意你存储我的明文。

    方法 1 跟方法 3 有区别,方法 3 后端永远不可能知道我的明文。

    方法 2 跟方法 3 是没有什么区别的,硬要说就是双 SALT ,一个前端 SALT ,一个后端 SALT+前端 SQLT 。对于攻击者来说,要么中间人的时候获取到出来后的 HASH ,直接跑字典,要么获取到数据库查询权限后,获取到对应的 HASH 值以及后端的盐,前端的盐默认就是公开的(这里不考虑中间人直接插 JS)。
    CloudMx
        20
    CloudMx  
       23 天前
    CloudMx
        21
    CloudMx  
       23 天前
    @BeautifulSoap 而且你这主要是考虑登录问题,我这边的角度是不想后端知道我的明文密码。
    还有你说的 100 次,其实有啊,pbkdf2Hmac 这种。攻击者要想跑字典得花更多的时间。
    BeautifulSoap
        22
    BeautifulSoap  
       23 天前   ❤️ 3
    @CloudMx 等等,你怎么偷偷改了话题? 话题怎么从防止密码原文入库变成了「这个网站它如果是是恶意的,它就是要想办法搞到我的密码原文去作恶该怎么办」了? 前者是纯技术话题,而你 19L 的这个话题则并不是技术话题,而是变成了网站内部有恶意第三者搞破坏我该怎么办了。

    假设一个网站隐含有主观恶意,它就是要搞到你的密码明文作恶,那么为什么你会觉得这个网站的前端就是安全的?哪怕这个网站的前端登录时把你的 password hash 一下,给了你一种虚假的安全感,它也有一万种方法再变相把你的密码原文发送给服务器。甚至后端想作恶了它都不用动你前端,直接拿你令牌就是了。对于一个有恶意的网站期望密码 hash 就能保护自己的密码原文本来就有点奇怪。这种时候你还不如一个网站一个随机密码实在。这相当你“人肉做了 hash”
    CloudMx
        23
    CloudMx  
       23 天前
    @BeautifulSoap 没有,我就是一直在说的是“我不同意 HASH 后传输是脱裤子放屁”。

    如果要说 HASH 跟不 HASH ,对于后端登录来说,它本来就是没有什么两样,它只是去验证是否一致。其他人获取了如果没有添加 nonce 的,重放肯定是可以正常登录的。

    你如果都说有主观恶意了,它其实什么都是不安全的了,你总得在前端输入你的明文密码,就像你说的,这里你如果不关注就算 websocket 发送出去你也不知道。

    我的论点就是,在其它都不关注的情况下,HASH 后的密码值传输到后端,比加密到后端更合适,所以我说“我不同意 HASH 后传输是脱裤子放屁”。

    HASH 传到后端的目标就是一个,从浏览器传输出去后,就没人能够拿到明文信息。
    connectError
        24
    connectError  
       23 天前
    @BeautifulSoap #22 逻辑清晰啊老哥,我就发现有的人讨论讨论着就,整个话题熵增后,都偏离了主旨了。
    ebushicao
        25
    ebushicao  
       23 天前   ❤️ 1
    前端加密有意义,但 Hash 传输没意义。前端加密可以增加破解难度,肯定是更安全一些的,最起码也需要花时间搞清楚前端的加密算法。而 Hash 毫无意义,首先,肯定是不可能直接把前端 Hash 的入库的,这比明文还要危险。那前端 Hash 就相当于把 Hash 值作为密码,本质上和明文密码是一样的,反而还多一个 Hash 处理浪费算力。加密举个简单例子就是比如以时间维度来将密码加密,在不同时间维度内加密出的结果是不同的,后端根据对应算法解密出实际密码。这样就算多了一层保护,安全性或多或少提升了一些。当然,因为前端的代码都在浏览器,即便有压缩和混淆,搞清楚具体算法也只是时间问题。
    jhdxr
        26
    jhdxr  
       23 天前
    tl;dr 用 https 足矣,非要改进建议放弃密码直接 passless

    密码明文入库、日志里明文暴露等在我看来都是借口,CSDN 密码泄露都过去 13 年了,如果还犯这种低级错误,你和你的领导至少有一个人不适合在这个行业干。

    那仅仅考虑传输安全呢?
    先说加密,对称加密不安全,毕竟不管是 js 里写死(那攻击者直接能看到)还是从服务器端获取/协商(那这个请求的传输安全如何保证)都不行。非对称加密理论上是可以的,但如果你完整地实现一遍,你可能会发现——你重新写了一遍 https 。那凭啥你自己写的 https 就比自带的安全了?

    再说哈希。首先我必须打醒某些觉得哈希了再传更安全的人。对于后端来说,你传的是明文密码还是哈希后的密码,都只是一个字符串,对攻击者来说也是如此。抓到请求我拿抓到的值去用就行(重放攻击),密码明文还是哈希,有区别吗?至于那些我被黑了没事,用户密码坚决不能泄露的,你可听说过彩虹表?就算加盐了,弱密码字典+盐跑一遍现在也没啥成本。那就变成要用户变态密码或者一站一密了,不如直接 passless
    BeautifulSoap
        27
    BeautifulSoap  
       23 天前
    @CloudMx 一个网站的前端后端不是割裂的,不知道为什么你会如此不自觉地将前端和后端如此割裂地来看待,一个网站往往是同一个公司的人写的,有的网站前端后端写代码的甚至是同一个批人或同一个人。可能你用的网站的前端就坐后端边上,两人还天天中午出去吃饭聊天打哈哈。我说这么多只是想提醒一下,一个网站的前后端往往联系是非常紧密的。对于一个整体的网站,当出现内部恶意第三者的时候,你要考虑的就不光只是密码这种微不足道的东西了。

    再次整理一下,你完全不信任一个网站后端觉得网站后端就是有恶意的可能想搞到你密码,但同时你又很奇怪地完全信任这个网站的前端,认为这个不安全的网站的前端是完全的好人把你的密码 hash 一下之后你的密码就安全了。所以你认为前端 hash 一下等同于从后端那保护了你原始的密码原文,对不

    但我的看法是,是的 hash 一下你说完全没用那是假的,但我上面也说了很多了,前端 hash 这件事本身就没多少用处
    CloudMx
        28
    CloudMx  
       23 天前
    @BeautifulSoap 前端后端同一个写的,在我遇到的情况现在很少,很多不是全栈,他们都是对自己方便用什么方式。

    你如果想说的是安全是一个整体,我肯定是赞同的。

    为什么说到前端信任这个问题,因为你说前端也是不安全的那真就没有解法了,你总得输入明文密码,也就不需要说 HASH 再传输到后端了,你无论咋处理,明文就是可以前端拿得到。

    我也同意你说的没有多少用处,上面我就说过了,它的用处就是出了浏览器传输开始到后端,没人能知道明文信息了。
    idealhs
        29
    idealhs  
       23 天前
    笑看一堆觉得需要处理的,看来大家普遍水平还是不够高,这行还能再多混几年
    cslive
        30
    cslive  
       23 天前
    前端加密脱裤子放屁
    tanranran
        31
    tanranran  
       23 天前
    参考银行 密码登录加密
    imnpc
        32
    imnpc  
       23 天前
    https 的意义是不是很多人都不愿意去了解?那么多大牛花了这么长时间建立的安全保障 居然都无视了?
    luxor
        33
    luxor  
       23 天前
    如果不考虑中间人,https 足够了。如果存在中间人劫持,那么前端的代码可以任意修改,在加密前获取数据即可,因此#30 说得没错。
    rimutuyuan
        34
    rimutuyuan  
       23 天前
    前端 hash 只有一个意义,防止被中间人攻击者拿着密码明文登录其他网站,对于自己网站安全性没有任何提高
    rimutuyuan
        35
    rimutuyuan  
       23 天前
    但通过劫持 js ,仍有方式获得密码原文,总结,脱裤子放屁
    ZE3kr
        37
    ZE3kr  
       23 天前 via iPhone
    比较完美的加密当然有啊,比如 TOTP 就是其中一种。更完美的前端加密还有 Passkey 。这些都是客户端参与计算,生成加密后的信息而非密码本身,并且有大量应用,非常成熟的技术。

    其他的简单的前端加密都是不完善的,比如简单的 hash 不能解决重放

    ( note:我说的加密是广义的,包含 Cryptographic hash function ,所以 hash 也是加密的一种)
    razertory
        38
    razertory  
       23 天前
    只要让每一个请求,都让用户手动做一个 2FA 验证就行了
    terence4444
        39
    terence4444  
       23 天前 via iPhone   ❤️ 1
    前端 hash 用户密码是对用户负责的表现,并不是说因为用了 HTTPS 就可以明文传输用户密码了。

    认为这样做“脱裤子放屁”的,在安全编程方面还是有所欠缺。
    lisongeee
        40
    lisongeee  
       23 天前
    如果前端 hash 密码,那后端怎么校验密码是否匹配大小写字母特殊字符 8-16 位?

    如果前端 hash 密码,那一但上线,岂不是这个 hash 规则到死都无法改变,因为一旦后期前端变更 hash 算法,之前的用户密码 hash 不对应则无法登录
    lisongeee
        41
    lisongeee  
       23 天前
    思考了一下,hash 算法确实是一开始定死的,请忽略我上一条评论的下半部分
    ShuWei
        42
    ShuWei  
       23 天前
    你连加密、哈希、混淆都没有搞清楚
    zlowly
        43
    zlowly  
       23 天前
    前面说 Hash 传输没意义,这只是从单一系统角度视角考虑的结果。
    要知道现在没有系统会保持明文密码,是因为用户密码的泄露,不但对本系统有风险,更是对用户使用的其它系统都照成风险,因为很多人是多个系统登录注册都用同一个密码的。
    同理,将用户密码明文传输,就会出现通信链路中通过中间人攻击可能获取到这个密码,给攻击者有机会利用这个密码试探将用户所有可能使用的系统,扩大了用户损失。
    busier
        44
    busier  
       22 天前 via iPhone
    @CloudMx 防中间人那是传输层的事情,SSL/TLS 做好就可以了。别指着前端搞全家桶什么都考虑进去。

    前端加密无非就是防止客户端调试类工具查看传输了什么
    前端又无法保证密钥和加密算法安全,使用非对称方式再合适不过了。
    chaoschick
        45
    chaoschick  
       22 天前 via Android
    usbkey
    luxor
        46
    luxor  
       22 天前
    @terence4444 @zlowly 为什么很多人认为中间人劫持只能看到明文密码或者密码 hash 的传输呢?密码是怎么输入的?直接劫持网页密码输入不就行了?好好想想 CS 和 BS 的区别吧。中间人是无法修改 CS 的 C 端代码的(漏洞除外),因此只要通讯协议可以对抗中间人(例如浏览器+HTTPS ),就是安全的。而 BS 的 C 端代码中间人是可以篡改的,再怎么加密混淆都阻止不了窃取数据。

    @busier 密码是用户输入的,用户自己还需要用调试工具来查看吗?
    CloudMx
        47
    CloudMx  
       22 天前
    @busier 防止中间人是 HTTPS 的事情,没问题。

    如果在没有中间人攻击的前提下,密码我还是建议 HASH ,理由之前说过。
    其他的敏感信息,你可以 RSA 这种非对称,反正现在的机器配置不低,在传输数据量不那么大的情况下,性能没啥问题。
    terence4444
        48
    terence4444  
       22 天前 via iPhone
    @luxor 你还在纠结中间人,中间人是一个问题但不是主要问题。
    明文密码在系统处理过程中会不知不觉留下痕迹,如果本着对用户负责的思维设计系统的话,就会考虑把用户明文密码在系统里的痕迹减少到最低。
    zlowly
        49
    zlowly  
       22 天前
    @luxor 目前的安全防护都趋向于零信任安全的理念,你不能指望只靠通讯协议可以完全对抗中间人,https 虽然对通信内容进行加密,但建立 https 过程仍然有很多步骤是有可能钻漏洞获进行中间人攻击的。当然安全的程度也要考虑成本,但是如果你前端采用 HASH 传输几乎就是 0 成本的,为何不做?万一你这个项目出现信息安全事故,遇到严厉的领导或甲方,你就算再怎么辩解这个用户密码不是从你前端漏出去的,追责时这个偷懒行为都够你喝一壶的。
    forty
        50
    forty  
       22 天前
    >“前端不加密的很重要一个点是加密太容易暴露”

    非对称加密,就是解决这类问题的,加密算法是公开的,不怕你看。具体到网站前端来说,就是后端给前端公钥,前端加密,发给后端,后端解密。也就是 HTTPS 。当然,你的目的是,防止被人从调试器查看你的加密,那就自己再来一层非对称加密,用 JS 代码来调用。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1255 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 17:41 · PVG 01:41 · LAX 10:41 · JFK 13:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.