Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 161 additions & 0 deletions jort_vleenen_nl/tainted-sql-string-copy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
<?php

// True Positives

function tp1() {
// ruleid: tainted-sql-string
$query = "SELECT * FROM table WHERE Id = '".$_GET['url']."'";
$info = mysql_query($query);
return $info;
}

function tp2() {
$part = $_POST['url'];
// ruleid: tainted-sql-string
$query = "SELECT * FROM table WHERE Id = '$part'";
$info = mysql_query($query);
return $info;
}

function tp3() {
// ruleid: tainted-sql-string
$query = "SELECT * FROM table WHERE Id = '{$_REQUEST['url']}'";
$info = mysql_query($query);
return $info;
}

function tp4() {
// ruleid: tainted-sql-string
$query = sprintf("SELECT * FROM table WHERE Id = '%s'", $_COOKIE['foo']);
$info = mysql_query($query);
return $info;
}

function tp5() {
// ruleid: tainted-sql-string
$query = "
SELECT * FROM table WHERE Id = '".$_GET['url']."'";
$info = mysql_query($query);
return $info;
}

function tp6_partial_sanitisation() {
// Only part of the expression is sanitised; tainted data from 'name' still flows
$id = intval($_GET['id']);
$name = $_GET['name'];
// ruleid: tainted-sql-string
$query = "SELECT * FROM users WHERE id = $id AND name = '$name'";
return mysql_query($query);
}

function tp7_filter_var_not_used() {
// Validation result is ignored; tainted value is used directly
$raw = $_GET['id'];
$validated = filter_var($raw, FILTER_VALIDATE_INT);
// ruleid: tainted-sql-string
$query = "SELECT * FROM users WHERE id = $raw";
return mysql_query($query);
}

// True Negatives

function tn1() {
// ok: tainted-sql-string
$query = 'SELECT * FROM table WHERE Id = 1';
$info = mysql_query($query);
return $info;
}

function tn2() {
$value = 1;
// ok: tainted-sql-string
$query = "SELECT * FROM table WHERE Id = '".$value."'";
$info = mysql_query($query);
return $info;
}

function tn3() {
// ok: tainted-sql-string
$query = "SELECT * FROM table WHERE Id = '{$foobar() ? 1 : 2}'";
$info = mysql_query($query);
return $info;
}

function tn4() {
$value = 1;
// ok: tainted-sql-string
$query = sprintf("SELECT * FROM table WHERE Id = '%s'", $value);
$info = mysql_query($query);
return $info;
}

function tn5() {
$part = $_POST['url'];
$part = mysqli_real_escape_string($part);
// ok: tainted-sql-string
$query = sprintf("SELECT * FROM table WHERE Id = '" . $part . "'");
$info = mysql_query($query);
return $info;
}

function tn6_ok_delete_non_sql_string() {
// ok: tainted-sql-string
$this->delete("id:".$_GET['id']);
}

function tn7_ok_non_sql_context() {
// ok: tainted-sql-string
$select = "Foobar: = '{$_REQUEST['url']}'";
$info = do_smth($select);
return $info;
}

function tn8_intval_in_numeric_context() {
$id = intval($_GET['id']);
// ok: tainted-sql-string
$query = "SELECT * FROM users WHERE id = $id";
return mysql_query($query);
}

function tn9_int_cast_in_numeric_context() {
$id = (int) $_GET['id'];
// ok: tainted-sql-string
$query = "SELECT * FROM users WHERE id = $id";
return mysql_query($query);
}

function tn10_floatval_price() {
$price = floatval($_GET['price']);
// ok: tainted-sql-string
$query = "SELECT * FROM products WHERE price > $price";
return mysql_query($query);
}

function tn11_filter_var_int() {
$id = filter_var($_GET['id'], FILTER_VALIDATE_INT);
// ok: tainted-sql-string
$query = "SELECT * FROM users WHERE id = $id";
return mysql_query($query);
}

function tn12_filter_var_float() {
$amount = filter_var($_POST['amount'], FILTER_VALIDATE_FLOAT);
// ok: tainted-sql-string
$query = "SELECT * FROM payments WHERE amount > $amount";
return mysql_query($query);
}

function tn13_intval_then_string_with_quotes() {
$id = intval($_GET['id']);
// ok: tainted-sql-string
$query = "SELECT * FROM users WHERE id = '$id'";
return mysql_query($query);
}

function tn14_int_sanitised_and_escaped_name() {
$id = (int) $_GET['id'];
$name = mysqli_real_escape_string($_GET['name']);
// ok: tainted-sql-string
$query = "SELECT * FROM users WHERE id = $id AND name = '$name'";
return mysql_query($query);
}
71 changes: 71 additions & 0 deletions jort_vleenen_nl/tainted-sql-string-copy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
rules:
- id: tainted-sql-string
languages:
- php
severity: ERROR
message: User data flows into this manually-constructed SQL string. User data can
be safely inserted into SQL strings using prepared statements or an object-relational
mapper (ORM). Manually-constructed SQL strings is a possible indicator of SQL
injection, which could let an attacker steal or manipulate data from the database.
Instead, use prepared statements (`$mysqli->prepare("INSERT INTO test(id, label)
VALUES (?, ?)");`) or a safe library.
pattern-sources:
- patterns:
- pattern-either:
- pattern: $_GET
- pattern: $_POST
- pattern: $_COOKIE
- pattern: $_REQUEST
pattern-sinks:
- pattern-either:
- patterns:
- pattern: sprintf($SQLSTR, ...)
- metavariable-regex:
metavariable: $SQLSTR
regex: (?is).*\b(select|delete|insert|create|update|alter|drop)\b.*
- patterns:
- pattern: '"...$EXPR..."'
- metavariable-regex:
metavariable: $EXPR
regex: (?is).*\b(select|delete|insert|create|update|alter|drop)\b.*
- patterns:
- pattern: '"$SQLSTR".$EXPR'
- metavariable-regex:
metavariable: $SQLSTR
regex: (?is).*\b(select|delete|insert|create|update|alter|drop)\b.*
pattern-sanitizers:
- pattern-either:
- pattern: mysqli_real_escape_string(...)
- pattern: real_escape_string(...)
- pattern: $MYSQLI->real_escape_string(...)
- pattern: intval(...)
- pattern: (int) $X
- pattern: floatval(...)
- pattern: (float) $X
- pattern: doubleval(...)
- pattern: (double) $X
- pattern: filter_var(..., FILTER_VALIDATE_INT)
- pattern: filter_var(..., FILTER_VALIDATE_FLOAT)
mode: taint
metadata:
cwe:
- 'CWE-89: Improper Neutralization of Special Elements used in an SQL Command
(''SQL Injection'')'
owasp:
- A01:2017 - Injection
- A03:2021 - Injection
references:
- https://owasp.org/www-community/attacks/SQL_Injection
category: security
technology:
- php
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- vuln
likelihood: HIGH
impact: MEDIUM
confidence: MEDIUM
license: Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license
vulnerability_class:
- SQL Injection