1
3dwelcome 2020-12-21 12:28:22 +08:00
就是防止中间人嗅探密码吧,https 传输的证书也不是完全可信的。密码不加密的话,万一本地被注入了第三方根证书,那不就验证通过,直接看到密码了。
|
2
xmumiffy 2020-12-21 12:31:32 +08:00 via Android
没有,有些只是为了编码
|
3
xmumiffy 2020-12-21 12:32:44 +08:00 via Android
不过你说的这些站都是早期从 http 过来的系统,即使现在上了 https 也还在沿用以前的体系,反正不改也不会有问题
|
4
Mitt 2020-12-21 12:37:29 +08:00 1
你可以再对比下国外的主流网站,就会发现只有国内的普遍会二次加密,主要就是历史遗留,http 时代劫持和中间人问题太严重,加上国内的网络环境并不是那么理想
|
5
opengps 2020-12-21 12:42:17 +08:00 2
https 是防止网络中间传输过程中的暴露
客户端加密,是为了防止本机抓包工具等轻松看到密码明文 至于密码在加密之前的运算环节,虽然是公开的,但是难度摆在那,难度每高一层,就能轻松排除掉一层 90%的小白攻击者。 以前我网站有很多疯狂的爬虫,我只把 reffer 限制了一下,就轻松换来了清净。这个经历足够解释基础防御的重要性了。 |
6
westoy 2020-12-21 12:42:52 +08:00
这个其实就只是代表一种态度, 我平台没有你的明文密码
就算 http 时代, 意义也不大, 针对 input[type=password]搞定向劫持拿到加密前的明文和整个表单数据太容易了 |
7
systemcall 2020-12-21 12:45:44 +08:00
@westoy http 时代,ActiveX 的各种操作,上个网会往浏览器甚至系统里加不少东西
|
8
3dwelcome 2020-12-21 12:47:16 +08:00
简单看了一下 JD,有下面这些参数。
d: 03s0029nq3BQS9000001000g102001000h000001000j101001000e000001000g101000000h000001006l101000000b103001000h1040010... c: c5b7bb1712a347d9a84998dc7b42dd24 w: 0 appId: 1604ebb2287 scene: login product: bind-suspend e: WBNPEK7FHYVGCTYUDSB4O5MO5LOZG5MALJQWPH6C6BGZPESVXB2J66SXYEFX26QQ654RBABHHR4CNA23UUERNDXTRM s: 693759515443421745 第一个 D 参数特别的长,我也不知道为什么官方不用 16 进制,非要用一大堆 0 和 1 来表示,也许是这样看起来很酷。 具体参数吗,就是那些 nonce, 把密码散列化,非对称魔改算法。最后再加个 JS 签名验证防止非法篡改。都是百变不离其中。 |
9
xuanbg 2020-12-21 12:50:57 +08:00 4
后端生成一个动态的盐给前端,并且拿密码加盐 hash 作为 key 寸 redis,value 是用户 id 。前端对密码加盐进行 hash 后传输。后端直接在 redis 里面以 hash 为 key 找用户 id 。
|
10
340244120w 2020-12-21 12:51:38 +08:00 via iPhone 2
主要就防中间人攻击,而且多一层防护终究比没防护好。 像银行客户端的乱序键盘,猛一看似乎没啥卵用,其实可以避免别人通过监控,根据你指法位置判断出输入的字符
|
12
acr0ss OP @opengps 本机只是网络环境的一部分,往大了说是 HTTPS 证书不可信。
虽说 Referer 这个单词本身是拼写错误,但也麻烦你拼写正确下! |
14
ysc3839 2020-12-21 15:30:02 +08:00 via Android
GitHub 好像是直接传密码的。
http 本地加密传输也只能防止抓包,防不了中间人攻击。 |
16
ZSeptember 2020-12-21 16:05:30 +08:00
https 一般不用加密
加密应该是为了反爬吧。 刚发现 GIthub 的登录竟然真的是 POST 一个 session,这个很 RESTful 。。 |
17
codehz 2020-12-21 16:11:54 +08:00 1
(但是其实如果说为了防止本地的问题或者中间人的话,人家完全可以直接替换掉你的脚本,或者直接在提交之前拿到你输入的东西。。。所以主要还是证明服务端没有原文存你的密码(
|
18
chinvo 2020-12-21 16:13:45 +08:00
|
19
chinvo 2020-12-21 16:14:57 +08:00 1
@codehz #15 实际上如果他在登陆时使用不可逆的算法, 比如摘要算法, 那才更说明他们存了明文密码, 因为通常注册的时候没有前端加密这一步.
|
20
kop1989 2020-12-21 16:20:34 +08:00
为什么加密:1 、防止中间人直接看到明文密码(增加破译成本)。2 、反爬虫
加密主流规则:没有主流规则,越非主流,越难逆向越好。 |
22
kop1989 2020-12-21 16:27:19 +08:00
@chinvo #21 所以我并没有说能杜绝中间人攻击。而是“不能让中间人直接看到明文密码”。
另外,既然是“加密”而不是“编码”,那么必然 encode 之后的结果是一次性,且是时间相关的。 这些都能增加中间人操作的难度,而不是“杜绝”。 这就跟门锁一样。门锁对于锁匠而言都是玩具,那并不代表所有人就可以门户洞开。 |
23
GIntonic 2020-12-21 16:35:04 +08:00
我认为除了防止中间人得到明文密码,使用散列还可以证明服务器没有存储明文密码,被脱裤的适合减少危害性,毕竟明文泄露比散列泄露危害更大。
我理解的国内的各种加密、签名相当于在 https 里又实现了一遍 https,不知道对不对,希望大佬指正。我也很疑惑这似乎是国内特色,大多国外公司和开发者都没有在 https 内再加密,不知道有没有一个定论,到底是否有必要 https 内的数据再次加密。 |
27
xuanbg 2020-12-21 17:05:54 +08:00
@zwpaper 就是防止中间人攻击而已。密码 hash 保密的原理就是利用服务器 /用户和中间人信息不对称。但由于有彩虹表的存在,所以需要加盐来保证不被破解出 hash 对应的明文。
|
28
xuanbg 2020-12-21 17:09:32 +08:00
@xuanbg 因为这个 hsah 是临时的,存在时间非常短暂,使用后立即失效,不使用也只会存在几秒钟。所以在一定程度上可以有效防范爆破。
|
31
h2xai111 2020-12-21 18:03:09 +08:00
告诉你们一个秘密,ins 可以用来爆破用户密码,啥限制都没做那种
|
32
unixeno 2020-12-21 19:23:10 +08:00 via Android
历史遗留+反爬
|
33
xuanbg 2020-12-21 20:04:39 +08:00
@Veneris 没什么意义,就是登录时没有用户名,除了只有这个 hash,啥都没有。。。但对我来说信息已经足够了,我用这个 hash 能在 redis 里面找到用户 id,就表明暗号对上了,密码验证成功。
|
34
xuanbg 2020-12-21 20:07:07 +08:00
@Veneris 登录本质上就是客户端和服务器对暗号,我只是不直接用用户名 /密码对暗号,而是用一个临时的 hash 对暗号而已。
|
35
qinxi 2020-12-21 20:52:31 +08:00
还有一个防 log 啊,包括 cdn/nginx.
原本 cdn/nginx 运维不该有权限接触密码的.但是日志记录明文.那不就白瞎了 |
37
GIntonic 2020-12-22 09:15:32 +08:00
@xuanbg 请教一下 如果是密码加盐 hash 如何处理相同密码的问题,而且是否每次都要用不同的盐对所有密码做一次 hash ?最近也见到过登录只有一个 hash 的情况
|
38
xuanbg 2020-12-22 09:48:17 +08:00
@GIntonic 是的,盐是随机的。客户端要先用登录账号获取这个随机的盐。然后才能登录时只用传一个除了客户端和服务端,谁都不知道是啥的 hash 。中间人拿到这个 hash 只能一脸懵逼,尝试重放也没效果,因为这个 hash 是一次性的,当你抓到包的时候就已经失效了。
|
39
xuanbg 2020-12-22 09:51:59 +08:00
@GIntonic 啊,没仔细看。不是对所有用户的密码做一次 hash,而是对当前登录账号的密码加盐做一次 hash,然后也不需要保存到数据库,验证完就没用了。
|
42
acr0ss OP @westoy 个人认为还是需要明文密码的。要不然全站多来源登录,都得统一一个加密方式,而且加密之后、效力等同于数据库密码。
|
45
S4m 2020-12-22 12:02:37 +08:00
客户端用的大部分是 RSA,还有一些是 RSA+AES (有点像自己重写了 SSL )
|
46
janus77 2020-12-22 14:17:47 +08:00
我个人觉得加密方式是不会统一和通用的,毕竟这是涉及安全的事,各家的考虑角度都不完全相同
|
47
acr0ss OP |
49
Veneris 2020-12-22 16:39:40 +08:00
@xuanbg 我尝试复述一下逻辑。当用户尝试登录时候,首先通过 用户名 /手机号 等方式调用一个接口,该接口取出用户的密码,生成了随机的一个盐,加起来做 hash 运算,然后在 redis 中存储了{ hash(pwd+salt) : id },然后把 salt 返回到了前端,此时前端将 用户输入的密码 +返回的盐 做一次同样的 hash 运算,然后再调用登录接口,如果此时根据前端计算的值,在 redis 中拿到了用户 id,即为登录成功,同时清除 redis 该键值对,否则,密码错误。您看,是这个逻辑吗?
|
50
fishCulturer 2020-12-22 17:46:55 +08:00
之前和公司老哥讨论过这个问题,当时讨论结果是防止内部人员作恶或者是提高内部人作恶成本
不止这个思路是否正确 |
52
EminemW 2020-12-22 22:10:19 +08:00
我之前发现很多网站是传原文的。现在所有密码都是用密码生成器生成的
|
53
YouLMAO 2020-12-22 23:28:35 +08:00 via Android
加密为啥是服务端生成盐?直接客户端发送 1 版本号 2 盐 3 精盐加密后信息, 服务端对称解码,解出密码,按照数据库的真盐跟数据库精盐加密比对
|
54
YouLMAO 2020-12-22 23:39:57 +08:00 via Android
避免重放很简单,一般是对用户提交信息加上 session cookie,做一次 js 签名, 如果 session 都被偷了,只能加上来源 ip 了
|
55
lap510200 2020-12-23 09:13:50 +08:00
密码对外是加密后的明文 你说的是对客户端请求数据的加密吗 一般是让客户端根据请求数据按约定的加密方式生成签名 服务端验签,或者有的网关服务生成客户端指纹和数据包加密 验证在网关那就可以拦截
|
56
Veneris 2020-12-23 09:29:57 +08:00
@xuanbg 这样的话,我想了想可能会有些许的问题
1.因为每次都是与不同盐值做 hash,所以你们数据库是存了密码的明文吗,不考虑被脱裤或者内部人员作恶吗? 2.两个使用相同密码的人,随机到了同一个盐值,会导致获取到错误的 id,虽然几率小,但是是可能存在的,因为密码与盐值都不具备唯一性; 3.这种方式会有 hash 碰撞的可能,原则上不考虑,但比其他方式风险要高一点点; 感觉有些过度设计了。 |
61
YouLMAO 2020-12-23 14:44:39 +08:00 via Android
@hehe12980 后端的数据库一般 save 加盐后的 hash,从来没有直接 md5 的,因为裸 md5 直接拿常见密码 md5 碰撞即可
|
62
hehe12980 2020-12-23 16:15:44 +08:00
@YouLMAO 注册的时候就是加密过的 也就是在客户端那一层再做一层加密 后面传输就不是明文了 后面服务端还是该怎么做就怎么做
|
63
YouLMAO 2020-12-23 16:31:30 +08:00 via Android
大哥,这是散列那是加密呀,注册不传原文,闻所未闻,可以设计,但是 p9 架构师不批准
|
64
hehe12980 2020-12-23 16:47:59 +08:00
@YouLMAO 注册不传原文的好处 即使密码被中间人嗅探 那也是拿到一个串 如果传原文, 现在大部分用户都是一个密码通用, 一旦被截获, 得 所有平台通用
|
65
xuanbg 2020-12-24 09:31:37 +08:00
@Veneris #56 数据库怎么可能存明文???加盐哈希只不过不希望数据库存的密码 hash 直接在网络上传输罢了,数据库存的密码 hash 被抓到基本等同于密码被抓到。随机到相同盐是不可能的,这个盐你可以用雪花 id 、uuid……。至于哈希碰撞的可能性是存在的,但无限接近于 0 。因为正常情况下,这个加盐后的临时密码 hash 只存在几十个毫秒的时间。这么短的生命周期,都能碰上,那也是没办法的事情。
这么做唯一的目的就是:不希望数据库存的密码 hash 直接在网络上传输。这也算过度设计的话,安全方面的加固,就啥都不用干了,干了就是过度设计。 |
66
xuanbg 2020-12-24 09:40:16 +08:00
@YouLMAO 注册为啥要传原文?传 MD5 不行吗?数据库为啥要存原文?存 md5(id+MD5)不行吗?我就告诉你吧,我的临时 hash 就是 md5(uuid+md5(id+MD5)),然后返回给客户端 uuid 。客户端计算 md5(uuid+md5(id+md5(用户输入密码))),就得到了和服务端一样的 hash 值了。这样就可以避免密码原文、密码的 MD5 值,还有数据库存的密码值暴露在网络上面。
|
67
LostPrayers 2020-12-24 11:19:14 +08:00
@YouLMAO Bcrypt 加密了解一下,各种语言都有实现方案,比如 Spring Security 之类的都会内置它
|
68
YouLMAO 2020-12-24 11:32:29 +08:00 via Android
@LostPrayers 为了达到不传原文,这样真的过度设计了,你点一下登录,居然要先根据 username 问后端拿盐,然后前端 hash 再回传。fb 三十亿月活看到这直摇头
|