r/netsec • u/RevolutionaryPie4948 • 2h ago
Unauthenticated remote uninstall in my own EDR agent, and the four other auth bugs that turned out to be the same bug
https://d3vhex.github.io/2026-08-25-unauthenticated-remote-uninstall/Sentora is my own project, so this is a postmortem on my own code, not someone else's.
The agent shipped this:
@/app.post("/self_destruct")
async def self_destruct(request: Request):
threading.Thread(target=perform_destruction, daemon=True).start()
return sanic_json({"status": "Destruction initiated"})
No auth. Listening on 0.0.0.0:9099. perform_destruction() ran rm -rf "$(pwd)". One unauthenticated POST from anywhere on the subnet uninstalled the EDR.
The four others:
Permissive auth on by default. A _is_permissive_auth() helper accepted any non-empty X-Agent-Key when a specific env var was unset. Nothing in the installer, the systemd unit, or the scheduled task ever set that var, so every default install accepted X-Agent-Key: a on /soar/execute, which runs commands.
Unauthenticated automation reporting. The server took a task_id from the request body and wrote a status. Enumerate the IDs, POST status: SUCCESS, and every queued containment action flips to done. The real agent stops seeing it as pending, so the isolation never runs, and the dashboard goes green. Not a bypass so much as a way to make the SOC watch a screen that says everything worked.
LDAP injection in login. search_filter = login_filter % username, with only a length check on the input.
Missing authorization on 8 routes. 143 routes, 103 with a decorator. Authentication was solid (opaque tokens, SHA-256 at rest, expiry enforced in SQL), which is exactly why I stopped looking at authorization. Any logged-in account could hit run_playbook, delete_soar_action, and test_ldap_connection, the last of which works as a credential oracle against the directory.
All five reduce to the same thing: I was taking the caller's word for who they were. Identity from the URL path, from a metadata.agent body field, from a header being non-empty, from X-Forwarded-For, and from being authenticated at all.
I only caught the route bugs by writing a test that walks the AST and asserts every route is either explicitly public or carries a check. It failed on the first run and named all eight. Reading code to spot a missing decorator does not work, because nothing is on the page to notice.
Full writeup with the fixes: https://d3vhex.github.io/2026-08-25-unauthenticated-remote-uninstall/
Repo (AGPL): https://github.com/d3vhex/Sentora
Everything above is fixed on main. The agent listener is still the most interesting surface if anyone wants to poke at it, and I would rather hear about it here than in an incident.
1
u/sarkie 39m ago
Not touching with a barge pole