4.837 account GitHub hanno seminato un ladro di segreti nei repository

4.837 account GitHub hanno seminato un ladro di segreti nei repository

4.837 account GitHub sono stati utilizzati per testare l'accesso in scrittura a 61.764 repository e, in una parte di essi, installare un ladro di segreti nei flussi di integrazione continua. Aikido Security ha conteggiato esecuzioni in almeno 1.806 repository. La campagna, rilevata da martedì 10 novembre, ha sfruttato credenziali rubate e in molti casi ha cancellato sia le modifiche malevole sia i registri delle esecuzioni.

L'attacco non si è limitato ai repository di proprietà degli account compromessi: i test hanno raggiunto anche progetti accessibili tramite autorizzazioni di collaboratore o di organizzazione. E la portata viene misurata in diversi modi. SafeDep, in un'analisi indipendente, ha trovato commit malevoli in 8.093 repository pubblici; WebPulse, sulla base di un campione di Aikido, riporta una stima di circa 6.500 repository nei quali il payload potrebbe essere stato eseguito. Sono conteggi basati su metodi e coperture differenti, non cifre intercambiabili.

Una pull request per verificare le autorizzazioni

L'attività iniziava con una pull request intitolata docs: dependency audit notes, inviata da un branch chiamato wfx-docs. La sua funzione era verificare se l'account rubato poteva scrivere nel repository. Aikido ha identificato richieste di test in 61.764 repository; alcune hanno poi ricevuto il codice malevolo.

Il test è importante di per sé, anche quando non c'è stata una seconda modifica. Aikido afferma che qualsiasi account che abbia aperto una di queste pull request deve essere considerato compromesso, anche se il ladro non è arrivato a essere eseguito. Nella maggior parte dei repository testati non è stato inviato altro, oppure il payload non ha funzionato a causa della configurazione del progetto o delle autorizzazioni disponibili.

Delle pull request inviate con accesso da collaboratore o da organizzazione, 10.431 hanno raggiunto repository che non appartenevano all'account attaccato. Il 92% risultava ancora aperto quando Aikido ha effettuato la verifica. Questo amplia la ricerca oltre i progetti di proprietà di ciascun utente: un account poteva usare le autorizzazioni delegate per sondare altri repository.

L'attività malevola ha assunto diverse forme. In 7.309 repository del conteggio di SafeDep, il codice è stato aggiunto a un flusso di lavoro già esistente. In altri 771 è arrivato sotto forma di hook postinstall di npm, che può essere eseguito anche sul computer di uno sviluppatore durante l'installazione delle dipendenze.

Una delle modifiche aggiungeva circa 1.500 righe a un flusso esistente e compariva con il messaggio di commit ci: refresh build cache. Altri indizi erano il messaggio chore: add ci helper, insieme a uno script .ci-xxxxxx.sh e a un hook di installazione, oppure un nuovo flusso con un nome simile a chore: add dependency audit workflow. Sono stati osservati anche commit con messaggi come ci: restore e ci: cleanup, compatibili con la sequenza di introduzione e rimozione delle modifiche.

La modifica spariva; i segreti, non necessariamente

Dopo aver introdotto il ladro, l'attaccante di solito annullava la modifica nel giro di pochi minuti. Anche i registri del flusso e, spesso, la stessa esecuzione venivano eliminati. Aikido ha verificato che il registro mancava in 156 dei 159 repository del suo campione citati da WebPulse. Perciò, una cronologia di Actions apparentemente pulita non esclude che il codice sia stato eseguito.

Un indizio più utile può essere un numero di esecuzione mancante in prossimità del commit dell'attaccante. Aikido osserva che l'assenza di tracce visibili come artefatti chiamati wfx-loot, voci di cache wfx- o riepiloghi con WFX-BEGIN non garantisce nemmeno che non ci sia stata una perdita di dati.

Le cifre pubblicate non descrivono esattamente lo stesso universo. Aikido ha confermato l'esecuzione in almeno 1.806 repository. WebPulse riporta che l'azienda ha esaminato un campione casuale di 1.500 repository testati e ha rilevato esecuzioni nel 10,6%, con un margine di 1,6 punti; proiettando il dato, si arriva a circa 6.500 repository. SafeDep, invece, ha conteggiato 8.093 repository che hanno ricevuto commit malevoli tra le 12:46 UTC di martedì e le 04:36 UTC del giorno della sua analisi. Questo conteggio include repository nei quali il ladro non è stato eseguito ed è limitato ai branch predefiniti di progetti pubblici; per questo i ricercatori ritengono che il totale reale sia superiore.

Il payload cercava credenziali disponibili per il runner: segreti e variabili di GitHub Actions, il token GITHUB_TOKEN, token OIDC e dell'ambiente di esecuzione di Actions, chiavi di servizi di IA e segreti presenti nella memoria dei processi. Leggeva anche file di credenziali di AWS, Azure, GCP, Kubernetes, npm, PyPI, SSH e altri strumenti nelle loro posizioni abituali.

Inoltre, copiava il repository, i suoi ultimi 100 commit e gli artefatti recenti dei flussi di lavoro. Nei runner autogestiti poteva raccogliere credenziali cloud tramite i metadati dell'istanza, oltre a informazioni sullo stato dei container Docker e delle unità systemd. Aikido ha trovato opzioni per operare nei repository privati, anche se questo non dimostra di per sé quanti siano stati colpiti.

L'accesso poteva sopravvivere alla rotazione delle chiavi

