RCE-Erkennungs- und Bestätigungs-Toolkit, das URLs oder erfasste HTTP-Anfragen auf Command Injection, SSTI, blinde und OOB-Pfade testet und abgestufte Urteile mit Beweis liefert.
confirmed bedeutet, dass das Ziel die Eingabe ausgeführt hat. negative bedeutet, dass die Sonden es erreicht haben.
Version 2.40.0 · MIT · Python 3.8+ · keine Drittanbieter-Abhängigkeiten
RCEKit ist ein RCE-Erkennungs- & -Bestätigungs-Toolkit für autorisiertes Penetration- Testing, Red Teaming und Sicherheitsforschung. Richte es auf ein Ziel, das du testen darfst — eine URL oder eine aufgezeichnete HTTP-Anfrage — und jeder Fund kommt mit der Stufe zurück, die er verdient hat.
Jedes confirmed stützt sich auf einen Wert, den RCEKit für diese Sonde zufällig generiert hat und
den eine Reflexion nicht erzeugen kann: ein berechnetes Ergebnis, das in der Antwort vorhanden und
in einer nutzlastfreien Kontrolle abwesend ist, oder ein Out-of-Band-Callback, der ein Token trägt,
das nur das Ziel jemals besaß. Schwächere Signale behalten ihre eigenen Stufen und werden niemals
dorthin befördert. Und ein Lauf, der etwas nicht testen konnte, meldet es niemals als sauber.
RCEKit bestätigt RCE durch mehrere Methoden unter einer CLI. Unten wird es auf echte, öffentlich dokumentierte CVEs in Produktionssoftware gerichtet — jedes Urteil gegen eine nutzlastfreie Kontrolle differenziert:
| RCE-Klasse | --methods | Realwelt-Ziel | Urteil |
|---|
| OS-Befehlsinjektion (ergebnisbasiert) | reflected | Webmin 1.910 — CVE-2019-15107 | confirmed |
| Ausdrucksinjektion (OGNL) | eval | Apache Struts2 — S2-001 | confirmed |
| Ausdrucks-Lookup (Log4Shell/JNDI) | lookup | Apache Solr 8.11.0 (Log4j 2.14.1) — CVE-2021-44228 | lookup-sink |
| Blinde Befehlsinjektion (keine Ausgabe) | time | Webmin 1.910 — CVE-2019-15107 | needs-review |
Jede Zeile wird von tests/bench/ reproduziert, das RCEKit
gegen diese Builds unter Docker ausführt und das Urteil und seine Negativkontrolle
prüft. Letzter Lauf grün bei 2.36.0 (2026-09-20): 3/3 Fälle. Das ist eine
zeitpunktbezogene Aussage, keine kontinuierliche -- der Benchmark wird in einem Rhythmus
ausgeführt, nicht bei jeder Änderung.
Jede Kontrolle ist der echte Test der Zeile. Struts2 mit reflected sondiert kommt
negative zurück, weil S2-001 OGNL neu auswertet und keine Shell dahinter steht.
Webmins time-Signal wird bei needs-review gehalten auf einem Ziel, wo es zufällig
richtig ist. Und Solr mit oob sondiert kommt negative zurück, obwohl es
ausnutzbar ist -- oob baut Shell-Befehle und eine ${jndi:...}-Senke führt keinen
davon aus, was die Lücke ist, die lookup zu schließen existiert, gemessen statt
behauptet.
Die Log4Shell-Zeile sagt lookup-sink, nicht confirmed: Was der Callback beweist,
ist, dass die Senke eine URI aufgelöst hat, die RCEKit gewählt hat. RCE zu erreichen
erfordert einen Server, der den Lookup mit einer ladbaren Klasse beantwortet, und bei
der Standard-Risikostufe geht nur jndi:dns:// hinaus -- ein Namens-Lookup, mit keiner
Verbindung darüber hinaus, auf der ein solcher Server antworten könnte.
reflected — OS-Befehlsinjektion, Webmin CVE-2019-15107 → confirmed
eval — OGNL-Ausdrucksinjektion, Apache Struts2 S2-001 → confirmed
lookup-sink
time — blinde Befehlsinjektion, Webmin CVE-2019-15107 → needs-review
RCEKit hat zwei unterstützte Formen, und keine ist ein Fallback für die andere.
Installiere es — pipx hält die CLI in ihrer eigenen Umgebung, was du für
ein Tool statt einer Bibliothek willst:```bash
pipx install rcekit # or: pip install rcekit
rcekit --doctor # confirms the corpus it will run with
**Oder nehmen Sie einfach die eine Datei.** Der Payload-Korpus ist in das Modul
eingebaut, sodass `rcekit.py` für sich allein läuft, ohne dass etwas daneben
liegt — kein Installationsschritt, keine site-packages, nichts, das zurückbleibt.
Auf einer Client-Jump-Box, einem air-gapped Host oder überall dort, wo `pip install`
keine Option ist:```bash
curl -O https://raw.githubusercontent.com/kabiri-labs/rcekit/main/rcekit.py
python rcekit.py --doctor # same corpus, same check, zero installation
Beide führen denselben Code aus und melden dieselben Ergebnisse. Die Arbeit mit einem Checkout ist der dritte Weg und erfordert ebenfalls keine Installation:```bash git clone https://github.com/kabiri-labs/rcekit.git cd rcekit # Python 3.8+, standard library only
Setze einen `FUZZ`-Marker dort, wo deine Eingabe landet (oder wähle einen Parameter mit `-p` bei
Verwendung einer aufgezeichneten Anfrage), und bitte RCEKit, RCE nachzuweisen:```bash
rcekit --acknowledge-consent \
--verify-url "https://target.example/lookup?host=FUZZ" \
--methods reflected,eval
| -s | --server | Server URL (default: http://localhost:8080) |
| -t | --token | API token for authentication |
| -o | --output | Output format: json, table, csv (default: table) |
| -v | --verbose | Enable verbose output |
| -q | --quiet | Suppress non-essential output |
| --no-color | | Disable colored output |
| --timeout | | Request timeout in seconds (default: 30) |
# Alle Schwachstellen auflisten
vulnscan list
# Schwachstellen nach Schweregrad filtern
vulnscan list --severity critical,high
# Ergebnisse als JSON ausgeben
vulnscan list --output json
# Bestimmtes Ziel scannen
vulnscan scan --target https://example.com
# Scan mit benutzerdefinierter Konfiguration ausführen
vulnscan scan --config /path/to/config.yaml
# Authentifizierung mit API-Token
vulnscan list --token YOUR_API_TOKEN
# Verbindung zu entferntem Server herstellen
vulnscan list --server https://vulnscan.example.com:8443
Die Konfigurationsdatei verwendet das YAML-Format:
server:
url: "http://localhost:8080"
token: "your-api-token"
timeout: 30
scan:
targets:
- "https://example.com"
- "https://test.example.org"
severity:
- critical
- high
- medium
exclude:
- "*/admin/*"
- "*/api/internal/*"
output:
format: "table"
color: true
verbose: false
notifications:
email:
enabled: true
smtp_host: "smtp.example.com"
smtp_port: 587
from: "[email protected]"
to:
- "[email protected]"
slack:
enabled: false
webhook_url: "https://hooks.slack.com/services/XXX/YYY/ZZZ"
Alle API-Anfragen erfordern einen gültigen API-Token im Authorization-Header:
Authorization: Bearer YOUR_API_TOKEN
GET /api/v1/vulnerabilitiesGibt eine Liste aller Schwachstellen zurück.
Abfrageparameter:
| Parameter | Typ | Beschreibung |
|---|---|---|
severity | string | Nach Schweregrad filtern (kommagetrennt) |
status | string | Nach Status filtern (open, fixed, ignored) |
target | string | Nach Ziel-URL filtern |
page | integer | Seitennummer (Standard: 1) |
limit | integer | Ergebnisse pro Seite (Standard: 50, max: 100) |
Beispielanfrage:
curl -X GET "http://localhost:8080/api/v1/vulnerabilities?severity=critical&limit=10" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Beispielantwort:
{
"data": [
{
"id": "vuln-001",
"title": "SQL Injection in Login Form",
"severity": "critical",
"status": "open",
"target": "https://example.com/login",
"cve": "CVE-2024-1234",
"discovered_at": "2024-01-15T10:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 1,
"pages": 1
}
}
POST /api/v1/scansStartet einen neuen Scan.
Anfragekörper:
{
"target": "https://example.com",
"profile": "full",
"options": {
"depth": 3,
"timeout": 60,
"follow_redirects": true
}
}
Beispielantwort:
{
"scan_id": "scan-abc123",
"status": "running",
"target": "https://example.com",
"started_at": "2024-01-15T10:30:00Z"
}
GET /api/v1/scans/{scan_id}Ruft den Status eines bestimmten Scans ab.
Beispielantwort:
{
"scan_id": "scan-abc123",
"status": "completed",
"target": "https://example.com",
"started_at": "2024-01-15T10:30:00Z",
"completed_at": "2024-01-15T10:35:00Z",
"vulnerabilities_found": 5,
"summary": {
"critical": 1,
"high": 2,
"medium": 1,
"low": 1
}
}
DELETE /api/v1/scans/{scan_id}Bricht einen laufenden Scan ab oder löscht einen abgeschlossenen Scan.``` [detect] methods: reflected, eval [detect] sent 13 probes: confirmed=4, negative=9
[detect] CONFIRMED execution (4): [reflected/unix/raw] ; echo RKYZRIP$((540141+314681))RKFWVFS$(echo RKBWOOC)RKYZRIP (target computed 'RKYZRIP854822RKFWVFSRKBWOOCRKYZRIP' — random operands, absent from control)
### Aus einer aufgezeichneten Anfrage — die Form, die die meisten realen Ziele haben
Eine `--verify-url` trägt eine URL und sonst nichts. Die meisten Sinks, die es wert sind, getestet zu werden, sitzen hinter einem POST mit einem Session-Cookie, einem Content-Type und einem Body, und RCEKit nimmt diese Anfrage als Ganzes: Speichere sie aus deinem Proxy oder den DevTools deines Browsers und benenne das Feld, in das injiziert werden soll.```bash
rcekit --acknowledge-consent \
-r search.req -p q \
--methods reflected,eval
| -s | --server | Server URL (default: http://localhost:8080) |
| -t | --token | Authentication token |
| -o | --output | Output file path |
| -v | --verbose | Enable verbose logging |
| -q | --quiet | Suppress non-error output |
| -f | --format | Output format: json, yaml, table |
| -c | --config | Path to configuration file |
| -n | --no-color | Disable colored output |
| -h | --help | Show help message |
| -V | --version | Show version information |
| Variable | Description | Default |
|---|---|---|
API_URL | Base URL for the API | http://localhost:8080 |
API_TOKEN | Bearer token for authentication | (none) |
LOG_LEVEL | Logging verbosity (debug, info, warn, error) | info |
OUTPUT_FORMAT | Default output format | table |
TIMEOUT | Request timeout in seconds | 30 |
CONFIG_PATH | Path to the configuration file | ~/.config/tool/config.yaml |
The tool reads configuration from a YAML file. Example:
server:
url: "http://localhost:8080"
timeout: 30
auth:
token: "your-token-here"
output:
format: "json"
color: true
logging:
level: "info"
file: "/var/log/tool.log"
Basic usage:
tool scan --target example.com
With authentication:
tool scan --target example.com --token "your-token"
Output to JSON file:
tool scan --target example.com --format json --output results.json
Using a custom configuration file:
tool scan --config /path/to/config.yaml
Verbose mode with debug logging:
tool scan --target example.com --verbose
| Code | Meaning |
|---|---|
0 | Success |
1 | General error |
2 | Invalid arguments |
3 | Authentication failure |
4 | Network error |
5 | Target not found |
6 | Permission denied |
7 | Configuration error |
Connection refused
Ensure the server is running and accessible:
curl -I http://localhost:8080/health
Authentication failed
Verify your token is valid and not expired. Tokens can be regenerated from the web interface under Settings → API Keys.
Timeout errors
Increase the timeout value in your configuration file or via the TIMEOUT environment variable:
export TIMEOUT=60
tool scan --target example.com
Permission denied
Some operations require elevated privileges. Run with sudo if necessary, or ensure your user has the appropriate permissions.
We welcome contributions from the community. Please follow these guidelines:
git checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)Please ensure your code adheres to the existing style and includes appropriate tests.
This project is licensed under the MIT License. See the LICENSE file for details.
[detect] CONFIRMED execution (3): [reflected/unix/raw] ; echo RKHWNHK$((114157+752773))RKXGFIH$(echo RKHSEIF)RKHWNHK (target computed 'RKHWNHK866930RKXGFIHRKHSEIFRKHWNHK' — random operands, absent from control)
Die Methode, der Pfad, die Header, der Body und die Cookies werden so wiederverwendet, wie sie erfasst wurden, und jeder Wert wird für den Kontext kodiert, in den er gelangt – ein JSON-Blatt, ein Formularfeld und ein Cookie werden nicht auf die gleiche Weise escaped. Lass `-p` weg und markiere die Stelle stattdessen mit `FUZZ` oder `*`, wenn dir das lieber ist.
### Alles, was das Tool hat
Zwei Dinge sind nur über eine erfasste Anfrage erreichbar: die **Aufzählung von Injektionspunkten** (`--auto-params`) und jede Senke, die eine Session benötigt. Der umfassendste Lauf, den RCEKit machen kann, startet also von `-r`, nicht von einer URL – was man wissen sollte, bevor man ein Ziel als sauber einstuft.```bash
rcekit --acknowledge-consent \
-r search.req --auto-params all --point-order thorough \
--methods reflected,eval,time,lookup,deser \
--oob-host oob.yourdomain.example --listen-dns-port 53 \
--verify-active-risk stateful --probe-depth full \
--detect-json findings.json
Ihre Zustimmung zur Verarbeitung Ihrer personenbezogenen Daten zum Zwecke der Bereitstellung der Dienste.``` [verify] loaded request from search.req: enumerating 4 injection point(s) [detect] enumerating 4 injection point(s) x 3 method(s) [detect] cost: 4 points x ~1739 probes = at least 6964 requests [detect] body param 'q': confirmed (1544 probes) <-- CONFIRMED [detect] sent 6371 probes: confirmed=446, negative=5925
Was die einzelnen Flags öffnen:
| | |
|---|---|
| `--auto-params all` | jeder Query-Wert, JSON-Leaf, Formularfeld, Multipart-Teil, Cookie und Header, statt eines einzelnen benannten Felds |
| `--point-order thorough` | jeder Nicht-Hop-by-Hop-Header, nicht nur die ertragreichen |
| `--methods ...,lookup,deser` | Expression-Lookup- und Deserialisierungs-Sinks, die die shell-förmigen Methoden nicht erreichen können |
| `--oob-host` | ein Callback-Host für die blinden Methoden. Benötigt eine dir delegierte Domain; Port 53 benötigt root |
| `--verify-active-risk stateful` | die oberste Stufe — fügt die Probe-Formen hinzu, die das Ziel dazu bringen, von einer Adresse abzurufen, die RCEKit nicht gewählt hat |
| `--probe-depth full` | jede Break-out-Form pro Sink, nicht nur die günstigen |
| `--detect-json` | dieselben Urteile als maschinenlesbares JSON |
**Das sind viele Requests.** Die Kostenzeile wird ausgegeben, bevor irgendetwas
abgefeuert wird, und `--max-points` / `--max-payloads` begrenzen sie. Führe es
gegen eine Instanz aus, die du beschädigen darfst: `--verify-active-risk stateful`
ist die Stufe für ein Wegwerf-Ziel, nicht für die Produktion.
Keine externe Infrastruktur, keine Konfigurationsdatei.
**Vertraue den GIFs nicht** — [reproduziere sie selbst](https://github.com/kabiri-labs/rcekit/blob/main/docs/verify-it-yourself.md)
gegen dockerisierte Webmin- und Struts2-Ziele in etwa fünf Minuten.
**Als Nächstes:** der [**Feldguide**](https://github.com/kabiri-labs/rcekit/blob/main/docs/guide.md) führt durch die realen
Situationen — mitgeschnittene Requests, WAFs, gefilterte Separatoren, gequotete
Sinks, blinde und No-Egress-Ziele — jeweils mit einem durchgearbeiteten Beispiel.
---
## Was ein Urteil bedeutet
Einen RCE-*Kandidaten* zu finden ist einfach. Einen zu melden, der einen
Retest durch jemand anderen übersteht, ist der schwierige Teil, und er scheitert
in zwei Richtungen: ein „möglicherweise verwundbar", das sich als Reflection
entpuppt, und ein „nicht verwundbar" aus einem Lauf, der tatsächlich nie
irgendetwas getestet hat.
RCEKit antwortet mit **acht Urteilen, die niemals ineinander kollabiert werden**:
| Urteil | Was es behauptet |
|---|---|
| **`confirmed`** | Das Ziel hat die Eingabe ausgeführt. Es hat einen Wert zurückgegeben, den es anders nicht hätte erzeugen können — berechnet aus Operanden, die für diese Probe zufällig waren — und dieser Wert fehlt in einer payload-freien Kontrolle. |
| **`deserialization-sink`** | Das Ziel hat einen vom Angreifer gelieferten Objektgraphen rekonstruiert. Bewiesen, aber über eine *andere Eigenschaft*: RCE von dort zu erreichen hängt von Classpath-Gadgets ab, weshalb es nie RCE genannt wird. |
| **`lookup-sink`** | Das Ziel hat eine URI aufgelöst, die RCEKit ihm übergeben hat — ein `${jndi:…}`-Ausdruck hat ein Lookup erreicht, bewiesen anhand eines Callbacks, der ein Token trug, das nur diese Probe besaß. Es ist ein Sink, keine Ausführung: RCE von dort zu erreichen erfordert einen Server, der mit einer ladbaren Klasse antwortet. |
| **`needs-review`** | Ein echtes Signal, das für sich genommen kein Beweis ist — eine lineare Timing-Regression, ein Parser-Fingerprint. Deine Zeit wert, niemals das Wort „confirmed" wert. |
| **`inconclusive`** | Der Beweis ist aufgetaucht, konnte aber nicht der Ausführung zugeschrieben werden — die payload-freie Kontrolle trug ihn ebenfalls. |
| **`negative`** | Probes wurden gebaut, haben das Ziel erreicht und nichts gefunden. |
| **`error`** | Nichts hat das Ziel erreicht. |
| **`nothing-tested`** | Es wurden überhaupt keine Probes gebaut. |
In dem Moment, in dem `confirmed` und `maybe` verschwimmen, bedeutet `confirmed`
nichts mehr — also wird niemals etwas nach oben befördert. Eine
Timing-Regression bleibt `needs-review`, so sauber die Steigung auch sein mag.
Ein Deserialisierungs-Callback bleibt `deserialization-sink`, so sicher du auch
bist, dass der Classpath ausnutzbar ist.
### Die andere Hälfte: ein Lauf, der nichts getestet hat, ist niemals sauber
Die letzten beiden Zeilen sind die, die andere Tools nicht haben, und sie sind
wichtiger, als sie aussehen. Ein Scanner, der das Ziel nicht erreichen konnte,
oder der keine Probes gebaut hat, weil deine Flags jede einzelne davon
ausgeschlossen haben, hat **nichts** über das Ziel gelernt — und dort `negative`
auszugeben ist eine Lüge, die sich genau wie Sicherheit liest.
Deshalb sind `error` und `nothing-tested` erstklassige Urteile, der Lauf endet
mit einem Nicht-Null-Exit-Code, und RCEKit sagt, welches von beiden eingetreten
ist und warum:```
[!] No probes were built, so NOTHING WAS TESTED — this is not a negative result.
[!] None of the selected methods (reflected, file) apply to environment(s): sql.
Es schlägt überall dort an, wo ein Lauf still leer werden kann: eine Methode, die nicht auf die ausgewählten Umgebungen zutrifft, eine --sink-shape-Stufe, für die die gewählte Shell keine Syntax hat, eine --bridges-Auswahl, die vollständig von der Sicherheitsobergrenze zurückgehalten wird, ein Request-Body, der die Zustellung brach, bevor er ankam.
Ein Lauf, der nur teilweise blind war, bekommt dieselbe Behandlung eine Ebene tiefer. Wenn du ein Second-Order-Oracle angefordert hast und der beobachtete Endpunkt nie geantwortet hat, gelten die Probe-Verdikte weiterhin — aber der Lauf sagt dir, dass sie entschieden wurden, ohne jemals den Kanal zu lesen, auf den du ihn gerichtet hast, statt sie als Second-Order-Negativ durchgehen zu lassen.
Eine CLI, ein --methods-Flag, das die Hauptpfade zu RCE abdeckt:
| RCE-Klasse | --methods | Wie RCEKit es beweist |
|---|---|---|
| OS-Command-Injection | reflected | Bringt die Shell dazu, $((a+b)) auf zufälligen Operanden zu berechnen und $(echo TAG) zu kollabieren; bestätigt das Ergebnis, niemals den literalen Ausdruck. Geschrieben im eigenen Dialekt des Sinks — POSIX, cmd.exe oder PowerShell. |
Code-/Expression-Injection — SSTI, SpEL, OGNL, Groovy, eval() (CWE-94) | eval | Injiziert a*b in jeder gängigen Template-Syntax (${…} {{…}} #{…} %{…} <%=…%> @(…), bare); bestätigt, dass das Produkt erscheint, während das literale a*b nicht erscheint. |
| Blinde Command-Injection (keine Ausgabe) | time | Feuert eine kontrollierte 0/N/2N-Verzögerungsreihe ab und bestätigt, dass die Antwortzeit der Verzögerung linear folgt; gemeldet als needs-review — Jitter kann es nicht fälschen, aber Timing ist kein berechneter Wert. |
| Interne / No-Egress-Ziele | file | Schreibt ein zufälliges Token und holt es über jeden Read-Back-Pfad zurück — ein Web-Root, ein LFI-Parameter, ein Download- oder Export-Handler, eine /tmp-gestützte Vorschau. Beweist Ausführung plus ein Write-Primitive, ohne externen Listener. |
| Upload-/Write-Primitive — PUT-a-JSP, ungeprüfter Upload (CWE-434) | write | Schreibt einen One-Liner, der ein Produkt durch deinen eigenen Upload-Request berechnet, und holt dann die Datei: das Produkt ist confirmed RCE, der Quellcode, der wortwörtlich zurückkommt, ist needs-review — beliebiges File-Write, ausgeliefert, aber nicht interpretiert. |
| Deserialisierungs-Sinks — fastjson, shiro, weblogic (CWE-502) | deser | Beweist, dass der Endpunkt Angreifer-Daten deserialisiert, über ein nicht-ausführendes DNS-Gadget oder ein Error-Shape-Differential. Gemeldet als , als RCE. |
Drei Dinge erweitern die Reichweite dieser Methoden, ohne zu ändern, was eine von ihnen confirmed nennen wird:
--observe-url) — wenn der Payload in einer Anfrage landet und in einer anderen ausgeführt wird: gespeichertes SSTI, das auf einer Profilseite gerendert wird, ein Payload, der in ein Log geschrieben wird, das eine Template-Engine später rendert, ein eingereihter Job. Der beobachtete Endpunkt wird gegen einen Snapshot differenziert, der vor dem Senden einer jeden Probe aufgenommen wurde.--bridges) — COPY … FROM PROGRAM, xp_cmdshell, expect://. Eine Bridge ist ein Träger, kein Oracle: Sie umhüllt den Befehl, den die Methoden ohnehin bauen, sodass dieselben Stufen durch sie hindurch gelten.-p all) — Query, JSON-Blätter, Formularfelder, Multipart-Teile, Cookies, Header und Pfadsegmente, jeweils kodiert für ihren Landeplatz, mit den vor dem Feuern ausgegebenen Probe-Kosten. Ein GraphQL-Body wird danach geordnet, was tatsächlich bestätigen kann: die variables, die ein Resolver vor dem Operation-Dokument selbst liest.Methoden frei mischen: --methods reflected,eval,time führt alle drei aus und meldet jede Stufe separat.
Ehrlicher Umfang. RCEKit bestätigt RCE, die durch Injection in eine Anfrage erreichbar und von einer Shell oder einem Evaluator interpretiert wird. Es deckt nicht Memory-Corruption-Bugs (Buffer Overflow, UAF) oder Argument-Injection in ein No-Shell-
argv-Array ab — das sind andere Probleme. Deserialisierungs-Gadget-Chains bleiben ebenfalls außerhalb des Umfangs:--methods deserbeweist, dass ein Endpunkt Angreifer-Daten deserialisiert, und sagt es in seiner eigenen Stufe, aber welches Gadget (falls überhaupt eines) das in Ausführung verwandelt, hängt vom Classpath des Ziels ab, und RCEKit beansprucht nicht, das zu wissen. Es zielt darauf ab, in den obigen injection-getriebenen RCE-Klassen exzellent zu sein, statt in allem mittelmäßig.
Die anderen Tools in diesem Bereich sind darauf ausgelegt, dich hineinzubringen. RCEKit ist darauf ausgelegt, dass der Fund der Prüfung durch andere standhält — dem Retest des Kunden, der Triage-Queue, der Report-Review. Dieser Unterschied zeigt sich dreimal.
Du weißt selten die Klasse, bevor du testest. Einen unbekannten Sink mit Single-Class-Tools abzudecken bedeutet, jedes nacheinander auszuführen und die Anfrage für jedes neu zu bauen:
| Bestätigen kann | RCEKit | commix | SSTImap | Nuclei |
|---|---|---|---|---|
| OS-Command-Injection | ✅ | ✅ (sein gesamter Umfang) | — | pro Template |
| Expression-Injection / SSTI | ✅ | über seine eval-basierte Technik | ✅ (sein gesamter Umfang) | pro Template |
| Blind — Timing | ✅ als separate Stufe | ✅ | ✅ | — |
| Blind — Out-of-Band | ✅ eingebauter Listener | — | — | über interactsh |
| No-Egress — schreiben & zurückholen | ✅ jeder Read-Back-Pfad | ✅ (Web-Root) | — | — |
cmd.exe- und PowerShell-Sinks | ✅ pro-Dialekt-Probes | ✅ (cmd) | — | pro Template |
| Upload → Write-then-Execute | ✅ Write vs. Execute, separate Stufen | — | — | pro Template |
| Second-Order — landet hier, läuft dort | ✅ | — | — | — |
| Query-Language-Bridge zum OS | ✅ | — | — | pro Template |
| Deserialisierungs-Sink | ✅ eigene Stufe, niemals RCE genannt | — | — | pro Template |
| Alles oben Genannte, eine CLI, ein Lauf | ✅ | — | — | — |
Abdeckung gemäß der jeweils eigenen dokumentierten Technikliste jedes Projekts. SSTImap ist der gepflegte Nachfolger von tplmap, das sein Autor als unmaintained markiert hat.```bash
python rcekit.py --acknowledge-consent -r request.txt -p host --methods reflected,eval,time
### 2. Es widerspricht seinen eigenen Ergebnissen
Ein Tool berichtet, was es gefunden hat. RCEKit berichtet auch **was es nicht glauben wollte** —
`inconclusive` ist ein eigenes Urteil, für Beweise, die auftauchten, aber nicht der Ausführung zugeordnet werden konnten:```
[detect] methods: reflected, eval
[detect] sent 13 probes: confirmed=0, inconclusive=2, negative=11
Diese beiden wären die Entdeckung von jemand anderem gewesen. Fünf Mechanismen erzeugen dieses Urteil, und sie laufen bei jeder Bestätigung:
inconclusive, keine Entdeckung.$((a+b)); nur die Ausführung liefert den Wert.confirmed bezeichnen wird.Derselbe Instinkt wirkt in die andere Richtung. Timing bestätigt sich niemals selbst, ein Deserialisierungs-Callback wird niemals als RCE bezeichnet, und ein Lauf, der keine Probes erzeugt hat, wird niemals als negativ bezeichnet.
Die Kontrollen, nach denen die Rules of Engagement eines Kunden tatsächlich fragen, im Tool statt in deinen Notizen:
| Consent-Gate | Nichts Exploitatives wird generiert oder ausgelöst ohne --acknowledge-consent. |
| Ausführungsplan | Gibt die exakte Probe-Anzahl, Senken-Formen, Sicherheitsstufen und alle ausgehenden Callback-Ziele vor der ersten Anfrage aus. |
| Standardmäßig sicher | Reverse Shells, Credential-Zugriff, Cloud-Metadaten, laterale Bewegung und Container Escape werden zurückgehalten, bis du --verify-active-risk erhöhst; Persistenz und Backdoors benötigen zusätzlich ein zweites Flag. Bridges, die ein Objekt auf dem Ziel erstellen, unterliegen derselben Obergrenze. |
| Cleanup-Befehle | file, write und die zustandsbehafteten Bridges verändern den Zielzustand, daher gibt jede Entdeckung — einschließlich einer needs-review — aus, was auszuführen ist, um sie rückgängig zu machen. |
| Credentials bleiben an Ort und Stelle | Der file-Read-back-Abruf trägt die Authorization/Cookie-Header des Laufs nur an den gleichen Origin, und sagt es laut, wenn er sie zurückhält. Der Abruf des beobachteten Kanals sendet gar keine, es sei denn, du übergibst ihm eine Anfrage mit --observe-request. |
| Redigierter Audit-Trail | Jeder Lauf landet in exploit_audit.log und zeichnet auf, dass ein Credential-Header gesendet wurde, niemals dessen Wert. |
| Watermarking | --watermark stempelt ein nachverfolgbares Token in jede Nutzlast, sodass eine Nutzlast, die Monate später in den Logs des Kunden gefunden wird, deinem Lauf zugeordnet werden kann. |
| Keine Drittanbieter-Callbacks | Der OOB-Listener gehört dir. Nichts wird über einen öffentlichen Interaction-Server geleitet, was manche Engagements kategorisch verbieten. |
| Eine Stdlib-Datei | rcekit.py läuft allein — Jump Box, air-gapped Host, überall dort, wo pip install keine Option ist. |
Willst du eine Shell statt eines Urteils? commix und SSTImap führen in die
Post-Exploitation weiter; RCEKit stoppt konstruktionsbedingt beim Nachweis. Tausende Hosts
nach bekannten CVEs durchsuchen? Das ist Nucleis Aufgabe — und RCEKit schreibt Nuclei-Templates
(--output-format nuclei), sodass es deinen Scanner speist, statt mit ihm zu konkurrieren.
Weißt du bereits, dass die Injection SQL ist und willst die Datenbank selbst?
sqlmap besitzt dieses Terrain — RCEKits
Bridges existieren, um zu beweisen, dass das OS von einem Textparameter aus erreichbar ist, nicht um
die Datenbank zu exploitieren.
Jede Zeile ist ein durchgearbeitetes Beispiel im Field Guide — der Befehl, was er sendet und wie man liest, was zurückkommt.
| Situation | Gehe zu |
|---|---|
| Ich habe eine URL und einen Parameter | Auf eine URL zeigen |
| Ich habe eine aus Burp gespeicherte Anfrage | Auf eine aufgezeichnete Anfrage zeigen |
| Die App ist JSON / die Nutzlast wird ständig verstümmelt | Die Nutzlast intakt landen |
| Ich weiß nicht, welche Klasse es ist | Methoden auswählen |
Die Senke entfernt ; | Wenn die Senke Separatoren filtert |
Meine Eingabe landet innerhalb von 'quotes' | Innerhalb von Quotes injizieren |
| Die Senke führt meine Eingabe als den gesamten Befehl aus | Ganzbefehl-Senken |
| Das Ziel ist Windows oder die Senke ist PowerShell | Windows- und PowerShell-Senken |
| Es gibt eine WAF | Eine WAF umgehen |
| Es kommt überhaupt keine Ausgabe zurück | Blinde Ziele |
| Keine Ausgabe und kein Egress | Ziele ohne Egress |
| Die Anfrage speichert eine Datei, statt etwas auszuführen | Upload- und Write-Primitive-Ziele |
| Selbst verifizieren | Reproduziere die obigen Bestätigungen auf deiner eigenen Maschine, gegen dockerisierte verwundbare Ziele. Fünf Minuten. |
| Field Guide | Beispielgetriebener Durchlauf durch jede reale Situation, von der ersten Probe bis zu mehrstufigen Ketten. Hier anfangen. |
| Nutzlast-Generierung & Exporte | RCEKit als Nutzlast-Generator: Zielprofile und Burp / ffuf / Nuclei-Exporte. |
| Referenz | Jedes Flag, jede Umgebung, Kategorie, Kontext, Kodierung und Code-Execution-Senke. |
| CHANGELOG.md | Was sich in jeder Version geändert hat und was beim Upgrade erneut geprüft werden sollte. |
| CONTRIBUTING.md | Wie man Senken, Kategorien, Kodierungen und Erkennungsmethoden hinzufügt. |
| SECURITY.md | Melden einer Schwachstelle in RCEKit selbst. |
RCEKit exploitiert, und das ist der Punkt. Eine Schwachstelle wird bestätigt, indem man das Ziel dazu bringt, die Sache zu tun, weil das der einzige Nachweis ist, den eine Signatur nicht fälschen und ein gepatchter Build nicht versehentlich erzeugen kann. Was einen Lauf begrenzt, ist nicht die Zurückhaltung beim Exploitieren. Es sind zwei strukturelle Tatsachen und ein Schalter.
Es nimmt keine beliebige Nutzlast von dir an. Probes werden von der Engine gebaut, um einem Orakel zu dienen — Arithmetik auf Operanden, die für diese Probe zufällig sind, ein Name, den nur dieser Lauf hätte wählen können. Es gibt keine Eingabe, die die Erkennung in etwas anderes verwandelt, weil es keine solche Eingabe gibt, die man geben könnte.
Alles, was über die Berechnung eines Wertes hinausgeht, deklariert die Stufe, die es benötigt,
sodass ein Flag entscheidet, wie weit ein Lauf geht: --verify-active-risk safe | intrusive | stateful. Eine Methode oder eine einzelne Probe-Form oberhalb dieser Stufe wird namentlich zurückgehalten,
mit dem Flag, das sie senden würde — eine Leiter, die still schrumpft, ist nicht von einem Ziel zu unterscheiden, bei dem nichts zu finden ist. Gegen eine Wegwerf-
Instanz erhöhe die Stufe und erhalte alles, was das Tool hat.
--acknowledge-consent; --detection-only ist harmlos und nicht.--verify-active-risk erhöhst. Destruktive Nutzlasten (Persistenz, Backdoors) werden niemals
ohne --verify-allow-destructive ausgelöst. Ein Ausführungsplan gibt exakt aus,
was gesendet wird, bevor irgendetwas ausgelöst wird.safe / intrusive / stateful. Korpus-Nutzlasten werden
durch --max-safety gefiltert; Erkennungsmethoden und ihre Probe-Formen deklarieren
dieselben Sprossen und werden durch --verify-active-risk gefiltert, sodass eine Methode, die
das Ziel dazu bringt, nach außen zu reichen oder etwas zurückzulassen, derselben
Ordnung unterliegt wie jede Korpus-Nutzlast. Der Pre-Flight benennt die Stufe, die jedes zurückgehaltene
Element tatsächlich benötigt. file und write werden stattdessen durch ihre eigene Konfiguration
gesteuert: keines von beiden tut etwas, bis du ein Verzeichnis zum Hineinschreiben und eine
URL zum Zurücklesen benennst.exploit_audit.log aufgezeichnet; --watermark bettet ein nachverfolgbares Token ein; Ausführungslogs gehen an
rcekit.log.--template-file, die fehlt, bringt RCEKit dazu, den Lauf zu verweigern und mit einem Nicht-Null-Wert zu beenden,
statt stillschweigend nichts zu generieren (--doctor prüft es). Nur eine fehlende
Standard-Korpusdatei fällt auf die eingebaute Kopie zurück, und es sagt es, wenn es
das tut.Dieses Toolkit ist nur für autorisiertes Penetrationstesting, Sicherheitsforschung, Ausbildung und defensives Training gedacht. Verwende es niemals gegen Systeme ohne ausdrückliche Erlaubnis — unbefugtes Testen ist illegal.
python -m unittest discover -s tests # dependency-free test suite
Beiträge willkommen — neue Sinks/Kategorien, Kodierungen, Umgebungen, Erkennungsmethoden, Bugfixes und Dokumentation. Payload-Basen liegen in editierbaren JSON-Vorlagen (`templates/payloads.json`), sodass die meisten Abdeckungen erweitert werden können, ohne den Python-Quellcode anzufassen. Nach Änderung des Korpus die integrierte Kopie aktualisieren, die in `rcekit.py` mitgeliefert wird:```bash
python tools/embed_corpus.py # --check verifies it is current
Die Testsuite schlägt fehl, wenn die beiden jemals voneinander abweichen. Siehe CONTRIBUTING.md.
MIT — siehe LICENSE.
deserialization-sink| Blind / Out-of-Band — Exfil, Async | oob | Eingebauter HTTP/DNS-Listener empfängt Callbacks und korreliert jeden mit dem exakten Payload; jede Probe trägt ihr eigenes Token. |
| Expression-Lookup-Sinks — Log4Shell/JNDI | lookup | Der Sink löst eine ${jndi:…}-URI auf, statt einen Befehl auszuführen, sodass die Shell-Probes von oob nichts erreichen. Beweist es allein am Callback und meldet lookup-sink, niemals confirmed. Es wird nur jndi:dns:// gesendet — ein Name-Lookup und nichts weiter —, sodass bewiesen wird, was bewiesen wird: der Lookup, nicht eine Gadget-Chain. |
| Die Nutzlast läuft später, bei einer anderen Anfrage | Wenn die Ausführung bei einer anderen Anfrage erfolgt |
| Der Injektionspunkt ist SQL und die Senke ist der Datenbank-Host | Query-Language-Bridges |
| Der Endpunkt nimmt ein serialisiertes Objekt entgegen | Deserialisierungs-Senken |
| Die Senke liegt hinter einem Login oder einem Datei-Upload | Mehrstufige Ketten |
Ich habe needs-review / inconclusive / error erhalten | Die Ergebnisse lesen |
| Es heißt, das Korpus sei unbrauchbar | Fehlerbehebung |