
POC per CVE-2026-30950 che permette l'hijacking di sessione in AutoGpt
Dimostrazione proof-of-concept per CVE-2026-30950, un IDOR autenticato (Mancanza di autorizzazione) nella piattaforma AutoGPT che consente a qualsiasi utente autenticato di riassegnare — e quindi dirottare — la sessione chat di qualsiasi altro utente tramite una singola richiesta PATCH, senza alcun accesso precedente alla sessione.
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:L)autogpt-platform-backend >= 0.6.36L'API delle sessioni chat espone una rotta che permette a un utente di associare il proprio account a un record di sessione. La rotta è protetta da autenticazione JWT, ma non verifica che il chiamante possieda attualmente la sessione che viene modificata — solo che sia un utente autenticato. Una chiamata diretta con il session_id della vittima e il JWT dell'attaccante trasferisce la proprietà della sessione all'attaccante.
La vulnerabilità ha tre livelli e il bypass è stabilito su ciascuno di essi:
# autogpt_platform/backend/backend/api/features/chat/routes.py:753-776
@router.patch(
"/sessions/{session_id}/assign-user",
dependencies=[Security(auth.requires_user)],
status_code=200,
)
async def session_assign_user(
session_id: str,
user_id: Annotated[str, Security(auth.get_user_id)],
) -> dict:
await chat_service.assign_user_to_session(session_id, user_id)
return {"status": "ok"}
La rotta accetta qualsiasi chiamante autenticato. Passa poi al servizio:
# autogpt_platform/backend/backend/copilot/service.py:291-303
async def assign_user_to_session(session_id: str, user_id: str) -> ChatSessionInfo:
session = await get_chat_session(session_id, None) # ← user_id=None
if not session:
raise NotFoundError(f"Session {session_id} not found")
session.user_id = user_id
session = await upsert_chat_session(session)
return session
Il servizio passa deliberatamente user_id=None all'accessor dei dati, invece di inoltrare l'ID utente del chiamante. L'accessor dei dati tratta quindi None come modalità amministratore e salta il filtro di proprietà:
# autogpt_platform/backend/backend/copilot/model.py:355-366
session = await _get_session_from_cache(session_id)
if session:
if user_id is not None and session.user_id != user_id:
logger.warning(f"Session {session_id} user id mismatch")
return None
return session
Quando user_id è None, la congiunzione si interrompe e il controllo di disallineamento non viene mai eseguito — qualsiasi sessione viene restituita a qualsiasi chiamante. Il servizio sovrascrive poi session.user_id con l'ID del chiamante e memorizza il risultato nella cache Redis, in modo che le ricerche successive da parte del proprietario originale vengano rifiutate dallo stesso controllo di disallineamento che è stato appena bypassato.
Qualsiasi istanza della piattaforma AutoGPT che esegue autogpt-platform-backend >= 0.6.36 e < 0.6.51 con la funzionalità chat (copilot) abilitata è sfruttabile. Lo sfruttamento richiede:
Impatto per sessione, che aumenta con ogni sessione dirottata:
Il punteggio CVSS (C:H / I:N / A:L) riflette l'ambito per sessione: impatto elevato sulla riservatezza delle sessioni dirottate, nessun danno all'integrità dei contenuti dei messaggi preesistenti e un impatto sulla disponibilità (blocco) per il legittimo proprietario.
Questo repository fornisce un POC, che copre il trigger diretto: una singola richiesta PATCH dal JWT di un attaccante contro un session_id noto. Lo script di configurazione crea due utenti (attaccante + vittima) in uno stack AutoGPT appena avviato e verifica le precondizioni prima di dichiararsi pronto.
setup/ — Ambiente Docker Compose.
setup.sh clona AutoGPT all'ultimo tag vulnerabile (autogpt-platform-beta-v0.6.50) in setup/AutoGPT-src/, avvia i servizi minimi dal docker-compose.yml upstream (rest_server, copilot_executor, database_manager, migrate, più le loro dipendenze transitive: Postgres, Redis, RabbitMQ, Supabase Kong + GoTrue), crea due utenti di test e verifica che l'endpoint vulnerabile sia instradato.teardown.sh arresta lo stack e cancella i volumi.pocs/session_hijack.py — Exploit autonomo. Effettua il login come vittima e attaccante, crea una sessione come vittima, conferma che l'attaccante non ha accesso in lettura pre-sfruttamento, invia la singola richiesta PATCH, quindi dimostra che la proprietà è stata trasferita e la vittima è bloccata.
Prerequisiti: Docker, Git, Python 3.10+ e uv.
cd setup
./setup.sh
La prima esecuzione clona AutoGPT al tag vulnerabile e costruisce l'immagine del backend (~3-5 minuti). Le esecuzioni successive sono rapide. Al termine, la configurazione stampa l'invocazione del POC pronta per essere incollata.
Esegui il POC:
uv run --no-project --with requests \
pocs/session_hijack.py \
--api-url http://localhost:58006 \
--auth-url http://localhost:58000 \
--attacker-email [email protected] \
--attacker-password 'Attacker123!' \
--victim-email [email protected] \
--victim-password 'Victim123!'
Perché le porte alte? Il compose upstream codifica i nomi dei container (
supabase-db,rabbitmq, ...) e pubblica le porte predefinite (5432, 8000, ...). Per coesistere con eventuali altri stack Supabase / Postgres / RabbitMQ che l'utente potrebbe già avere in esecuzione,setup/docker-compose.override.ymlrinomina i container, isola le reti sotto un nome di progetto univoco (autogpt-cve-2026-30950) e alza le due porte esposte esternamente nell'intervallo 58000. Gli altri servizi interni si legano solo alla rete docker del progetto.
L'output previsto termina con:
[PASS] AUTHENTICATED SESSION HIJACK CONFIRMED
Arresta:
cd setup
./teardown.sh
Il sorgente AutoGPT clonato in setup/AutoGPT-src/ viene preservato tra gli arresti, quindi le riesecuzioni non lo scaricano di nuovo. Per eliminarlo completamente, cancella setup/AutoGPT-src/.