逆天!干了 3 年的同事用 base64 编码做 token 并且把密码也放了进去

76 天前
 xhatt510

最近做项目,他搞了用户登陆和状态保持。

当时存的时候他跑过来问我密码要不要用 base64 加密存。
我说这和明文没啥区别把,区别就是比明文多浪费1/3空间。不如直接加盐然后存 md5 。

当我看到 token 的时候,我人直接傻了。

这就是 token YWRtaW58cGFzczEyMzQ1NnwxNzEzNzcxNzg4

我相信只要干过开发的人一眼就能认出来这是什么东西。 我本来以为这已经够逆天了。解码出来的内容才真的让人窒息。

admin|pass123456|1713771788

数据库的 user 表里面的用户名和密码也都是base64 编码存储的。

我本以为这种最基本的常识问题,只可能在一个实习生身上发生,但是这个同事至少在这里干了 3 年了

在他的知识库里 base64 编码=加密

然后只有这种格式的才叫json。(用一对花括号包裹{}

{
    "test": 1
}

这种不叫json,更别说其他的值类型的被叫json

[
    "abc",
    "def"
]
22171 次点击
所在节点    程序员
205 条回复
ljyst
76 天前
token 不都是随机后端生成保存在 session 里然后发给用户 cookies 的么?难道是我 out 了?
crc8
76 天前
3 年在人类的历史长河中微不足道~
lasuar
76 天前
它的无知并不能凸显你的才能,因为你俩是同事。所以,尽可能做好分内的事,这个可以提醒一下他。
ebushicao
76 天前
从你的描述来讲这应该是他完全负责的,那按他的来就好,反正出了事你不用负责。为了这个和他发生不必要的冲突没意义,反而可能带来一些更麻烦的后果(同事之间因为一点小事下毒的也不是没有)。
levelworm
76 天前
这种事情楼主可以专门开个讲座,不然这种事情还会发生。
DefoliationM
76 天前
见过更逆天的,习惯就好,这种我一般也不会动,最后出问题了谁写的谁背锅就是了。
xhatt510
76 天前
@q727729853 可能是看得多了。一看就觉得长得像
xhatt510
76 天前
@lasuar 大哥说的对。并不能凸显我多会。提醒了的,别人一意孤行,特别犟。
lidongyooo
76 天前
根据以下规则可得楼主也是个菜鸡,肉眼能分辨上面的字符是 base64 ?除非你没见过其他编码或加密方式。

要根据字符特征识别一个字符串是否为 Base64 编码,可以遵循以下步骤和规则:

1 、字符集检查:Base64 编码只使用特定的字符集,包括大写字母( A-Z )、小写字母( a-z )、数字( 0-9 )和两个特殊符号(+、/)。在 URL 安全的 Base64 变种中,可能会用-和_分别替换+和/。首先确保输入字符串仅由这些字符组成,不包含其他任何非法字符。

2 、长度检查:Base64 编码将每 3 个字节( 24 位)的数据转换为 4 个 Base64 字符(每个字符对应 6 位)。因此,一个有效的 Base64 字符串的长度应该是 4 的整数倍,除非它在末尾包含填充字符=。
当原始数据长度不是 3 的整数倍时,在编码的末尾会添加 1 个或 2 个=作为填充。这意味着如果字符串长度不是 4 的倍数,但减去末尾的=后变为 4 的倍数,则可以认为该字符串可能是 Base64 编码的。如果字符串长度既不是 4 的倍数,也没有以合法数量的=结束,则几乎可以确定它不是 Base64 编码。

3 、填充字符检查:填充字符=仅出现在 Base64 字符串的末尾,用来标识编码过程中因原始数据长度不足而补充的零位。最多可能出现 2 个连续的=。
如果字符串末尾有=,检查其数量。如果数量为 1 或 2 ,并且去掉这些=后,剩余部分的长度是 4 的整数倍,那么这是 Base64 编码的一个特征。否则,如果出现非法数量的=或者=出现在非末尾位置,可以断定这不是 Base64 编码。

4 、正则表达式匹配: 使用正则表达式来快速验证字符串是否符合 Base64 编码的字符集和结构要求。例如,一个基本的正则表达式可以是 ^[A-Za-z0-9+/]+={0,2}$ 或者针对 URL 安全 Base64 的 ^[A-Za-z0-9-_]+={0,2}$。如果字符串能被此正则表达式成功匹配,说明它具有 Base64 编码的字符特征。
younggod
76 天前
不像人
totoro52
76 天前
@superedlimited #65 估计以前是搞 php 的 我见过太多 php 程序这么干的了,用|分割用户账号密码加一个时间戳当 token ,然后也用 base64 但是是自己变了一点算法的 base64
oamu
76 天前
@xhatt510 #27 经典菜鸡言论:我不会 = 不支持/不行。
oamu
76 天前
@lidongyooo #109 符合这些规则的就一定是 Base64 编码?并不一定,只能说它能通过 Base64 的解析方式解析。
Citrus
76 天前
叹为观止的是居然有很多人认为这样做是对的。真可怕。
456vv
76 天前
@crab 能黑库的,就不是这个用户密码了。
qbqbqbqb
76 天前
@ljyst 你说的这种叫做 session id ,需要后端保存状态(也就是你说的“保存在 session 里”)。

token 一般指的是支持无状态校验身份的,原理上是把用户身份和过期时间加密之后发给客户端,这样后端无需维持 session ,只要解密 token 就可以验证用户身份,在分布式的场景下很有用。可以了解一下 jwt 。
GeruzoniAnsasu
76 天前
@lidongyooo 辛苦你复制 GPT ,但有种东西叫 cyberchef:

- https://gchq.github.io/CyberChef/ 打开它
- 复制任意 base-wtf-like 字符串
- 点下面的魔棒

> 4 、正则表达式匹配: 使用正则表达式来快速验证字符串是否符合 Base64 编码的字符集和结构要求。例如,一个基本的正

起码比肉眼正则靠谱
jinliming2
76 天前
@456vv #47 还真不一样。从攻击面的角度来说,密码在网上传输的次数越多,承担的风险越大。
登录这个过程,用户名和密码必须要通过网络传输,这没办法。但登录后获取 token 的意义就在于,避免后续再传密码了,用 token 来充当用户名+密码。
但如果 token 是固定不变的,那也没意义了,和 basic auth 一样,并不安全,所以 token 必须要经常变。
token 当然不用是一次性的,但是必须要有时效性,定期续期,并且时效性越短越安全。比如银行网站就可能会要求 5 分钟不操作自动退出。
用 token 来代替密码就是为了频繁更新,避免同一套字符串一直在网上传。

所以,比较推荐的做法是,密码登录,换取两个 token ,一个是有较短时效的 session token ,一个是有较长时效但是一次性的 refresh token ,然后用 session token 通信,session token 过期后,再用 refresh token 获取两个新的 token 。
这样,密码因为更新频率很低,并且长度通常相对较短,所以只在网上传输一次。refresh token 因为可以充当密码来获取新的 token ,所以只在网上传输两次(往返各一次)。session token 权限最低,只能在有限时间内使用,且不能充当密码来获取新 token ,泄漏后的影响也是有时效性的,用来进行低频敏感操作可能还会要求用密码来做二次认证。
如果存在攻击者,那么他必须精准地获取登录包或者是 refresh token 的数据包,才可以拥有较高的权限,但这样的数据在网上传输的频率非常低。那么这个攻击者就必须长期攻击监控这个用户,那被用户发现的概率就提高了,而且大概率还只能拿到 refresh token 跟用户抢续期权,用户更容易发现账号被盗。
way2explore2
76 天前
是,技术不合格。

其实也不奇怪,林子大了
ljyst
76 天前
@qbqbqbqb 我好歹也有 7 。8 年后端功底你说的这些谁不懂。你意思是每次发送请求加个非对称加密 token 进去就不用 cookie 了是吗。另外还有一种就是每次变 token 防止模拟 http 请求。就算没有 cookie 在 header 里发送 token 后端也要验证请求信息啊!楼主的意思是他同事留后门。懂?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1034660

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX