📦 OliveTin

What is it?

  • Concept: OliveTin is a lightweight web application that gives non-technical users buttons for a fixed list of shell commands defined by an administrator in a YAML config. The security model is the allow-list: you cannot run arbitrary commands, only the ones an admin pre-approved, with arguments constrained by declared types.
  • Impact: The whole model rests on argument validation, and it is normally deployed as root so its buttons can restart services and write to system paths. A single argument whose declared type performs no character validation therefore turns a fixed command into arbitrary root command execution.

How it works

  1. OliveTin serves an HTTP UI and a JSON API, by default on port 1337, typically bound to 127.0.0.1 behind a reverse proxy.
  2. /etc/OliveTin/config.yaml defines every action: a title, a shell string, and an arguments list. The shell string interpolates arguments via {{ name }} placeholders.
  3. Each argument carries a declared type — int, ascii_identifier, password, and so on — which is the only input filtering that exists.
  4. POST /api/StartAction executes an action by id, with an arguments array of {name, value} objects. The UI is a client of this API; nothing about the API requires the UI.
  5. The interpolated string is handed to a shell, so the placeholder is textual substitution into a command line, not a parameterised exec.

Security Quirks & Niche Facts

  • It usually runs as root by design. That is the point of the tool — expose privileged operations safely to unprivileged people — and it is precisely why an injection here is a full privilege escalation rather than a lateral step. An unfamiliar root process in ps auxww is the tell.
  • config.yaml is the exploit map. It contains every command, every placeholder, and every argument type. Reading it converts blind guessing into a targeted search for the one argument whose type does not filter.
  • Argument types are not uniformly strict. int and ascii_identifier reject quotes and semicolons; a password type is designed to accept arbitrary characters, because passwords legitimately contain them. That asymmetry is the vulnerability class: the permissive argument in an otherwise well-validated action.
  • The classic injectable shape is a quoted password on a command line, e.g. mysqldump -u {{ db_user }} -p'{{ db_pass }}' {{ db_name }}. A value of ' ; id > /tmp/proof ; echo ' closes the quote, runs a command, and reopens a quote so the remainder still parses.
  • {{ output }} and {{ exit_code }} are not attacker-controlled — they are populated by the server. Time spent on them is wasted; only user-supplied arguments matter.
  • The API field name is bindingId, not actionId. Payloads copied from blog posts frequently use the wrong key and silently do nothing; proxying one real UI request through (incomplete) BurpSuite settles the exact schema in seconds.
  • Binding to 127.0.0.1 is not a boundary once you have a shell. Confirm with ss -lntp, then either curl it locally or forward the port out with Chisel to drive it from a browser.
  • Command output is not returned to the injecting caller — the injected command runs in a different context to the response you see. Redirect to a world-readable file (> /tmp/proof ; chmod 666 /tmp/proof) and read it separately.
  • Version 3000.10.0 is affected by CVE-2026-27626, a critical RCE; OliveTin --version fingerprints it directly.

Notes

  • Enumeration order that works: ps auxww | grep root → OliveTin --version → ss -lntp to confirm the port → cat /etc/OliveTin/config.yaml to pick the argument.
  • Prove the primitive with id before going for the flag; a failed cat /root/root.txt is ambiguous, a successful id is not.
  • If the injected command appears to run but not as root, the action may be configured with a lower-privilege user — re-read the action definition rather than assuming the injection failed.

Mitigation

  • Fix: Never interpolate an unvalidated argument into a shell string. Pass arguments as an argv array so the shell never re-parses them, which removes the injection regardless of the value.
  • Run OliveTin as a dedicated unprivileged user and grant only the specific escalations individual actions need via narrowly scoped sudo rules.
  • Avoid free-form argument types in shell contexts; where a secret genuinely must be passed, hand it through an environment variable or a file, not the command line.
  • Keep the service bound to localhost and patched — localhost binding delays an attacker who already has a shell, it does not stop them.
FileCreated
HTB Machine - EnigmaSeptember 07, 2026

References: