go.lang.security.audit.md5-used-as-password.md5-used-as-password

profile photo of semgrepsemgrep
Author
unknown
Download Count*

It looks like MD5 is used as a password hash. MD5 is not considered a secure password hash because it can be cracked by an attacker in a short amount of time. Use a suitable password hashing function such as bcrypt. You can use the golang.org/x/crypto/bcrypt package.

Run Locally

Run in CI

Defintion

rules:
  - id: md5-used-as-password
    languages:
      - go
    severity: WARNING
    message: It looks like MD5 is used as a password hash. MD5 is not considered a
      secure password hash because it can be cracked by an attacker in a short
      amount of time. Use a suitable password hashing function such as bcrypt.
      You can use the `golang.org/x/crypto/bcrypt` package.
    options:
      interfile: true
    metadata:
      category: security
      technology:
        - md5
      references:
        - https://tools.ietf.org/id/draft-lvelvindron-tls-md5-sha1-deprecate-01.html
        - https://security.stackexchange.com/questions/211/how-to-securely-hash-passwords
        - https://github.com/returntocorp/semgrep-rules/issues/1609
        - https://pkg.go.dev/golang.org/x/crypto/bcrypt
      owasp:
        - A03:2017 - Sensitive Data Exposure
        - A02:2021 - Cryptographic Failures
      cwe:
        - "CWE-327: Use of a Broken or Risky Cryptographic Algorithm"
      confidence: MEDIUM
      subcategory:
        - vuln
      likelihood: MEDIUM
      impact: MEDIUM
      interfile: true
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Cryptographic Issues
    mode: taint
    pattern-sources:
      - patterns:
          - pattern-either:
              - pattern: md5.New
              - pattern: md5.Sum
    pattern-sinks:
      - patterns:
          - pattern: $FUNCTION(...)
          - metavariable-regex:
              metavariable: $FUNCTION
              regex: (?i)(.*password.*)

Examples

md5-used-as-password.go

package main

import (
    "crypto/md5"
    "crypto/sha256"
    "fmt"
    "io"
)

//// True positives ////
func ex1(user *User, pwtext string) {
    h := md5.New()
    io.WriteString(h, pwtext)
    // ruleid: md5-used-as-password
    user.setPassword(h.Sum(nil))
}

func ex2(user *User, pwtext string) {
    data := []byte(pwtext)
    // ruleid: md5-used-as-password
    user.setPassword(md5.Sum(data))
}

//// True negatives ////
func ok1(user *User, pwtext string) {
    h := sha256.New()
    io.WriteString(h, pwtext)
    // ok: md5-used-as-password
    user.setPassword(h.Sum(nil))
}

func ok2(user *User, pwtext string) {
    data := []byte(pwtext)
    // ok: md5-used-as-password
    user.setPassword(sha256.Sum(data))
}

func ok3(user *User, pwtext string) {
    data := []byte(pwtext)
    // ok: md5-used-as-password
    user.setSomethingElse(md5.Sum(data))
}