kotlin.lang.security.bad-hexa-conversion.bad-hexa-conversion

profile photo of semgrepsemgrep
Author
unknown
Download Count*

'Integer.toHexString()' strips leading zeroes from each byte if read byte-by-byte. This mistake weakens the hash value computed since it introduces more collisions. Use 'String.format("%02X", ...)' instead.

Run Locally

Run in CI

Defintion

rules:
  - id: bad-hexa-conversion
    metadata:
      cwe:
        - "CWE-704: Incorrect Type Conversion or Cast"
      owasp: A03:2017 - Sensitive Data Exposure
      source-rule-url: https://find-sec-bugs.github.io/bugs.htm#BAD_HEXA_CONVERSION
      category: security
      technology:
        - kotlin
      references:
        - https://cwe.mitre.org/data/definitions/704.html
      subcategory:
        - audit
      likelihood: LOW
      impact: LOW
      confidence: LOW
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Improper Validation
    message: "'Integer.toHexString()' strips leading zeroes from each byte if read
      byte-by-byte. This mistake weakens the hash value computed since it
      introduces more collisions. Use 'String.format(\"%02X\", ...)' instead."
    severity: WARNING
    languages:
      - kt
    pattern: |-
      fun $METHOD(...) {
        ...
        val $MD: MessageDigest = ...
        ...
        $MD.digest(...)
        ...
        Integer.toHexString(...)
      }

Examples

bad-hexa-conversion.kt

package testcode.crypto

import java.io.UnsupportedEncodingException
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException

public class BadHexa {
    public fun main(args: Array<String>): Void {
        val good: String = goodHash("12345")
        val bad: String = badHash("12345")
        System.out.println(String.format("%s (len=%d) != %s (len=%d)", good, good.length(), bad, bad.length()))
    }

    // ok: bad-hexa-conversion
    public fun goodHash(password: String): String {
        val md: MessageDigest = MessageDigest.getInstance("SHA-1")
        val resultBytes: Array<Byte> = md.digest(password.getBytes("UTF-8"))

        var stringBuilder: StringBuilder = StringBuilder()
        for (b in resultBytes) {
            stringBuilder.append(String.format("%02X", b))
        }

        return stringBuilder.toString()
    }

    // ruleid: bad-hexa-conversion
    public fun badHash(password: String): String {
        val md: MessageDigest = MessageDigest.getInstance("SHA-1")
        val resultBytes: Array<Byte> = md.digest(password.getBytes("UTF-8"))

        var stringBuilder: StringBuilder = StringBuilder()
        for (b in resultBytes) {
            stringBuilder.append(Integer.toHexString(b and 0xFF))
        }

        return stringBuilder.toString()
    }
}