漏洞简介
2024年1月11日,Gitlab 官方披露 CVE-2023-7028,GitLab 任意用户密码重置漏洞,官方评级严重。攻击者可利用忘记密码功能,构造恶意请求获取密码重置链接从而重置密码。官方已发布安全更新,建议升级至最新版本,若无法升级,建议利用安全组功能设置Gitlab 仅对可信地址开放。
影响版本
16.1 <= GitLab CE/EE < 16.1.5
16.2 <= GitLab CE/EE < 16.2.8
16.3 <= GitLab CE/EE < 16.3.6
16.4 <= GitLab CE/EE < 16.4.4
16.5 <= GitLab CE/EE < 16.5.6
16.6 <= GitLab CE/EE < 16.6.4
16.7 <= GitLab CE/EE < 16.7.2
在漏洞版本范围内的 GitLab 开启 邮箱登录认证,就可以利用内置用户 admin@example.com 重置该密码实现登录
环境搭建
wget https://mirror.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-16.1.1-ce.0.el7.x86_64.rpm #下载gitlab-ce
yum localinstall gitlab-ce-16.1.1-ce.0.el7.x86_64.rpm -y
vim /etc/gitlab/gitlab.rb # 修改配置文件 修改 external_url 为对应ip
gitlab-ctl reconfigure # 生效配置代码
gitlab-ctl status # 查看服务运行状态
systemctl stop firewalld # 关闭防火墙
firewall-cmd --state # 查看防火墙状态
cat /etc/gitlab/initial_root_password # 查看初始密码
漏洞出现在忘记密码时发送邮件,所以我们需要进行邮箱配置
vim /etc/gitlab/gitlab.rb
gitlab_rails['smtp_enable'] = true # 开启邮件配置
gitlab_rails['smtp_address'] = "smtp.qq.com" # 修改为对应的邮箱服务器域名
gitlab_rails['smtp_port'] = 465 # 对应的端口协议
gitlab_rails['smtp_user_name'] = "xxxxxx@qq.com" # 登录邮箱的用户名
gitlab_rails['smtp_password'] = "xxxxxx" # 登录邮箱的密码(其他的邮箱为授权码,例如QQ、163邮箱)
gitlab_rails['smtp_domain'] = "qq.com" # 修改为对应的邮箱服务器域名
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = false
gitlab_rails['smtp_tls'] = true
gitlab_rails['smtp_pool'] = true
gitlab_rails['gitlab_email_from'] = 'xxxxxx@qq.com' # gitlab发送人,修改为对用的邮箱
gitlab_rails['gitlab_email_display_name'] = 'admin' # gitlab发邮件时使用的名称
gitlab_rails['gitlab_email_reply_to'] = 'xxxxxx@qq.com'
进行邮件测试发送
#登录gitlab控制台
gitlab-rails console -e production
#测试邮件发送
Notify.test_email('xxxx@qq.com','test','test').deliver_now
发送成功
注册一个用户
登录管理员账号 通过审核
成功登录
漏洞复现
点击忘记密码
输入邮箱地址 抓取数据包
修改传参方式 将原本的 user%5Bemail%5D 修改为数组传参 user%5Bemail%5D%5B%5D 再添加一个邮箱
同时两个邮箱都收到了信息
点击重置密码链接
成功重置用户密码并登录
漏洞分析
这是一个用 Ruby 编写的函数,用于测试是否已发送符合预期主题和接收者的一封电子邮件。该函数接受两个参数:subject
,类型为字符串,表示预期电子邮件的主题; to
,为字符串数组,表示预期电子邮件的接收者。
函数首先使用 ActionMailer::Base.deliveries.count
获取已发送电子邮件的计数。然后使用 expect(count_of_sent_emails).to eq(1)
检查计数是否等于 1。如果计数不等于 1,则会引发错误消息,说明发送了多封电子邮件。
如果只有一封电子邮件被发送,则获取第一封(也是唯一的)电子邮件,并使用 expect(message.subject).to eq(subject)
检查其主题是否与预期主题匹配。还使用 expect(message.to).to match_array(to)
检查电子邮件是否发送给了预期接收者。
最后,如果任何期望未达成,函数将引发详细说明出错原因的错误消息。否则,函数仅返回而不执行任何操作。
获取版本信息
http://192.168.222.142/assets/webpack/manifest.json
通过对比 hash 值来获取版本信息
https://github.com/righel/gitlab-version-nse/blob/main/gitlab_hashes.json