CodeQL 文档

硬编码凭据

ID: rb/hardcoded-credentials
Kind: path-problem
Security severity: 9.8
Severity: error
Precision: medium
Tags:
   - security
   - external/cwe/cwe-259
   - external/cwe/cwe-321
   - external/cwe/cwe-798
Query suites:
   - ruby-security-extended.qls
   - ruby-security-and-quality.qls

单击以在 CodeQL 存储库中查看查询

在源代码或配置文件中包含未加密的硬编码入站或出站身份验证凭据很危险,因为这些凭据很容易被发现。

包含硬编码凭据的源代码或配置文件可能对攻击者可见。例如,源代码可能是开源的,或者可能被泄露或意外泄露。

对于入站身份验证,硬编码凭据可能允许未经授权访问系统。如果凭据在源代码中硬编码,这将尤其成问题,因为无法轻松禁用它。对于出站身份验证,硬编码凭据可能会向攻击者提供特权信息或对其他系统的未经授权访问。

建议

从源代码中删除硬编码凭据,例如用户名、密码和证书,如果必要,将它们放在配置文件或其他数据存储中。如果可能,请将包含凭据数据的配置文件与源代码分开存储,并将其存储在安全位置,并限制访问权限。

对于出站身份验证详细信息,请考虑加密凭据或封闭的数据存储或配置文件,并使用权限来限制访问权限。

对于入站身份验证详细信息,请考虑尽可能使用标准库函数对密码进行散列。例如,OpenSSL::KDF.pbkdf2_hmac

示例

以下示例显示了不同类型的入站和出站身份验证。

在第一个案例中,RackAppBad,我们接受来自远程用户的密码,并将其与明文字符串文字进行比较。如果攻击者获取了源代码,他们可以观察到密码,并登录到系统。此外,如果发现了此类入侵,则需要重新编写应用程序并重新部署它以更改密码。

在第二个案例中,RackAppGood,密码使用 OpenSSL::KDF.pbkdf2_hmac 与存储在配置文件中的散列和加盐密码进行比较。在这种情况下,访问源代码或汇编不会向攻击者泄露密码。即使访问包含密码哈希和盐的配置文件,对攻击者也没有太大价值,因为通常很难从哈希和盐中逆向工程密码。在实际应用程序中,应注意使散列输入与散列密码的字符串比较在接近恒定时间内进行,因为这将使计时攻击更加困难。

require 'rack'
require 'yaml'
require 'openssl'

class RackAppBad
  def call(env)
    req = Rack::Request.new(env)
    password = req.params['password']

    # BAD: Inbound authentication made by comparison to string literal
    if password == 'myPa55word'
      [200, {'Content-type' => 'text/plain'}, ['OK']]
    else
      [403, {'Content-type' => 'text/plain'}, ['Permission denied']]
    end
  end
end

class RackAppGood
  def call(env)
    req = Rack::Request.new(env)
    password = req.params['password']

    config_file = YAML.load_file('config.yml')
    hashed_password = config_file['hashed_password']
    salt = [config_file['salt']].pack('H*')

    #GOOD: Inbound authentication made by comparing to a hash password from a config file.
    hash = OpenSSL::Digest::SHA256.new
    dk = OpenSSL::KDF.pbkdf2_hmac(
      password, salt: salt, hash: hash, iterations: 100_000, length: hash.digest_length
    )
    hashed_input = dk.unpack('H*').first
    if hashed_password == hashed_input
      [200, {'Content-type' => 'text/plain'}, ['OK']]
    else
      [403, {'Content-type' => 'text/plain'}, ['Permission denied']]
    end
  end
end

参考

  • ©GitHub, Inc.
  • 条款
  • 隐私