match the shodan-style mmh3 favicon hash of the response body; signed or unsigned 32-bit values both accepted. validated at parse time.
7.9 KiB
writing sif modules
sif modules are yaml files that define security checks. they're similar to nuclei templates but designed specifically for sif.
module locations
- built-in:
modules/directory in the sif installation - user-defined:
~/.config/sif/modules/(linux/macos) or%LOCALAPPDATA%\sif\modules\(windows)
user modules can override built-in modules with the same id.
basic structure
id: unique-module-id
info:
name: human readable name
author: your-name
severity: low|medium|high|critical|info
description: what this module checks for
tags: [tag1, tag2, tag3]
type: http
http:
method: GET
paths:
- "{{BaseURL}}/path"
matchers:
- type: status
status:
- 200
fields
id (required)
unique identifier for the module. use lowercase with hyphens.
id: sqli-error-based
info (required)
metadata about the module.
info:
name: SQL Injection Detection
author: sif
severity: high
description: detects sql injection via error messages
tags: [sqli, injection, owasp-top10]
severity levels:
info- informational findinglow- minor issuemedium- moderate security concernhigh- serious vulnerabilitycritical- critical security flaw
type (required)
module type. currently only http is supported.
type: http
http
http request configuration.
method
http method to use.
http:
method: GET
supported: GET, POST, PUT, DELETE, HEAD, OPTIONS
paths
urls to check. use {{BaseURL}} as placeholder for the target.
http:
paths:
- "{{BaseURL}}/.git/HEAD"
- "{{BaseURL}}/.git/config"
- "{{BaseURL}}/admin"
payloads
values to inject into paths. use {{payload}} as placeholder.
http:
paths:
- "{{BaseURL}}/?id={{payload}}"
payloads:
- "'"
- "1' OR '1'='1"
- "1; DROP TABLE--"
each payload creates a separate request for each path.
attack
how paths and payloads combine into requests.
http:
attack: pitchfork
clusterbomb(default) - every path is tried with every payloadpitchfork- path and payload are paired by index, stopping at the shorter list
headers
custom headers to send.
http:
headers:
User-Agent: "Mozilla/5.0"
X-Custom-Header: "value"
body
request body for POST/PUT requests.
http:
method: POST
body: '{"username": "admin", "password": "{{payload}}"}'
threads
concurrent requests (default: 10).
http:
threads: 5
matchers
matchers determine if a response indicates a finding.
status matcher
match http status codes.
matchers:
- type: status
status:
- 200
- 301
- 302
word matcher
match words in response.
matchers:
- type: word
part: body
words:
- "admin"
- "login"
condition: or
parts:
body- response bodyheader- response headers
conditions:
or- match any word (default)and- match all words
regex matcher
match regex patterns.
matchers:
- type: regex
part: body
regex:
- "SQL syntax.*MySQL"
- "ORA-[0-9]+"
- "PostgreSQL.*ERROR"
condition: or
size matcher
match the response body length in bytes (measured after the 5 MB response cap, so larger sizes never match).
matchers:
- type: size
size:
- 0
- 1337
favicon matcher
match the shodan-style mmh3 hash of the response body. point the module at a favicon and list the hashes of the tech you want to fingerprint.
http:
paths:
- "{{BaseURL}}/favicon.ico"
matchers:
- type: status
status:
- 200
- type: favicon
hash:
- -235701012 # jenkins
- 1278322581 # grafana
the hash is shodan's http.favicon.hash value. paste it signed or unsigned;
both 32-bit forms are accepted, so values from shodan or any favicon-hash tool
drop in without conversion. pair it with a status: 200 matcher so an error
page served for /favicon.ico is not hashed. a finding fires when the body
hashes to any listed value.
combining matchers
multiple matchers are combined with AND logic by default.
matchers:
- type: status
status:
- 200
- type: word
part: body
words:
- "ref: refs/"
condition: or
this matches responses with status 200 AND containing "ref: refs/".
to require any matcher instead of all, set matchers-condition: or on the http
block; the module then reports a finding when any one matcher matches.
http:
matchers-condition: or
matchers:
- type: status
status:
- 401
- type: status
status:
- 403
this matches a 401 OR a 403 response. matchers-condition accepts and (the
default) or or; any other value fails at load.
extractors
extractors pull data from responses.
regex extractor
extractors:
- type: regex
name: version
part: body
regex:
- "version[\"']?\\s*[:=]\\s*[\"']?([0-9.]+)"
group: 1
group: capture group to extract (0 = full match, 1+ = groups)
kv extractor
record every response header as a key-value pair, namespaced by name.
extractors:
- type: kv
name: headers
part: header
json extractor
extract values from a json body by gjson path (github.com/tidwall/gjson); the first path that exists is stored under name.
extractors:
- type: json
name: version
part: body
json:
- "version"
- "data.version"
examples
exposed git repository
id: git-exposed
info:
name: exposed git repository
author: sif
severity: high
description: detects exposed .git directories
tags: [git, exposure, source-code]
type: http
http:
method: GET
paths:
- "{{BaseURL}}/.git/HEAD"
- "{{BaseURL}}/.git/config"
matchers:
- type: word
part: body
words:
- "ref: refs/"
- "[core]"
condition: or
- type: status
status:
- 200
extractors:
- type: regex
name: branch
part: body
regex:
- "ref: refs/heads/(.+)"
group: 1
sql injection detection
id: sqli-error-based
info:
name: sql injection (error-based)
author: sif
severity: high
description: detects sql injection via database errors
tags: [sqli, injection, database]
type: http
http:
method: GET
paths:
- "{{BaseURL}}/?id={{payload}}"
- "{{BaseURL}}/search?q={{payload}}"
payloads:
- "'"
- "1' OR '1'='1"
- "1; SELECT * FROM--"
threads: 10
matchers:
- type: regex
part: body
regex:
- "SQL syntax.*MySQL"
- "ORA-[0-9]+"
- "PostgreSQL.*ERROR"
- "Microsoft SQL Server"
condition: or
security headers check
id: security-headers
info:
name: security headers analysis
author: sif
severity: info
description: checks for missing security headers
tags: [headers, security, info]
type: http
http:
method: GET
paths:
- "{{BaseURL}}/"
matchers:
- type: status
status:
- 200
extractors:
- type: kv
name: headers
part: header
tips
-
use specific paths - don't just check
/, be specific about what you're looking for -
combine matchers - use status + content matchers together to reduce false positives
-
limit payloads - too many payloads slow down scans, pick the most effective ones
-
tag properly - use consistent tags so modules can be filtered with
-mt -
test locally - run your module against a test target before sharing
running modules
# list all modules
./sif -lm
# run specific module
./sif -u https://example.com -m git-exposed
# run multiple modules
./sif -u https://example.com -m git-exposed,sqli-error-based
# run by tag
./sif -u https://example.com -mt owasp-top10
# run all modules
./sif -u https://example.com -am