原文:
https://mayank-01.medium.com/an-interesting-account-takeover-3a33f42d609d
有删减
这个漏洞出现在密码重置处。它包含了不安全对象引用,一点点密码学,还有一些目录爆破。
我们姑且称目标为A.com。我们先看一下正常的密码重置功能。
1. 用户再“A.COM/php/login_or_password_forgotten”然后输入他们的个人资料和用户名。
2. 个人资料和用户名验证通过后,会生成一个state的参数。
STATE=eJxdkN1OwzAMhd8lDzA1XffT9GpMDE2gdmKTuIxM4paILilJJhBo747DfjRxlfhzYp9zGpHPBduaryiXzqN8wdeVhz1%2BOv8utxEiMsHFTxATwcJfWYEoEpgKppxtTZfIOJGSSG%2FQRmkGVgXBC8H4ZDYq8hHnfMSnZaL0r3cKekwFTUUrH%2B7SnXT0YLsDdP9aRxo1E6y96hrAR4ueVY3Iy1v1i81abk7Ny8loIWkjKQcLe1bVNDrPBHuDIHuEYGwnyUf0oCKrXkWWhFPfo3KdNd%2Bob6k0FiOt34cLJTvy4wD9FZANCVp7DCFtO4vfPS%2Fq7WK5Wze13DWP93WyOM4FgxJn7VgrBS2fTzVqzDLFVY4cs2Le6vSuTMmESL5P0RT8bHrjXWt68j0M8sl1xjZ%2BAyFQSHrlfOdidJbyO%2F4CvKKcYg%3D%3D55840ad4a2f32819aa5da2cf48288290
3. 然后重置密码的链接会发到注册的邮箱里。
https://example.com/php/login_or_password_forgotten?k=789c0dc8610a80200c06d0bbec049bc9d26f870921834192a4ffa2bbd7fbf90a029e810c9adeea98a5753287a844e16555b1016150bfafc3cfbaf94eff2450e494a2e640f67ebc89137aade927d25a020ab2535ab4b5c9dc4fd1
4. 现在用户可以重置他的密码了。
有趣的事情来了:
K参数的值有点奇怪,所以我就拷贝到CyberChef 看他是不是加密的字符串。令我惊讶的是,他确实是加密+压缩的字符串。

首先是Zlib压缩然后十六进制编码。然后token就变成这个样子。
“789c0dc8610a80200c06d0bbec049bc9d26f870921834192a4ffa2bbd7fbf90a029e810c9adeea98a5753287a844e16555b1016150bfafc3cfbaf94eff2450e494a2e640f67ebc89137aade927d25a020ab2535ab4b5c9dc4fd1"
解码之后
“a:2:{s:9:”timestamp”;i:1614104013;s:10:”profile_id”;s:8:”40884692";}”
解密后的字符串由两个重要变量“ profile_id”和“ timestamp”组成。我立即为第二个帐户伪造了令牌,使用该令牌更改了密码。
伪造的token
789c0dc8510a85201005d0bdcc0ac6f25da6eb62427806034992fe457bb7df93b9f0e9dc28c36be923d726c919107ec0aa40ea0c4a69f775f85976ffcb2746891a610693f44ebe171387
但是根本没有起作用。

曲折
如果你足够细心,你可以看到这两个token长度是不一样的。

原始的链接和我伪造的差了32个字符,填充垃圾字符,服务器也不接受。但是这两个字符解出来都是
“a:2:{s:9:”timestamp”;i:1614104013;s:10:”profile_id”;s:8:”40884692";}”.
这就让我很沮丧了,然后我就去搜Zlib压缩的相关知识。大概画了2个小时,我发现zlib有一个Adler-32_Checksum函数,如果使用这个方法数据就会包含ADLER32校验值BC89137A。在原始链接里可以找到。在Zlib里,校验值之后的值都会被丢弃,这也是为什么长度不一样,但是解出来的数据都是一样的。
所以现在的任务就是找到这个32位的字符串。由于所有与令牌相关的工作都在客户端进行,因此我非常确定会在JS文件中找到某些内容。
在查看JS文件几个小时后,我找到了一个端点“ / php / user”。我决定爆破该目录,最后找找到了接口“
https://example.com / php / user / example /”,该接口有一个名为“ Transction_Token”的字符串,这确实是我要寻找的最后一块。

放在一起:
现在是时候将所有内容组合在一起并加以利用了。
每次刷新页面时,“ Transaction _Token”都会发生变化,因此这种攻击需要精确。因此,我制作了一个python脚本来自动化整个过程。
我为第二个帐户生成了令牌,并用它来更改密码和成功了!!!

译者按:
编码不是加密!编码不是加密!编码不是加密!重要的事情说三遍。再次重申编码不是加密!如果服务器使用AES加密,密钥放在服务端,啥事就都没了。
本文迁移自知识星球“火线Zone”