亲宝软件园·资讯

展开

CVE-2020-7245 CTFd v2.0.0 – v2.2.2漏洞分析复现

d3solate 人气:0
## CVE-2020-7245 CTFd v2.0.0 – v2.2.2漏洞分析复现 ### 一、漏洞介绍 ​ 在 CTFd v2.0.0 - v2.2.2 的注册过程中,如果知道用户名并在 CTFd 实例上启用电子邮件,则攻击者可以修改任意帐户的密码。 ​ 漏洞影响范围 ​ V2.0.0-V2.2.2 ### 二、漏洞环境搭建 ​ 在github上下载对应版本的CTFd,文件夹中有dockerfile,可以选择手动搭建,或者在docker中搭建。这里选择使用docker-compose来搭建,比较方便。 ​ 输入 ```python docker-compose up ``` ​ 等待安装完成,之后访问ip:8000端口即可。 ​ **注**: ​ 如果过程太过漫长,建议修改 **docker源,pip源,以及alpine源** 至国内镜像源 ​ docker源可以通过阿里云的 [容器镜像服务控制台](https://cr.console.aliyun.com/)中的说明进行修改。(阿里云的说明还是挺棒的) ​ pip源如果不想永久修改,可以打开Dockerfile,修改它的命令达到临时修改的目的。 ![](https://img2020.cnblogs.com/blog/1939948/202003/1939948-20200305223750468-737276067.jpg) ​ 在两处命令后都加上-i https://mirrors.aliyun.com/pypi/simple/来临时指定下载地址 ​ 安装过程中使用了alpine系统 依然通过修改Dockerfile来达到加速的目的 ​ ![](https://img2020.cnblogs.com/blog/1939948/202003/1939948-20200305223811330-296194750.jpg) ​ 修改 alpine的镜像源。 ### 三、漏洞分析 ​ 首先找到它注册部分的代码 ```python def register(): errors = get_errors() if request.method == 'POST': name = request.form['name'] email_address = request.form['email'] password = request.form['password'] name_len = len(name) == 0 names = Users.query.add_columns('name', 'id').filter_by(name=name).first() emails = Users.query.add_columns('email', 'id').filter_by(email=email_address).first() pass_short = len(password) == 0 ``` ​ 可以看到 当我们通过POST发来注册请求的时候,其中的name参数并没有经过处理,而是直接被再次当作参数传入。 ```python else: with app.app_context(): user = Users( name=name.strip(), email=email_address.lower(), password=password.strip() ) ``` ​ 当name通过了各种检查之后,即将存入时,使用了strip方法对name进行了处理。 这就意味着,**如果我们在用户名的首尾添加上空格的时候,可以绕过用户名重复的检查** **存入数据库之前空格会被删去**,那么就会导致注册的用户名会和数据库中已有的重复。 ​ 然后找到他的找回密码部分的代码 ```python def reset_password(data=None): if data is not None: try: name = unserialize(data, max_age=1800) except (BadTimeSignature, SignatureExpired): return render_template('reset_password.html', errors=['Your link has expired']) except (BadSignature, TypeError, base64.binascii.Error): return render_template('reset_paassword.html', errors=['Your reset token is invalid']) if request.method == "GET": return render_template('reset_password.html', mode='set') if request.method == "POST": user = Users.query.filter_by(name=name).first_or_404() user.password = request.form['password'].strip() db.session.commit() log('logins', format="[{date}] {ip} - successful password reset for {name}", name=name) db.session.close() return redirect(url_for('auth.login')) ``` ​ 这里发现,会取出data,来找一下data是什么 ```python def forgot_password(email, team_name): token = serialize(team_name) text = """Did you initiate a password reset? Click the following link to reset your password: {0}/{1} """.format(url_for('auth.reset_password', _external=True), token) sendmail(email, text) def verify_email_address(addr): token = serialize(addr) text = """Please click the following link to confirm your email address for {ctf_name}: {url}/{token}""".format( ctf_name=get_config('ctf_name'), url=url_for('auth.confirm', _external=True), token=token ) sendmail(addr, text) ``` ​ 发现发到邮箱里的url是 {url}/{token}。 ​ 到这里,漏洞的利用方式就大概出来了。 - 首先注册一个用户名包含空格,默认的管理员是admin,那么就可以注册一个 admin。 - 然后,退出登录,点重置密码。 - 这时候邮箱里就会收到一个url,这个url后面拼接的token实际上是属于用户名admin的 - 将自己注册的账号用户名修改成其他 - 然后点开链接修改密码,admin的密码就被修改了 ### 四、漏洞复现 - **注册账号** 账号名字取为 "空格admin" ![](https://img2020.cnblogs.com/blog/1939948/202003/1939948-20200305223858258-1263888211.jpg) - **退出登录,点击忘记密码** 输入邮箱 ![](https://img2020.cnblogs.com/blog/1939948/202003/1939948-20200305223932981-926856933.jpg) - 修改用户名为其他 - 点开邮箱中的链接 ![](https://img2020.cnblogs.com/blog/1939948/202003/1939948-20200305224008533-1473744801.jpg) - 重置成功

加载全部内容

相关教程
猜你喜欢
用户评论