go.lang.security.audit.unsafe-reflect-by-name.unsafe-reflect-by-name

profile photo of semgrepsemgrep
Author
7,585
Download Count*

If an attacker can supply values that the application then uses to determine which method or field to invoke, the potential exists for the attacker to create control flow paths through the application that were not intended by the application developers. This attack vector may allow the attacker to bypass authentication or access control checks or otherwise cause the application to behave in an unexpected manner.

Run Locally

Run in CI

Defintion

rules:
  - id: unsafe-reflect-by-name
    patterns:
      - pattern-either:
          - pattern: |
              $SMTH.MethodByName($NAME,...)
          - pattern: |
              $SMTH.FieldByName($NAME,...)
      - pattern-not: |
          $SMTH.MethodByName("...",...)
      - pattern-not: |
          $SMTH.FieldByName("...",...)
      - pattern-inside: |
          import "reflect"
          ...
    message: If an attacker can supply values that the application then uses to
      determine which method or field to invoke, the potential exists for the
      attacker to create control flow paths through the application that were
      not intended by the application developers. This attack vector may allow
      the attacker to bypass authentication or access control checks or
      otherwise cause the application to behave in an unexpected manner.
    metadata:
      cwe:
        - "CWE-470: Use of Externally-Controlled Input to Select Classes or Code
          ('Unsafe Reflection')"
      owasp:
        - A03:2021 - Injection
      category: security
      technology:
        - go
      confidence: LOW
      references:
        - https://owasp.org/Top10/A03_2021-Injection
      subcategory:
        - audit
      likelihood: LOW
      impact: LOW
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Improper Authorization
    severity: WARNING
    languages:
      - go

Examples

unsafe-reflect-by-name.go

package testing

import (
    "bytes"
    "fmt"
    "reflect"
)

func (mf mapFmt) Format(s fmt.State, c rune, userInput string) {
    refVal := mf.m
    key := keys[i]
    val := refVal.MapIndex(key)

    // ruleid: unsafe-reflect-by-name
    meth := key.MethodByName(userInput)
    meth.Call(nil)[0]

    return
}

func Test1(job interface{}, userInput string) {
    jobData := make(map[string]interface{})

    valueJ := reflect.ValueOf(job).Elem()

    // ruleid: unsafe-reflect-by-name
    jobData["color"] = valueJ.FieldByName(userInput).String()

    return jobData
}

func OkTest(job interface{}, userInput string) {
    jobData := make(map[string]interface{})

    valueJ := reflect.ValueOf(job).Elem()

    // ok: unsafe-reflect-by-name
    meth := valueJ.MethodByName("Name")
    // ok: unsafe-reflect-by-name
    jobData["color"] = valueJ.FieldByName("color").String()

    return jobData
}