July 24, 2026
I got tired of spraying RCE payloads that never fire — so I built a tool that only sends the ones…
Sink-aware payload generation, and why “did it actually execute?” is the question most tools quietly ignore
By ahmad kabiri
3 min read
If you've tested for remote code execution, you know the ritual. You find an injection point, you grab a big list of payloads — PayloadsAllTheThings, a SecLists file, your own collection — you load it into Burp Intruder, and you spray.
And then you watch most of it bounce off.
Not because the target isn't vulnerable. Because the payloads never had a chance. The sink strips quotes, so every quoted payload is dead on arrival. It caps input at 64 characters, so half your list is too long. It sits mid-command, so anything without a separator does nothing. You're firing hundreds of requests, and the handful that could actually work are buried somewhere in the noise — if they're even in the list at all.
I did this enough times that the waste started to bother me. A payload list is a blunt instrument: it knows nothing about the target it's being thrown at. So I built RCEKit to invert the relationship — to make the target shape the payloads, instead of the payloads ignoring the target.
Describe the sink once, generate only what can reach it
The core idea is simple. Before generating anything, you tell RCEKit what the sink looks like: which characters it denies, its maximum length, whether it needs a command separator, whether it's blind, what encodings it decodes. Then it emits only the payloads that could actually survive that sink.
On one real target, describing the sink as mid-command (needs a separator) dropped about 20% of the candidate payloads — without losing a single one that actually worked. Less noise hitting the target, same coverage of what matters.
There's a second, quieter half to this: context. A payload that's perfect for a raw shell is garbage inside a JSON string, where an unescaped quote breaks the whole request before it reaches the sink. RCEKit escapes each payload for the context it's landing in — quotes and backslashes escaped in JSON, entity-escaped in XML, quote-broken in a single-quoted shell string — so the payload survives its container and arrives intact. It's the difference between a payload that reaches the vulnerability and one that dies in transit.
And the generation is targeted per environment and sink — 14+ environments, down to specific code-execution sinks like SSTI, SpEL, OGNL, $where, and deserialization. You get payloads shaped for the target in front of you, not a one-size-fits-all dump.
The question most tools ignore: did it actually execute?
Better generation is half the story. The other half is the part I find most tools quietly skip: confirming that something executed.
For reflected output it's tedious but doable. For blind injection it's genuinely painful — you end up eyeballing response times and spinning up a separate out-of-band service, then trying to correlate a callback back to which of your 200 payloads caused it. Most of that guesswork is where false positives are born.
So RCEKit closes the loop. It fires the generated payloads at an authorized target and confirms which ones actually ran — and it's deliberately hard to fool. Confirmation is differential: a timing signal has to clear a noise-aware baseline and reproduce on a re-fire before it counts; a signature that already appears in the payload-free response is reported as inconclusive, not celebrated as a hit. For blind cases, a built-in listener catches the out-of-band callback and maps it back to the exact payload that triggered it — no separate infrastructure to babysit.
The output isn't "maybe." It's a clean split:
[verify] sent 270 unique payloads: confirmed=44, no-match=86, no-signature=140[verify] sent 270 unique payloads: confirmed=44, no-match=86, no-signature=140Forty-four you can put in a report. The rest, you can stop wondering about.
Built to be trusted — in both directions
It's offensive tooling, so the guardrails aren't cosmetic. Generating exploitation payloads and running live verification require an explicit consent flag. There's a benign detection-only mode for when you just want a canary. Destructive payloads are never fired at a target unless you deliberately opt in. Every run is logged. It exists for authorized penetration testing, security research, and defensive training — and the framing is built to keep it there.
It's open source under MIT, runs on Python 3.8+, and has zero third-party dependencies — git clone and it works.
If any of this sounds like a workflow you recognize, take a look: https://github.com/kabiri-labs/rcekit
And if you run it in a real engagement, I'd genuinely like to hear what confirmed and what didn't. The confirmation logic gets sharper with adversarial feedback — which is exactly the kind of thing that's better built in the open.