elastic / elastic/detection-rules
[Rule Tuning] Initial Access via File Upload Followed by GET Request
- Dominant language
- Python
- Stars
- 2.7k
- Forks
- 696
- Avg merge
- 4d 17h
- Merged PRs (30d)
- 87
Description
## Link to Rule
https://github.com/elastic/detection-rules/blob/main/rules/cross-platform/initial_access_file_upload_followed_by_get_request.toml
## Rule Tuning Type
False Negatives - Enhancing detection of true threats that were previously missed.
## Description
This rule ("Initial Access via File Upload Followed by GET Request") currently scopes its `file.extension`/`url.extension` webshell-extension list to `("php", "phtml", "pht", "php5", "asp", "aspx", "jsp", "jspx", "war", "cgi")`. This misses three additional real, commonly-abused PHP-family extensions that a web server can be configured to execute exactly like `.php`: **`.phar`** (PHP Archive, executable via `phar://` stream-wrapper/handler mapping), **`.php7`** (an alternate PHP handler extension seen in real PHP 5→7 migration hosting configs), and **`.phps`** (intended as a source-display extension, but on misconfigured servers mapped directly to the PHP handler like `.php`, and a plausible deliberate choice by an attacker trying to blend in).
**Behavior-based**: this is an extension-completeness fix to an existing behavioral pattern (upload-then-access), not a new detection concept.
**Real testing performed, with a real captured 3-way signal**: stood up a real Caddy + php-fpm stack with a real upload handler (`move_uploaded_file`), issued a genuine multipart `POST /upload.php` with `Content-Disposition: form-data; filename="shell.phar"` (an inert placeholder payload), followed by a real `GET /uploads/shell.phar`. Captured three independent real signals for the same flow: Packetbeat's real HTTP body parsing of the `Content-Disposition` header, Auditbeat's real file-creation event (`php-fpm` opening the uploaded file on disk), and Packetbeat's own real ECS URL parsing (`url.extension: "phar"`, populated automatically by Packetbeat, not derived by hand). Repeated the identical flow with a real `legit.jpg` as the false-positive control.
**Validated the literal rule query, both before and after the tuning**: against the current (untuned) extension list, the real `.phar` upload-then-GET sequence produces **zero** matches, confirming this is a genuine gap, not a hypothesized one. Against the tuned list (`+phar, php7, phps`), the same real sequence produces exactly **one** match; the real `.jpg` control matches neither version, confirming the addition introduces no new false positive for ordinary image uploads.
## Example Data
Real captured sequence (Packetbeat HTTP module + Auditbeat file-creation, both genuine, not simulated):
Stage 1, real multipart upload:
```json
{
"http": {
"request": {
"method": "POST",
"body": { "content": "...Content-Disposition: form-data; name=\"file\"; filename=\"shell.phar\"..." }
}
},
"url": { "path": "/upload.php" }
}
```
Stage 2, real file creation on disk (Auditbeat, reshaped into ECS file-event shape):
```json
{
"event": { "category": ["file"], "type": ["creation"] },
"process": { "name": "php-fpm" },
"file": { "name": "shell.phar", "path": "/var/www/html/uploads/shell.phar", "extension": "phar" }
}
```
Stage 3, real subsequent GET (Packetbeat's own ECS URL parsing, not hand-derived):
```json
{
"http": { "request": { "method": "GET" } },
"url": { "path": "/uploads/shell.phar", "extension": "phar" }
}
```
Real negative control (identical flow, a real `.jpg` upload; matches neither the current nor the tuned rule):
```json
{ "url": { "path": "/uploads/legit.jpg", "extension": "jpg" } }
```
Proposed extension list addition (both occurrences in the rule, `file.extension` and `url.extension`):
```eql
("php", "phtml", "pht", "php5", "php7", "phps", "phar", "asp", "aspx", "jsp", "jspx", "war", "cgi")
```
Contributor guide
Research direction
Open rules/cross-platform/initial_access_file_upload_followed_by_get_request.toml and inspect the two extension lists for file.extension and url.extension. Add phar, php7, and phps to both occurrences, then validate the literal rule query against the described phar upload-then-GET sequence and the jpg negative control.
Written by the indexing model from the issue text.
Assessment
- Domain
- security
- Issue type
- Bug
- Difficulty
- 1/5
- Estimated time
- Under an hour
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100