go.aws-lambda.security.database-sqli.database-sqli

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Detected SQL statement that is tainted by $EVENT object. This could lead to SQL injection if the variable is user-controlled and not properly sanitized. In order to prevent SQL injection, use parameterized queries or prepared statements instead. You can use prepared statements with the 'Prepare' and 'PrepareContext' calls.

Run Locally

Run in CI

Defintion

rules:
  - id: database-sqli
    languages:
      - go
    message: Detected SQL statement that is tainted by `$EVENT` object. This could
      lead to SQL injection if the variable is user-controlled and not properly
      sanitized. In order to prevent SQL injection, use parameterized queries or
      prepared statements instead. You can use prepared statements with the
      'Prepare' and 'PrepareContext' calls.
    mode: taint
    metadata:
      references:
        - https://pkg.go.dev/database/sql#DB.Query
      category: security
      owasp:
        - A01:2017 - Injection
        - A03:2021 - Injection
      cwe:
        - "CWE-89: Improper Neutralization of Special Elements used in an SQL
          Command ('SQL Injection')"
      technology:
        - aws-lambda
        - database
        - sql
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - vuln
      likelihood: HIGH
      impact: MEDIUM
      confidence: MEDIUM
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - SQL Injection
    pattern-sinks:
      - patterns:
          - focus-metavariable: $QUERY
          - pattern-either:
              - pattern: $DB.Exec($QUERY,...)
              - pattern: $DB.ExecContent($QUERY,...)
              - pattern: $DB.Query($QUERY,...)
              - pattern: $DB.QueryContext($QUERY,...)
              - pattern: $DB.QueryRow($QUERY,...)
              - pattern: $DB.QueryRowContext($QUERY,...)
          - pattern-inside: |
              import "database/sql"
              ...
    pattern-sources:
      - patterns:
          - pattern-either:
              - pattern-inside: |
                  func $HANDLER($CTX $CTXTYPE, $EVENT $TYPE, ...) {...}
                  ...
                  lambda.Start($HANDLER, ...)
              - patterns:
                  - pattern-inside: |
                      func $HANDLER($EVENT $TYPE) {...}
                      ...
                      lambda.Start($HANDLER, ...)
                  - pattern-not-inside: |
                      func $HANDLER($EVENT context.Context) {...}
                      ...
                      lambda.Start($HANDLER, ...)
          - focus-metavariable: $EVENT
    severity: WARNING

Examples

database-sqli.go

package main

import (
	"database/sql"
	"encoding/json"
	"log"
	"os"
	"context"

	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
	_ "github.com/go-sql-driver/mysql"
)

var (
	db               *sql.DB
	err              error
	connectionString string
	dbUser           string
	dbPass           string
	dataSource       string
)

type Employee struct {
	EmployeeNo int    `json:"emp_no"`
	FirstName  string `json:"first_name"`
	LastName   string `json:"last_name"`
}

func init() {
	connectionString = os.Getenv("CONN")
	dbUser = os.Getenv("DBUSER")
	dbPass = os.Getenv("DBPASS")
	dataSource = dbUser + ":" + dbPass + "@tcp(" + connectionString + ")/employees"
}

func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {

	searchCriteria := request.Body

	db, err = sql.Open("mysql", dataSource)
	if err != nil {
		panic(err.Error())
	}

	defer db.Close()

  // ruleid: database-sqli
	results, err := db.Query("select e.emp_no, e.first_name, e.last_name " +
		"from employees e, departments d, dept_emp de " +
		"where de.emp_no = e.emp_no " +
		"and de.dept_no = d.dept_no " +
		"and d.dept_name = 'Marketing' " +
		"and e.last_name LIKE '" + searchCriteria + "%';")

	if err != nil {
		log.Fatal(err)
	}
	defer results.Close()

  // ok: database-sqli
	results2, err2 := db.Query("select * from foobar")

	employees := make([]Employee, 0)

	for results.Next() {
		var e Employee

		err := results.Scan(&e.EmployeeNo, &e.FirstName, &e.LastName)
		if err != nil {
			log.Fatal(err)
		}
		employees = append(employees, e)
	}

	data, _ := json.Marshal(employees)

	return events.APIGatewayProxyResponse{
		StatusCode:      200,
		Body:            string(data),
		IsBase64Encoded: false,
	}, nil
}

func HandleRequest(ctx context.Context, name MyEvent) (string, error) {
	searchCriteria := context.Smth

	db, err = sql.Open("mysql", dataSource)
	if err != nil {
		panic(err.Error())
	}

	defer db.Close()

  	// ok: database-sqli
	results, err := db.Query("select e.emp_no, e.first_name, e.last_name " +
		"from employees e, departments d, dept_emp de " +
		"where de.emp_no = e.emp_no " +
		"and de.dept_no = d.dept_no " +
		"and d.dept_name = 'Marketing' " +
		"and e.last_name LIKE '" + searchCriteria + "%';")

	if err != nil {
		log.Fatal(err)
	}
	defer results.Close()

	data, _ := json.Marshal(results)

	return events.APIGatewayProxyResponse{
		StatusCode:      200,
		Body:            string(data),
		IsBase64Encoded: false,
	}, nil
}

func main() {
	lambda.Start(handler)
	lambda.Start(HandleRequest)
}