Skip to content
Merged
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
23 changes: 23 additions & 0 deletions regex-assembly/932390.ra
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.

##! Detect shell fork bomb patterns.
##! A fork bomb defines a function whose body recursively calls itself
##! via a pipe or background operator, causing exponential process
##! creation. The structural pattern is:
##! <name>() { <name call> <| or &> <name call> <optional &> }; <name call>
##!
##! The function name can be any identifier including special bash
##! builtins like : (colon) or . (dot).
##!
##! Either pipe (|) or background (&) is sufficient for a fork bomb:
##! :(){ :|:& };: — classic (pipe + background)
##! f(){ f & f; };f — background only
##! f(){ f() | f(); };f — pipe with explicit calls
##! f(){ f() & f(); };f — background with explicit calls

##! Function name: word chars plus : and . (bash builtins)
##!> define func-name [\w:.]+

##! Match: name() { ... (| or &) ... }
{{func-name}}\s*\(\s*\)\s*\{[^}]+[|&][^}]+\}
41 changes: 41 additions & 0 deletions rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf
Original file line number Diff line number Diff line change
Expand Up @@ -1796,6 +1796,47 @@ SecRule REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer "@pmFromFile unix-she
setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\
setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'"

# [ Shell fork bomb detection ]
#
# This rule detects shell fork bomb patterns, where a function is defined
# whose body recursively calls itself via pipe and / or background process,
# causing exponential process creation that exhausts system resources.
#
# Examples:
# :(){ :|:& };:
# f(){ f|f& };f
# test() { test | test & }; test
#
# The detection targets the structural pattern:
# <name>() { <name call> <| or &> <name call> <optional &> }; <name call>
# where <name> can be any identifier including bash builtins like : or .
#
# Regular expression generated from regex-assembly/932390.ra.
# To update the regular expression run the following shell script
# (consult https://coreruleset.org/docs/development/regex_assembly/ for details):
# crs-toolchain regex update 932390
#
SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_HEADERS|!REQUEST_HEADERS:Cookie|ARGS_NAMES|ARGS|XML:/* "@rx [\.0-:A-Z_a-z]+[\s\x0b]*\([\s\x0b]*\)[\s\x0b]*\{[^\}]+[&\|][^\}]+\}" \
"id:932390,\
phase:2,\
block,\
capture,\
t:none,t:urlDecodeUni,\
msg:'Remote Command Execution: Shell Fork Bomb',\
logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\
tag:'application-multi',\
tag:'language-shell',\
tag:'platform-unix',\
tag:'attack-rce',\
tag:'paranoia-level/2',\
tag:'OWASP_CRS',\
tag:'OWASP_CRS/ATTACK-RCE',\
tag:'capec/1000/152/248/88',\
ver:'OWASP_CRS/4.25.0-dev',\
severity:'CRITICAL',\
setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\
setvar:'tx.inbound_anomaly_score_pl2=+%{tx.critical_anomaly_score}'"


SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:932015,phase:1,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0-dev',skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE"
SecRule TX:DETECTION_PARANOIA_LEVEL "@lt 3" "id:932016,phase:2,pass,nolog,tag:'OWASP_CRS',ver:'OWASP_CRS/4.25.0-dev',skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE"
Expand Down
274 changes: 274 additions & 0 deletions tests/regression/tests/REQUEST-932-APPLICATION-ATTACK-RCE/932390.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
---
meta:
author: "fzipitria"
description: "Shell fork bomb detection"
rule_id: 932390
tests:
- test_id: 1
desc: "classic fork bomb with colon function name"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Accept: "*/*"
Host: localhost
User-Agent: "OWASP CRS test agent"
method: POST
port: 80
uri: /
data: "cmd=%3A%28%29%7B+%3A%7C%3A%26+%7D%3B%3A"
version: "HTTP/1.1"
output:
log:
expect_ids: [932390]
- test_id: 2
desc: "fork bomb with single letter function name"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Accept: "*/*"
Host: localhost
User-Agent: "OWASP CRS test agent"
method: POST
port: 80
uri: /
data: "cmd=f%28%29%7B+f%7Cf%26+%7D%3Bf"
version: "HTTP/1.1"
output:
log:
expect_ids: [932390]
- test_id: 3
desc: "fork bomb with word function name and spaces"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Accept: "*/*"
Host: localhost
User-Agent: "OWASP CRS test agent"
method: POST
port: 80
uri: /
data: "cmd=test%28%29+%7B+test+%7C+test+%26+%7D+test"
version: "HTTP/1.1"
output:
log:
expect_ids: [932390]
- test_id: 4
desc: "fork bomb with dot function name (bash source builtin)"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Accept: "*/*"
Host: localhost
User-Agent: "OWASP CRS test agent"
method: POST
port: 80
uri: /
data: "cmd=.%28%29%7B+.%7C.%26+%7D%3B."
version: "HTTP/1.1"
output:
log:
expect_ids: [932390]
- test_id: 5
desc: "fork bomb with no spaces (compact form)"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Accept: "*/*"
Host: localhost
User-Agent: "OWASP CRS test agent"
method: POST
port: 80
uri: /
data: "cmd=%3A%28%29%7B%3A%7C%3A%26%7D%3B%3A"
version: "HTTP/1.1"
output:
log:
expect_ids: [932390]
- test_id: 6
desc: "fork bomb in query string via GET"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Accept: "*/*"
Host: localhost
User-Agent: "OWASP CRS test agent"
method: GET
port: 80
uri: "/get?cmd=%3A%28%29%7B+%3A%7C%3A%26+%7D%3B%3A"
version: "HTTP/1.1"
output:
log:
expect_ids: [932390]
- test_id: 7
desc: "fork bomb preceded by command separator"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Accept: "*/*"
Host: localhost
User-Agent: "OWASP CRS test agent"
method: POST
port: 80
uri: /
data: "cmd=%3B+test%28%29+%7B+test+%7C+test+%26+%7D+test"
version: "HTTP/1.1"
output:
log:
expect_ids: [932390]
- test_id: 8
desc: "fork bomb with longer function name"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Accept: "*/*"
Host: localhost
User-Agent: "OWASP CRS test agent"
method: POST
port: 80
uri: /
data: "cmd=myfunc%28%29%7B+myfunc%7Cmyfunc%26+%7D%3Bmyfunc"
version: "HTTP/1.1"
output:
log:
expect_ids: [932390]
- test_id: 9
desc: "fork bomb in Referer header"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Accept: "*/*"
Host: localhost
User-Agent: "OWASP CRS test agent"
Referer: ":(){ :|:& };:"
method: GET
port: 80
uri: /
version: "HTTP/1.1"
output:
log:
expect_ids: [932390]
- test_id: 10
desc: "fork bomb in User-Agent header"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Accept: "*/*"
Host: localhost
User-Agent: "f(){ f|f& };f"
method: GET
port: 80
uri: /
version: "HTTP/1.1"
output:
log:
expect_ids: [932390]
- test_id: 11
desc: "fork bomb with background only, no pipe"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Accept: "*/*"
Host: localhost
User-Agent: "OWASP CRS test agent"
method: POST
port: 80
uri: /
data: "cmd=f%28%29%7B+f+%26+f%3B+%7D%3Bf"
version: "HTTP/1.1"
output:
log:
expect_ids: [932390]
- test_id: 12
desc: "fork bomb with explicit recursive calls using pipe"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Accept: "*/*"
Host: localhost
User-Agent: "OWASP CRS test agent"
method: POST
port: 80
uri: /
data: "cmd=f%28%29%7B+f%28%29+%7C+f%28%29%3B+%7D%3B+f"
version: "HTTP/1.1"
output:
log:
expect_ids: [932390]
- test_id: 13
desc: "fork bomb with explicit recursive calls using background"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Accept: "*/*"
Host: localhost
User-Agent: "OWASP CRS test agent"
method: POST
port: 80
uri: /
data: "cmd=f%28%29%7B+f%28%29+%26+f%28%29%3B+%7D%3B+f"
version: "HTTP/1.1"
output:
log:
expect_ids: [932390]
- test_id: 14
desc: "negative test - normal parentheses in value"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Accept: "*/*"
Host: localhost
User-Agent: "OWASP CRS test agent"
method: GET
port: 80
uri: "/get?q=hello+world+(test)"
version: "HTTP/1.1"
output:
log:
no_expect_ids: [932390]
- test_id: 15
desc: "negative test - normal function-like syntax without pipe and background"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Accept: "*/*"
Host: localhost
User-Agent: "OWASP CRS test agent"
method: POST
port: 80
uri: /
data: "code=myfunction%28%29%7B+echo+hello+%7D"
version: "HTTP/1.1"
output:
log:
no_expect_ids: [932390]
- test_id: 16
desc: "negative test - normal URL with colon"
stages:
- input:
dest_addr: 127.0.0.1
headers:
Accept: "*/*"
Host: localhost
User-Agent: "OWASP CRS test agent"
method: GET
port: 80
uri: "/get?url=http%3A%2F%2Fexample.com%3A8080%2Fpath"
version: "HTTP/1.1"
output:
log:
no_expect_ids: [932390]
Loading