从业者-加密预言机-通过预言机绕过身份验证
# 实验室:通过加密预言机绕过身份验证
# 题目
此实验室包含一个逻辑缺陷,该缺陷会向用户暴露加密预言机。要解决实验室问题,请利用此缺陷访问管理面板并删除carlos
用户。
你可以使用以下凭据登录到自己的帐户:wiener
:peter
- name: 实验室-从业者
desc: 通过加密预言机绕过身份验证 >>
avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
link: https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-authentication-bypass-via-encryption-oracle
bgColor: '#001350'
textColor: '#4cc1ff'
2
3
4
5
6
# 实操
根据题意,可得实验目标:
- 该实验室存在逻辑缺陷,暴露了加密预言机。
- 利用该缺陷,绕过身份验证 并 访问账户管理面板,然后删除 carlos 用户。
点击 “ACCESS THE LAB” 进入实验室。

点击 “My account” 转到登录页面。

输入题目中提供的用户名和密码,勾选 “Stay logged in”,登录相应账户。

登录成功。

# Cookie测试
登录过程中产生了两个请求数据包。
第一个数据包,携带用户名和密码进行登录操作,返回了两个 Cookie 并跳转至账户界面。

第二个数据包,携带刚刚获得的 Cookie 访问账号界面。

我们的目标是 用于保持登录状态的 Cookie 。
stay-logged-in=a4b2WXgN9OQMHOTTHtji6ZiEkHIDiubEGgmQu%2bMlT3c%3d
这是一串密文,在进行 URL 编码之后设置在 Cookie 当中。

携带 stay-logged-in Cookie 访问账户页面,访问正常。

在 stay-logged-in Cookie 参数值中添加任意字符,程序返回错误信息。
说明 stay-logged-in 应用了某种加密算法。

# Cookie解密
破解Cookie算法 --> 伪造其他账户的Cookie
目前没有相应的密钥,破解 Cookie 成了一大难题。
但,如果目标站点上存在相反的功能,则会让我们有机可乘(Cookie 被 “登录功能” 加密,找找站点上有没有 “其它功能” 可以解密 Cookie)。
回到首页,点击 “View post” 进入任意商品的详情页。

滚动页面至最下方,有一个评论功能。
由于程序没有对 Email 参数值进行校验,即使输入错误的邮箱也没问题,例如 123456 。
填写相应信息,然后点击 “Post Comment” 提交表单。

提交之后,程序返回错误信息,邮箱格式不正确。

提交评论时,共产生了两个请求数据包。
第一个数据包,提交评论表单时发出,程序返回了一串奇怪的 Cookie ,和登录时产生的stay-logged-in
有点类似。
stay-logged-in 和 notification 使用的有没有可能是 同一种算法、同一个密钥?
notification=r8l%2fq0VO8wVXQZ8dnDr7DsZmb9K40Iq5iL%2bSaqLK6AY%3d

第二个数据包,携带刚刚的 Cookie notification 跳转至原来的商品页面,并提示邮箱错误Invalid email address: 123456
。
notification 与 错误信息 之间有没有什么关联性?

为了验证猜想,将第一个数据包转发至 Repeater 模块,将 email 参数修改为123456000000000000000000000000000000
,然后重新发送数据包。
在响应包中,程序返回了更长的 notification 参数值。
notification=r8l%2fq0VO8wVXQZ8dnDr7DnTMdKUIkNcp4Yx5uYBHQDkIkLsyQ62hue%2b2iTjtGeORIAV9jwnJ1ap%2fDeDH2Iu%2b5w%3d%3d

将新的 notification 参数值替换到第二个数据包当中,然后发送数据包。
在响应包中,程序返回了错误信息,其中包含了新的 email 参数值。
大概率:
- 第一次,对 email 参数进行加密操作,将密文设置为 Cookie 并返回给客户端。
- 第二次,对 Cookie 进行解密操作,获得明文 email 并输出错误信息。

如果将原先的stay-logged-in
添加到notification
当中,会发生什么?
如图,原先的密文被解密了,明文信息为wiener:168804228069
。

前面的信息为用户名wiener
,而后面的信息为时间戳,应该是用户登录的时间。

Cookie 的加密和解密功能都已经找到。
# 伪造Cookie
在站点的 /admin 路径中存在管理界面,只有 administrator 身份才能访问。
通过上一步的操作,Cookie 的加解密方式已被找到,现在尝试伪造 administrator 账户的 Cookie 。

在提交评论的数据包中,将 email 参数值修改为administrator:1688042280697
,然后发送数据包,获取该账户的 Cookie。
r8l%2fq0VO8wVXQZ8dnDr7DiTPAvLB6RQdCHFQnNpBjyqxbhoCY6I34%2fYAvl2gbP%2bWwXrWQ3QTffwwcH8lcas%2fDg%3d%3d

将获得的 Cookie 粘贴到第二个数据包当中,然后发送请求,检验加密是否成功。
加密确实成功了,程序返回错误信息Invalid email address: administrator:1688042280697
。

