elastic / elastic/detection-rules

[New Rule] Potential Webshell Command Execution via URL Query Parameter

Open
#6,596 3 comments 0 reactions 0 assignees View on GitHub
community
Dominant language
Python
Stars
2.7k
Forks
696
Avg merge
4d 17h
Merged PRs (30d)
87

Description

## Description

Detects an HTTP request to a webshell-extension URL (`.php`, `.jsp`, `.asp`, and variants) whose query string contains a `cmd=`/`exec=`/`shell=` parameter, the standard interaction pattern for simple webshells, which typically execute the value of a query parameter as an OS command.

Checked for overlap before proposing: Elastic's existing `initial_access_file_upload_followed_by_get_request` rule detects the drop-and-first-access sequence, but not this *interaction* pattern specifically. This rule fires on every subsequent command an attacker issues through an already-dropped webshell, including ones dropped before that rule's lookback window, or where the drop itself wasn't observed/ingested. Ported from and generalized beyond Splunk `security_content`'s equivalent JSP-specific detection to cover the common webshell extension family.

**Behavior-based** (an interaction pattern), not IOC-based.

**Real testing performed**: stood up a real `nginx` + `php-fpm` stack with a genuine one-line webshell (``), issued a real `GET /shell.php?cmd=id` request (received the real command output, `uid=33(www-data)...`, confirming actual code execution), captured via a real Packetbeat HTTP module instance. As a negative control, a real `GET /shell.php?id=5` request (a benign-looking query parameter *not* named `cmd`/`exec`/`shell`) was also captured; it does not match, confirming the rule isn't simply "any query string on this extension."

## Target Ruleset
network

## Target Rule Type
Custom (KQL or Lucene)

## Tested ECS Version
Validated against `logs-network_traffic.http-*` (`url.extension`, `url.query`) via a real Packetbeat 9.4.0 HTTP-module capture, indexed and queried directly (not reshaped, this is genuine Packetbeat-native telemetry).

## Query

```kql
url.extension: ("asp" or "aspx" or "jsp" or "jspx" or "phar" or "php" or "php5" or "php7" or "pht" or "phtml") and
url.query: (
(*cmd=* or *exec=* or *shell=*) and
(*%20* or *%2B* or *%2F* or *%3B* or *%7C* or *curl* or *passwd* or *uname* or *wget* or *whoami*)
)
```

## New fields required in ECS/data sources for this rule?
None. Uses standard `url.extension`/`url.query` ECS fields already populated by Packetbeat's HTTP module.

## Related issues or PRs
None yet. Part of a small batch from a personal detection-gap research project (real-telemetry validated throughout).

## References
- https://attack.mitre.org/techniques/T1505/003/
- https://github.com/splunk/security_content

## Redacted Example Data

True positive (real Packetbeat HTTP-module capture of an actual webshell command execution):
```json
{
"url": {
"full": "http://example-app.internal/shell.php?cmd=cat%20%2Fetc%2Fpasswd",
"path": "/shell.php",
"extension": "php",
"query": "cmd=cat%20%2Fetc%2Fpasswd"
},
"http": {
"request": { "method": "GET" },
"response": { "status_code": 200 }
}
}
```

Negative control (real, same endpoint, an unrelated query parameter; does not match):
```json
{
"url": {
"full": "http://example-app.internal/shell.php?id=5",
"path": "/shell.php",
"extension": "php",
"query": "id=5"
},
"http": {
"request": { "method": "GET" },
"response": { "status_code": 200 }
}
}
```

Contributor guide

Open the contributing guide

Research direction

Start with the network ruleset and compare existing custom KQL detection rules before adding this query. Validate the rule against the supplied positive Packetbeat example and confirm the shell.php?id=5 negative control does not match; done means the webshell command pattern is represented without requiring new ECS fields.

Written by the indexing model from the issue text.

Assessment

Domain
networking, security
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.