Il ladro non si limitava a raccogliere segreti per inviarli all'esterno. Secondo Aikido, poteva scambiare i token OIDC di GitHub con sessioni AWS, GCP e Azure; su AWS, poteva anche creare chiavi di accesso di lunga durata per utenti IAM. Alcune funzioni erano progettate per mantenere l'accesso anche dopo la modifica delle credenziali.

Su AWS, poteva modificare la policy di attendibilità di un ruolo per consentire l'accesso da qualsiasi account AWS. Su Azure, poteva aggiungere credenziali di identità federata con il prefisso wfx-ci- alle applicazioni Entra ID. In questo modo, i flussi del repository compromesso potevano autenticarsi senza un segreto memorizzato, anche dopo la rotazione dei token abituali.

SafeDep e Aikido consigliano di cercare modifiche non riconosciute in questi sistemi: credenziali federate wfx-ci-* in Entra ID; sessioni o chiamate AssumeRoleWithWebIdentity con nomi wfx-* in CloudTrail, seguite da CreateAccessKey o UpdateAssumeRolePolicy; chiamate GenerateAccessToken e SignJwt dal pool di identità di GitHub in GCP; e accessi JWT dall'emittente OIDC di GitHub in Vault.

SafeDep consiglia di revocare i token dell'autore del commit, le concessioni delle applicazioni OAuth, le chiavi SSH e le sessioni; attivare l'autenticazione a due fattori; e ruotare tutti i segreti e le variabili che il repository poteva leggere. Se qualcuno ha eseguito npm install su un commit interessato, deve considerare compromesso anche quel computer e cambiare le chiavi che contiene.

“we don't attribute November to the same actor at this stage”

— Aikido Security

L'avvertimento di Aikido riguarda il rapporto con GhostAction, una campagna di ottobre che ha utilizzato anch'essa account GitHub rubati per introdurre flussi di lavoro che sottraevano segreti. Gli account compromessi allora avevano una probabilità circa 1.000 volte maggiore rispetto ad altri account attivi di essere riutilizzati questa settimana. In oltre 100 repository, il nuovo ladro è stato aggiunto ai flussi di lavoro di ottobre, lasciando attivo il passaggio precedente che inviava i dati. Al momento Aikido non attribuisce entrambe le ondate allo stesso attore: segnala differenze nell'infrastruttura, negli strumenti e nei metodi, e osserva che le credenziali rubate possono finire nelle mani di più aggressori.

Pacchetti interessati e indizi da cercare

La campagna ha raggiunto almeno un pacchetto Packagist e un modulo Go tramite trigger di pubblicazione automatizzati. Almeno 50 degli account compromessi sembrano pubblicare pacchetti per npm, Go, Packagist, PyPI o crates. Aikido ritiene che l'obiettivo principale fosse rubare segreti CI, non propagarsi tramite pacchetti, ma ha identificato diverse versioni da controllare.

La versione 3.14.3 di digitalelvis/neuronai-studio, pubblicata mercoledì, è malevola. Aikido consiglia di considerare compromesso qualsiasi computer su cui sia stata installata o aperta, di bloccare quella versione e di fissare la dipendenza alla 3.14.2 o a una versione precedente. Un normale composer install non esegue il ladro; per farlo è necessario eseguire npm install all'interno della directory vendor del pacchetto.

Nel modulo Go github.com/onuragtas/docker-env, le versioni v1.0.278 e v1.0.280 contengono il codice in un file di flusso di GitHub Actions. Il codice Go e i binari pubblicati non sono cambiati, e le build Go non eseguono questi flussi; Aikido consiglia comunque di ritirare tali versioni. Ha inoltre rilevato il ladro nel flusso di lavoro di github.com/vkuznet/gocurl, versione pseudoversione v0.0.0-20261111095532-8d5aad0cb0da, anche se quel flusso non era mai stato eseguito. La raccomandazione è di bloccarla.

Il codice è arrivato anche in 28 repository di WebdriverIO tramite commit attribuiti all'account bot wdio-bot. Nessuna release di pacchetti è stata interessata, ma il token del bot deve essere considerato rubato.

Per cercare l'attività nei repository accessibili da martedì 10 novembre, gli indizi includono il branch wfx-docs, branch di breve durata con nomi chore/[a-z0-9]{8} o ci-check-[0-9]{4} e la pull request docs: dependency audit notes. È inoltre opportuno controllare i commit e i file menzionati, oltre alle esecuzioni con numerazione mancante. The Hacker News include tra gli indicatori lo SHA-256 89695abb392d5cfd4972672961e644bb46baa98aa1ed7173c2a2816c762735cf dello script. SafeDep ha identificato invii HTTP POST a 194.150.166[.]244:8080/exfil, 18.143.168[.]96:8080/exfil e 153.75.82[.]159:8080, oltre a una chat Telegram. In un campione di 200 commit con payload, circa un quinto ha usato solo Telegram.

The Hacker News ha trovato nuove pull request con lo stesso titolo dopo che mercoledì si è conclusa la ricerca di Aikido. Tre richieste esaminate, aperte tra le 05:04 e le 05:38 UTC, provenivano da branch wfx-docs; non è stato possibile stabilire se il ladro sia stato eseguito. Le verifiche pubblicate coprono i repository pubblici visibili, mentre le autorizzazioni di scrittura hanno portato i test anche in progetti di organizzazioni e collaboratori.

Fonti: The Hacker News, WebPulse, Business Upturn, Secure Blog, Hamer Intelligence Services