CVE-2020-7245(CTFd账户接管漏洞)复现

0x01 漏洞描述

在CTFd v2.0.0-v2.2.2的注册过程中,错误的用户名验证方式会允许攻击者接管任意帐户,前提是用户名已知并且在CTFd平台上启用了电子邮件功能。

0x02 漏洞分析

CTFd v2.0.0版本注册部分的代码

CTFd/CTFd/auth.py#159

CTFd/CTFd/auth.py#207

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
159 def register():
160     errors = get_errors()
161     if request.method == "POST":
162         name = request.form["name"]
163         email_address = request.form["email"]
164         password = request.form["password"]
165
166         name_len = len(name) == 0
167         names = Users.query.add_columns("name", "id").filter_by(name=name).first()
168         emails = (
169             Users.query.add_columns("email", "id")
170             .filter_by(email=email_address)
171             .first()
172         )
173         pass_short = len(password) == 0
174         pass_long = len(password) > 128
175         valid_email = validators.validate_email(request.form["email"])
176         team_name_email_check = validators.validate_email(name)
# 省略部分代码
207         else:
208             with app.app_context():
209                 user = Users(
210                     name=name.strip(),
211                     email=email_address.lower(),
212                     password=password.strip(),
213                 )

可以看到用户注册时name参数并未经过任何处理,判断用户名是否重复时使用的就是没有经过任何处理的name值,然而存入数据库时却将这个name值做了 strip处理,去掉name值首尾的空字符。

这就意味着只要注册一个首尾添加空格的用户名即可绕过用户名不能重复的限制。

CTFd v2.0.0版本找回密码部分的代码

CTFd/CTFd/auth.py#95

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 95 @auth.route("/reset_password", methods=["POST", "GET"])
 96 @auth.route("/reset_password/<data>", methods=["POST", "GET"])
 97 @ratelimit(method="POST", limit=10, interval=60)
 98 def reset_password(data=None):
 99     if data is not None:
100         try:
101             name = unserialize(data, max_age=1800)
102         except (BadTimeSignature, SignatureExpired):
103             return render_template(
104                 "reset_password.html", errors=["Your link has expired"]
105             )
106         except (BadSignature, TypeError, base64.binascii.Error):
107             return render_template(
108                 "reset_password.html", errors=["Your reset token is invalid"]
109             )
110
111
112             return render_template("reset_password.html", mode="set")
113         if request.method == "POST":
114             user = Users.query.filter_by(name=name).first_or_404()
115             user.password = request.form["password"].strip()
116             db.session.commit()
117             log(
118                 "logins",
119                 format="[{date}] {ip} -  successful password reset for {name}",
120                 name=name,
121             )
122             db.session.close()
123             return redirect(url_for("auth.login"))

大致可以理解为找回密码时从链接参数中取data值,将其反序列化后获得用户名,即可重置任意用户的密码。

利用该漏洞需要以下几步:

  • 利用首尾添加空格绕过限制,注册一个与受害者用户名相同的账号
  • 找回密码链接发送到自己的邮箱
  • 修改自己账号的用户名(与受害者不同)
  • 点击重置密码链接,设置新密码

0x03 漏洞复现

V&N 2020公开赛HappyCTFd原题,buuoj有对应的环境。

具体操作主要分为以下几步:

  • 先在buuoj注册个邮箱

  • 利用首尾添加空格绕过限制来注册一个与受害者用户名相同的账号

  • 找回密码链接发送到自己的邮箱

  • 修改自己账号的用户名(与受害者不同)

  • 点击重置密码链接,设置新密码

由于buuoj靶机无法访问外网,所以需要在buuoj的邮件系统注册邮箱。

http://mail.buuoj.cn/admin/ui/user/signup/mail.buuoj.cn

然后我们访问靶机地址,发现该ctfd平台有一个admin账号,所以我们尝试重置admin账号的密码。

首先注册一个首或者尾带空格的admin账号,邮箱需要设置正确。

注册成功可以发现自己后台的用户名首尾并没有空格。

然后尝试重置admin密码,浏览器另外开一个页面,输入自己注册账号的邮箱,获取重置密码链接。

在收件箱中收到重置密码链接后,先不要操作,需要去用户后台页面修改用户名(任意)。

修改完自己的用户名直接点击重置密码链接,对admin账号进行密码重置,设置一个你想要的密码。

再次用admin和你设置的密码登录,就成功拿到了超级管理员权限。

flag在challenges里面找一下,发现有个”flagflag你在哪”的挑战,打开后找到一个”miaoflag.txt”的附件,即flag。

0x04 漏洞修补

更新CTFd为最新版即可。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值