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
Binary file added PR_9_php/semgrep_php/doctrine/.DS_Store
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

class ProductRepository extends ServiceEntityRepository
{
public function test1(int $price): array
{
$conn = $this->getEntityManager()->getConnection();

$sql = "SELECT * FROM product p WHERE p.price > " . $_GET['cur_price']. " ORDER BY p.price ASC";
// {fact rule=sql-injection@v1.0 defects=1}
// ruleid: doctrine-dbal-dangerous-query
$stmt = $conn->prepare($sql);
// {/fact}
$stmt->execute(['price' => $price]);

return $stmt->fetchAllAssociative();
}

public function test2(): array
{
$conn = $this->getEntityManager()->getConnection();

// {fact rule=sql-injection@v1.0 defects=1}
// ruleid: doctrine-dbal-dangerous-query
$query = $conn->createQuery("SELECT u FROM User u WHERE u.username = '" . $_GET['username'] . "'");
// {/fact}
$data = $query->getResult();
return $data;
}

public function okTest1(int $price): array
{
$conn = $this->getEntityManager()->getConnection();
$sql = "SELECT * FROM users WHERE username = ?";
// {fact rule=sql-injection@v1.0 defects=0}
// ok: doctrine-dbal-dangerous-query
$stmt = $conn->prepare($sql);
// {/fact}
$stmt->bindValue(1, $_GET['username']);
$resultSet = $stmt->executeQuery();
return $resultSet;
}

public function okTest2(int $price): array
{
$conn = $this->foobar();
$sql = "SELECT * FROM users WHERE username = ?";
// {fact rule=sql-injection@v1.0 defects=0}
// ok: doctrine-dbal-dangerous-query
$stmt = $conn->prepare($sql);
// {/fact}
$stmt->bindValue(1, $_GET['username']);
$resultSet = $stmt->executeQuery();
return $resultSet;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
rules:
- id: doctrine-dbal-dangerous-query
languages:
- php
message: Detected string concatenation with a non-literal variable in a Doctrine DBAL query method.
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.
metadata:
category: security
cwe:
- "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')"
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
owasp:
- A01:2017 - Injection
- A03:2021 - Injection
references:
- https://www.doctrine-project.org/projects/doctrine-dbal/en/current/reference/security.html
- https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html
technology:
- doctrine
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- audit
likelihood: LOW
impact: HIGH
confidence: LOW
patterns:
- pattern-either:
- pattern: $CONNECTION->prepare($QUERY,...)
- pattern: $CONNECTION->createQuery($QUERY,...)
- pattern: $CONNECTION->executeQuery($QUERY,...)
- pattern-either:
- pattern-inside: |
use Doctrine\DBAL\Connection;
...
- pattern-inside: |
$CONNECTION = $SMTH->getConnection(...);
...
- pattern-not: $CONNECTION->prepare("...",...)
- pattern-not: $CONNECTION->createQuery("...",...)
- pattern-not: $CONNECTION->executeQuery("...",...)
severity: WARNING
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

function test1($input)
{
$queryBuilder = $conn->createQueryBuilder();

$queryBuilder
->select('id', 'name')
->from('users')
// {fact rule=sql-injection@v1.0 defects=1}
// ruleid: doctrine-orm-dangerous-query
->where('email = '.$input)
// {/fact}
;
}

function test2($email, $input)
{
$queryBuilder = new QueryBuilder($this->connection);

$queryBuilder
->select('id', 'name')
->from('users')
->where('email = ?')
->setParameter(0, $email)
// {fact rule=sql-injection@v1.0 defects=1}
// ruleid: doctrine-orm-dangerous-query
->andWhere(sprintf('user = %s', $input))
// {/fact}
;
}

function okTest1($input)
{
$queryBuilder = $conn->createQueryBuilder();

$queryBuilder
->select('id', 'name')
->from('users')
// {fact rule=sql-injection@v1.0 defects=0}
// ok: doctrine-orm-dangerous-query
->where('email = ?')
// {/fact}
->setParameter(0, $input)
;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
rules:
- id: doctrine-orm-dangerous-query
languages:
- php
message: >-
`$QUERY` Detected string concatenation with a non-literal variable in a Doctrine
QueryBuilder method. 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.
metadata:
category: security
cwe:
- "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')"
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
owasp:
- A01:2017 - Injection
- A03:2021 - Injection
references:
- https://www.doctrine-project.org/projects/doctrine-dbal/en/current/reference/query-builder.html#security-safely-preventing-sql-injection
- https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html
technology:
- doctrine
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- vuln
likelihood: MEDIUM
impact: MEDIUM
confidence: MEDIUM
mode: taint
pattern-sinks:
- patterns:
- focus-metavariable: $SINK
- pattern-either:
- pattern: $QUERY->add(...,$SINK,...)
- pattern: $QUERY->select(...,$SINK,...)
- pattern: $QUERY->addSelect(...,$SINK,...)
- pattern: $QUERY->delete(...,$SINK,...)
- pattern: $QUERY->update(...,$SINK,...)
- pattern: $QUERY->insert(...,$SINK,...)
- pattern: $QUERY->from(...,$SINK,...)
- pattern: $QUERY->join(...,$SINK,...)
- pattern: $QUERY->innerJoin(...,$SINK,...)
- pattern: $QUERY->leftJoin(...,$SINK,...)
- pattern: $QUERY->rightJoin(...,$SINK,...)
- pattern: $QUERY->where(...,$SINK,...)
- pattern: $QUERY->andWhere(...,$SINK,...)
- pattern: $QUERY->orWhere(...,$SINK,...)
- pattern: $QUERY->groupBy(...,$SINK,...)
- pattern: $QUERY->addGroupBy(...,$SINK,...)
- pattern: $QUERY->having(...,$SINK,...)
- pattern: $QUERY->andHaving(...,$SINK,...)
- pattern: $QUERY->orHaving(...,$SINK,...)
- pattern: $QUERY->orderBy(...,$SINK,...)
- pattern: $QUERY->addOrderBy(...,$SINK,...)
- pattern: $QUERY->set($SINK,...)
- pattern: $QUERY->setValue($SINK,...)
- pattern-either:
- pattern-inside: |
$Q = $X->createQueryBuilder();
...
- pattern-inside: |
$Q = new QueryBuilder(...);
...
pattern-sources:
- patterns:
- pattern-either:
- pattern: sprintf(...)
- pattern: |
"...".$SMTH
severity: WARNING
33 changes: 33 additions & 0 deletions PR_9_php/semgrep_php/lang/security/assert-use.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

$tainted = $_GET['userinput'];

// {fact rule=code-injection@v1.0 defects=1}
// ruleid: assert-use
assert($tainted);
// {/fact}

// {fact rule=code-injection@v1.0 defects=0}
// ok: assert-use
assert('2 > 1');
// {/fact}

// {fact rule=code-injection@v1.0 defects=0}
// todook: assert-use
assert($tainted > 1);
// {/fact}

Route::get('bad', function ($name) {
// {fact rule=code-injection@v1.0 defects=1}
// ruleid: assert-use
assert($name);
// {/fact}

// {fact rule=code-injection@v1.0 defects=0}
// ok: assert-use
assert('2 > 1');
// {/fact}

// todook: assert-use
assert($name > 1);
});
41 changes: 41 additions & 0 deletions PR_9_php/semgrep_php/lang/security/assert-use.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
rules:
- id: assert-use
mode: taint
pattern-sources:
- pattern-either:
- patterns:
- pattern-either:
- pattern: $_GET
- pattern: $_POST
- pattern: $_COOKIE
- pattern: $_REQUEST
- pattern: $_SERVER
- patterns:
- pattern: |
Route::$METHOD($ROUTENAME, function(..., $ARG, ...) { ... })
- focus-metavariable: $ARG
pattern-sinks:
- patterns:
- pattern: assert($SINK, ...);
- pattern-not: assert("...", ...);
- pattern: $SINK
message: >-
Calling assert with user input is equivalent to eval'ing.
metadata:
owasp:
- A03:2021 - Injection
cwe:
- "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')"
references:
- https://www.php.net/manual/en/function.assert
- https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/AssertsSniff.php
category: security
technology:
- php
confidence: HIGH
subcategory:
- vuln
likelihood: MEDIUM
impact: MEDIUM
languages: [php]
severity: ERROR
71 changes: 71 additions & 0 deletions PR_9_php/semgrep_php/lang/security/audit/assert-use-audit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

// {ex-fact rule=code-injection@v1.0 defects=1}
// ruleid: assert-use-audit
//assert($user_input);
// {/ex-fact}

// {fact rule=code-injection@v1.0 defects=1}
// ruleid: assert-use-audit
assert($_GET['something']);
// {/fact}

// {fact rule=code-injection@v1.0 defects=1}
// ruleid: assert-use-audit
assert($_POST[$param]);
// {/fact}

// {ex-fact rule=code-injection@v1.0 defects=1}
// ruleid: assert-use-audit
//assert($someobj->name);
// {/ex-fact}

// {fact rule=code-injection@v1.0 defects=0}
// ok: assert-use-audit
assert('2 > 1');
// {/fact}

// {fact rule=code-injection@v1.0 defects=0}
// ok: assert-use-audit
assert($user_input > 1);
// {/fact}

// {fact rule=code-injection@v1.0 defects=0}
// ok: assert-use-audit
assert($ok < 1 || $ok > 2);
// {/fact}

// {fact rule=code-injection@v1.0 defects=0}
// ok: assert-use-audit
assert($ok->count < 1 || $ok > 2);
// {/fact}

// {fact rule=code-injection@v1.0 defects=0}
// ok: assert-use-audit
assert($ok != "something");
// {/fact}

// {fact rule=code-injection@v1.0 defects=0}
// ok: assert-use-audit
assert($ok!="something");
// {/fact}

// {fact rule=code-injection@v1.0 defects=0}
// ok: assert-use-audit
assert($ok instanceof FakeClass);
// {/fact}

// {fact rule=code-injection@v1.0 defects=0}
// ok: assert-use-audit
assert($ok[$param] instanceof FakeClass);
// {/fact}

// {fact rule=code-injection@v1.0 defects=0}
// ok: assert-use-audit
assert($ok['foo'] instanceof FakeClass);
// {/fact}

// {fact rule=code-injection@v1.0 defects=0}
// ok: assert-use-audit
assert($ok->property instanceof FakeClass);
// {/fact}
29 changes: 29 additions & 0 deletions PR_9_php/semgrep_php/lang/security/audit/assert-use-audit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
rules:
- id: assert-use-audit
patterns:
- pattern: assert($ASSERT, ...);
- pattern-not: assert("...", ...);
- metavariable-regex:
metavariable: $ASSERT
# explanation - alphanumerics, array references (literal or variable), object properties
regex: \A\$[A-Za-z\[\]\-_'"\$]+(\-\>\w+)?\Z
message: >-
Calling assert with user input is equivalent to eval'ing.
metadata:
owasp:
- A03:2021 - Injection
cwe:
- "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')"
references:
- https://www.php.net/manual/en/function.assert
- https://github.com/FloeDesignTechnologies/phpcs-security-audit/blob/master/Security/Sniffs/BadFunctions/AssertsSniff.php
category: security
technology:
- php
confidence: LOW
subcategory:
- audit
likelihood: LOW
impact: HIGH
languages: [php]
severity: ERROR
Loading