Semgrep
Semgrep¶
Auto Testing:
semgrep --metrics=off --config=auto $(pwd)
#semgrep --metrics=off --config "p/security-audit" --config "p/owasp-top-ten" --config "p/auto" --config "p/mobsfscan" --config "p/java" v1.0.0+32548-jadx/sources/
Manual Config Testing¶
Manual Code Testing¶
Master Command:
semgrep -c "p/ci" -c "p/clientside-js" -c "p/django" -c "p/docker" -c "p/docker-compose" -c "p/dockerfile" -c "p/eslint-plugin-security" -c "p/expressjs" -c "p/flask" -c "p/insecure-transport" -c "p/javascript" -c "p/jwt" -c "p/kubernetes" -c "p/lockfiles" -c "p/nginx" -c "p/nodejs" -c "p/nodejsscan" -c "p/phpcs-security-audit" -c "p/python" -c "p/r2c" -c "p/r2c-ci" -c "p/react" -c "p/sql-injection" -c "p/terraform" -c "p/trailofbits" -c "p/typescript" -c "p/xss" -c "p/gitlab-bandit" -c "p/command-injection" -c "p/secrets" -c "p/owasp-top-ten" -c "p/r2c-security-audit" -c "p/gitlab-eslint" $(pwd)
Configurations:
semgrep --config "p/r2c" --config "p/r2c-ci" --config "p/docker-compose" --config "p/dockerfile" --config "p/kubernetes" --config "p/nginx" --config "p/terraform" --config "p/lockfiles" $(pwd)
Testing an Javascript Codebase:
semgrep --config "p/ci" --config "p/r2c" --config "p/r2c-ci" --config "p/eslint-plugin-security" --config "gitlab-eslint" --config "cleintside-js" --config "p/typescript" --config "p/javascript" --config "p/react" $(pwd)
Testing an Nodejs Codebase:
semgrep --config "p/ci" --config "p/typescript" --config "p/sql-injection" --config "p/eslint-plugin-security" --config "p/gitlab-eslint" --config "p/nodejsscan" --config "p/expressjs" --config "p/nodejs" --config "p/react"
Testing an Rust Codebase:
semgrep --config "p/ci"
# Runs Semgrep rules from the /home/semgrep-rules directory
#semgrep -f /home/semgrep-rules
Testing an Android Codebase:
semgrep --config "p/ci" --config "p/mobsfscan" --config "p/koltin"
Testing an iOS Codebase:
semgrep --config "p/ci"
Testing a Java Codebase:
semgrep --config "p/ci" --config "p/sql-injection" --config "p/java
Testing an Python Codebase:
semgrep --config "p/ci" --config "p/gitlab-bandit" --config "p/trailofbits" --config "p/python" --config "p/django" --config "p/flask"
Testing an PHP Codebase:
semgrep --config "p/ci" --config "p/phpcs-security-audit"
Testing an Go Codebase:
semgrep --config "p/ci" --config "p/semgrep-go" --config "trailofbits" --config "golang"
Testing an Ruby Codebase:
semgrep --config "p/ci" --config "ruby"
Testing a C Codebase:
Testing a C++ Codebase:
Making Rules¶
Simple Rules¶
Match Inside Function:
def $FUNC(...):
...
requests.$METHOD(...)
Match Variable used later:
$FD = open($FILENAME, 'r', ...)
...
$FD.$METHOD(...)
Match Arguments:
open($FILENAME, $RW, ...)
requests.get("...", timeout=$SEC, verify=True)
Advanced Rules¶
Semgrep OR:
rules:
- id: use-string-equals
message: In Java, do not use == with strings. Use String.equals() instead.
pattern-either:
- pattern: if ($X == "...") ...
- pattern: if ("..." == $X) ...
Semgrep Limit Match:
rules:
- id: subprocess-call
patterns:
- pattern: subprocess.call(...)
# This says never match if first argument is a string
- pattern-not: subprocess.call("...", ...)
Check Pattern within Pattern:
rules:
- id: http-responsewriter-write
patterns:
- pattern-inside: |
func $FUNC(...) {
...
}
- pattern: $WRITER.Write(...)
Check Pattern that does not have line:
rules:
- id: secure-flag-not-set
patterns:
- pattern: $RESPONSE.addCookie($COOKIE);
- pattern-not-inside: |
$COOKIE.setSecure(true);
...
Source Sync Rules¶
Sample Source and Sync Taint:
rules:
- id: tmw24-net-http-path-traversal-taint
message: Path Traversal Vulnerability
severity: ERROR
languages:
- go
mode: taint
pattern-sources:
- patterns:
- pattern: $REQ.$FIELD
- metavarable-type:
metavarable: $REQ
type: |
*http.Request
- metavarable-regex:
metavariable: $FIELD
regex: ^(basicAuth|Body|Cookie)
pattern-sinks:
- pattern: os.Open(...)
Sample Source and Sync Taint with Sanitizers:
rules:
- id: tmw24-express-taint
message: Express XSS Vuln
severity: ERROR
languages:
- javascript
mode: taint
pattern-sources:
- patterns:
- pattern: |
$APP.$METHOD($PATH, function($REQ, $RES)) {
...
})
- focus-metavariable: $REQ
pattern-sanitizers:
- pattern: cleanXSS(...)
- pattern: path.basename(...)
pattern-sinks:
- pattern: res.sendFile(...)
- pattern: res.write(...)
Taint with Propagators:
rules:
- id: tmw24-formated sqlstring
message: Java SQL injection Vuln
severity: ERROR
languages:
- java
mode: taint
pattern-sources:
- pattern: (HttpServletRequest $REQ)
pattern-propagators:
- pattern: (myStringList $S).append($X)
from: $X
to: $S
pattern-sinks:
- patterns:
- pattern: $Q.$SQLQUERY(...)
- metavarable-regex:
metavarible: $SQLQUERY
regex: execute|execureQuery
Taint with labels:
rules:
- id: tm24-ruameL-deseriauzation-probIem
message: "Insecure deserialization (catted pickling in pytnon) is when
user-controllable data Is deseriaUzed by an application. "
severity: ERROR
languages:
- python
mode: taint
pattern-sources:
- label: USER_INPUT
pattern: self-path
- label: TYP_UNSAFE
pattern: ruyaml.yaml.YAML(..., typ="unsafe", ...)
- label: TOOO
pattern: TOOO
pattern-sinks:
- requires: USER_INPUT and TYP_UNSAFE
pattern: $YML.load(...)
Language Rules¶
Solidity Rules
C Rules
Mobile Rules
XSS Rules
Android Rules
Android Rules
Mobile Rules
PHP¶
Example Rule:
rules:
- id: test
languages:
- php
severity: ERROR
message: test
patterns:
- pattern-inside: |
function $FUNC(...,$PAR,...) {
...
}
- pattern: $AAAA . <... $PAR ...> . $BBBB;
Check for name of varable matches regex:
rules:
- id: use-decimalfield-for-money
patterns:
- pattern-inside: |
class $M(...):
...
- pattern: $F = django.db.models.FloatField(...)
- metavariable-regex:
metavariable: '$F'
regex: '.*(price|fee|salary).*'
message: Found a FloatField used for variable $F. Use DecimalField for currency fields to avoid float-rounding errors.
languages: [python]
severity: ERROR
Inverse Regex Match:
rules:
- id: invalid-base-url
message:
The 'baseURL' is invalid. This may cause links to not work if deployed. Include the scheme (e.g., https://).
patterns:
- pattern: baseURL = "..."
- pattern-not-regex: http(s)?://.*
languages: [generic]
Integer Condition:
rules:
- id: use-of-weak-rsa-key
message: RSA keys should be at least 2048 bits based on NIST recommendation.
patterns:
- pattern: |
KeyPairGenerator $KEY = $G.getInstance("RSA");
...
$KEY.initialize($BITS);
- metavariable-comparison:
comparison: $BITS < 2048
metavariable: $BITS
languages: [java]
severity: WARNING
Whitelist Options for variables:
rules:
- id: disallow-old-tls-versions2
message: Detected an old tls version
patterns:
- pattern: |
$CONST = require('crypto');
...
$OPTIONS = $OPTS;
...
https.createServer($OPTIONS, ...);
- metavariable-pattern:
metavariable: $OPTS
patterns:
- pattern-not: >
{secureOptions: $CONST.SSL_OP_NO_SSLv2 | $CONST.SSL_OP_NO_SSLv3
| $CONST.SSL_OP_NO_TLSv1}
languages:
- javascript
severity: WARNING
Make a Fix to the code:
rules:
- id: use-sys-exit
pattern: exit($X)
message: |
Use "sys.exit" over the python shell "exit" built-in. "exit" is not available on all Python implementations.
languages: [python]
severity: WARNING
fix: sys.exit($X)
Multi Pattern Match:
rules:
- id: user-eval
patterns:
- pattern-inside: |
def $F(...):
...
- pattern-either:
- pattern: eval(..., request.$W.get(...), ...)
- pattern: |
$V = request.$W.get(...)
...
eval(..., $V, ...)
- pattern: eval(..., request.$W(...), ...)
- pattern: |
$V = request.$W(...)
...
eval(..., $V, ...)
- pattern: eval(..., request.$W[...], ...)
- pattern: |
$V = request.$W[...]
...
eval(..., $V, ...)