但现在有个问题,通过对比wiener
账户的明文 Cookie 发现:
# wiener的明文信息
wiener:168804228069
# administrator的明文信息
Invalid email address: administrator:1688042280697
# 脏字符
Invalid email address:
2
3
4
5
6
7
8
我们通过第一个数据包加密 administrator 的账户信息之后,程序在字符的前方添加了 23 个脏字符Invalid email address:
,这影响了 Cookie 的有效性。
管理员的Cookie --> 解密 --> 去除脏字符 --> 重新加密 --> 使用
通过对比每次的密文,发现密文前面有一段相同的字符,这应该就是脏字符了。
# 原脏字符
Invalid email address:
# 密文
r8l%2fq0VO8wVXQZ8dnDr7D
# URL解码后, 脏字节长度为 21 位
r8l/q0VO8wVXQZ8dnDr7D
2
3
4
5
6
7
8

# 去除脏字符
转到 “Decode” 功能模块,填入管理员账户的 Cookie 密文。
1、对第一行数据进行 URL 解码:
- 点击 “Smart decode” 智能解码。

2、对第二行数据进行 Base64 解码:
- 点击 “Decode as --> Base64”

3、删除第三行数据中的脏字符:
- 选中前 21 个字节,然后 “右键 --> Delete selected bytes” 删除选中的字节。

4、对第三行数据重新进行 Base64 编码:
- 点击 “Encode as --> Base64”

5、对第四行数据重新进行 URL 编码:
- 这一步手动进行,更加直观
6RQdCHFQnNpBjyqxbhoCY6I34/YAvl2gbP+WwXrWQ3QTffwwcH8lcas/Dg==
+ 替换为 %2b
/ 替换为 %2f
= 替换为 %3d
6RQdCHFQnNpBjyqxbhoCY6I34%2fYAvl2gbP%2bWwXrWQ3QTffwwcH8lcas%2fDg%3d%3d
2
3
4
5
6
7

将修改过的密文粘贴到 notification 参数当中,然后发送数据包,验证加密是否成功。
程序返回错误信息,密文长度不匹配,必须为 16 的倍数。
原先的密文长度为 64 个字节,删除 21 个脏字节之后变为了 64-21=43 个字节,不符合规则。
- 不删吧,脏字符影响 Cookie 有效性,没用。
- 删吧,长度又不符合规则,还是没用。
那咋办嘛?

# 删除脏字符,并保持密文长度为16的倍数
既然原先的脏字符长度为 23 个字符,那我们再添加 9 个脏字符,形成 23+9=32 个脏字符。
在去除脏字符的时候,将这 32 个字符一并删除,形成 64-32=32 个字符的密文,从而符合长度要求。
这是加密前的脏字符,长度 23 位。

在用户名前面添加 9 个任意字符:
# 例如九个0
000000000administrator:1688042280697
2
现在,包括刚刚添加的 0 ,脏字符长度为 32 位。

使用第一个请求包,加密账户信息,获得密文。
r8l%2fq0VO8wVXQZ8dnDr7DsFw0NZTV%2fatpTur6r%2fdltxz5CJQjNX19GepyWLepXmw3vukV%2bflc6SNQH23q5k6Tw%3d%3d

重复刚刚的步骤:URL解码 --> Base64解码 --> 去除脏字节 --> Base64编码 --> URL编码。
这次选择 32 个字节,然后右键删除。

通过对第三行数据的 Base64 编码,获得密文字符串。

手动 URL 编码,比较直观。
c+QiUIzV9fRnqcli3qV5sN77pFfn5XOkjUB9t6uZOk8=
+ 替换为 %2b
/ 替换为 %2f
= 替换为 %3d
c%2bQiUIzV9fRnqcli3qV5sN77pFfn5XOkjUB9t6uZOk8%3d
2
3
4
5
6
7

使用第二个请求包,验证 脏字符 是否被成功去除。
查看响应内容,去除成功。

# 登录管理员账户
接下来,要将最终的密文字符串 应用到 Cookie 当中。
在登录界面,按下 F12 启用开发者模式,切换至 “存储” 选项卡,点击右上角的 “+” 添加一条 Cookie 。
(你也可以用 BurpSuite 完成此操作)

填入 Cookie 信息:
- 参数名称:
stay-logged-in
- 参数值:
c%2bQiUIzV9fRnqcli3qV5sN77pFfn5XOkjUB9t6uZOk8%3d
添加完毕后,刷新当前页面。

刷新页面之后,虽然还处在登录界面,但是右上角多出了一个 “Admin panel” 选项,说明状态已经发生了改变。

点击 “My account” 可以进入 administrator 的账户界面,说明我们成功获得了管理员身份。

来到管理面板,点击 Delete 删除 carlos 账户。

删除成功,实验完成。

# 修复建议
身份验证绕过漏洞4 - 填充提示攻击
- (推荐)实施多因素身份验证,不能仅凭一个 Cookie 来验证用户身份。
- 不同的功能点,应该采用不同的加密算法 和 不同的密钥。
- 同一功能点,不同作用,也应该采用不同的加密算法 和 不同的密钥。
A 的家有一把锁,B 的家也有一把相同的锁,所以 A/B 用自己家的钥匙 可以打开对方的家门?