Che cos'è l'esecuzione di una pipeline avvelenata (PPE)?

L'esecuzione avvelenata della pipeline (PPE), un rischio di sicurezza OWASP CI/CD, è un vettore di attacco che abusa dei permessi di accesso a un sistema di gestione del codice sorgente (SCM) con l'intento di far eseguire a una pipeline CI comandi dannosi. Mentre gli aggressori PPE non hanno accesso all'ambiente di compilazione, hanno ottenuto l'accesso all'SCM, che consente loro di iniettare codice dannoso nella configurazione della pipeline di compilazione per manipolare il processo di compilazione.

 

CICD-SEC-4: Spiegazione dell'esecuzione della pipeline avvelenata

L'esecuzione di pipeline avvelenate (PPE), elencata come CICD-SEC-4 nella OWASP Top 10 CI/CD Security Risks, rappresenta una strategia di attacco sofisticata che prende di mira i sistemi di integrazione continua e distribuzione continua (CI/CD).

I clienti possono avere a disposizione una serie di opzioni:

Nella strategia PPE, gli aggressori eseguono codice maligno all'interno della porzione CI della Pipeline CI/CD, aggirando la necessità di accedere direttamente al sistema CI/CD. Il metodo prevede la manipolazione delle autorizzazioni su un repository di gestione del codice sorgente (SCM). Modificando i file di configurazione CI o altri file da cui dipende il lavoro della pipeline CI, gli aggressori iniettano comandi dannosi, avvelenando di fatto la pipeline CI e consentendo l'esecuzione di codice non autorizzato.

Gli attacchi DPI di successo possono consentire un'ampia gamma di operazioni, tutte eseguite nel contesto dell'identità della pipeline. Le operazioni dannose possono includere l'accesso a segreti disponibili per il lavoro CI, l'accesso ad asset esterni per i quali il nodo di lavoro ha i permessi, la spedizione di codice e artefatti apparentemente legittimi lungo la pipeline e l'accesso a host e asset aggiuntivi nella rete o nell'ambiente del nodo di lavoro.

Dato il suo impatto critico, la bassa rilevabilità e l'esistenza di molteplici tecniche di sfruttamento, l'attacco DPI rappresenta una minaccia diffusa. Per i team addetti alla sicurezza, gli ingegneri e i team rossi, la comprensione dei DPI e delle loro contromisure è fondamentale per la sicurezza delle CI/CD.

Esecuzione della pipeline definita

Nel contesto dell'integrazione continua (CI), il flusso di esecuzione della pipeline si riferisce alla sequenza di operazioni definite dal file di configurazione CI ospitato nel repository che la pipeline costruisce. Questo file delinea l'ordine dei lavori eseguiti, oltre a dettagliare le impostazioni dell'ambiente di costruzione e le condizioni che influenzano il flusso. Quando viene attivato, il lavoro della pipeline estrae il codice dalla fonte scelta (ad esempio, commit/branch) ed esegue i comandi specificati nel file di configurazione CI contro quel codice.

I comandi all'interno della pipeline sono invocati direttamente dal file di configurazione CI o indirettamente da uno script, un test di codice o un linter residente in un file separato a cui si fa riferimento dal file di configurazione CI. I file di configurazione CI hanno in genere nomi e formati coerenti, come Jenkinsfile (Jenkins), .gitlab-ci.yml (GitLab), .circleci/config.yml (CircleCI) e i file YAML delle Azioni GitHub che si trovano sotto .github/workflows.

Gli attaccanti possono sfruttare la capacità di manipolare i comandi eseguiti dalla pipeline, direttamente o indirettamente, possono essere sfruttati dagli attaccanti per eseguire codice dannoso nell'IC.

Come avviene lo sfruttamento di CICD-SEC-4

Affinché un attacco DPI abbia successo, devono essere soddisfatti diversi criteri:

  1. L'attaccante deve ottenere le autorizzazioni per un repository SCM. Questo può avvenire attraverso le credenziali dell'utente, i token di accesso, le chiavi SSH, i token OAuth o altri metodi. In alcuni casi, l'accesso anonimo a un archivio pubblico può essere sufficiente.
  2. Le modifiche al repository in questione devono attivare una pipeline CI senza ulteriori approvazioni o revisioni. Questo può avvenire tramite push diretti ai rami remoti o tramite modifiche suggerite tramite una richiesta di pull da un ramo remoto o da un fork.
  3. Le autorizzazioni ottenute dall'aggressore devono consentire l'attivazione degli eventi che causano l'esecuzione della pipeline.
  4. I file che l'attaccante può modificare devono definire i comandi che vengono eseguiti (direttamente o indirettamente) dalla pipeline.
  5. Il nodo della pipeline deve avere accesso a risorse non pubbliche, come segreti, altri nodi o risorse di calcolo.

Le pipeline che eseguono codice non revisionato, come quelle innescate da richieste di pull o commit a rami di repository arbitrari, sono più suscettibili di PPE. Una volta che un aggressore è in grado di eseguire codice dannoso all'interno della pipeline CI, può condurre operazioni dannose nel contesto dell'identità della pipeline.

Tre tipi di esecuzione di una pipeline avvelenata

L'esecuzione di pipeline avvelenate si manifesta in tre forme distinte: PPE diretta (D-PPE), PPE indiretta (I-PPE) e PPE pubblica (3PE).

DPI diretti

In uno scenario di DPI diretto, gli aggressori modificano il file di configurazione CI in un repository a cui hanno accesso, spingendo la modifica direttamente su un ramo remoto non protetto del repo o inviando una richiesta di pull con la modifica da un ramo o un fork. L'esecuzione della pipeline viene attivata dagli eventi di richiesta push o pull, come definito dai comandi nel file di configurazione CI modificato, il che comporta l'esecuzione dei comandi dannosi nel nodo di compilazione una volta attivata la pipeline di compilazione.

Flusso di attacco diretto di esecuzione della pipeline avvelenata

Figura 1: Flusso di attacco diretto di esecuzione della pipeline avvelenata

L'esempio di attacco D-PPE illustrato nella figura 1 si svolge nella seguente successione di passi:

  1. Un avversario avvia un nuovo ramo remoto all'interno del repository, alterando il file di configurazione della pipeline con istruzioni dannose per recuperare le credenziali AWS memorizzate all'interno dell'organizzazione GitHub e trasmetterle a un server esterno sotto il controllo dell'attaccante.
  2. Il push del codice attiva una pipeline che estrae il codice, compreso il file di configurazione della pipeline dannosa, dal repository.
  3. La pipeline opera in base al file di configurazione, ora contaminato dall'aggressore. Le istruzioni dannose comandano di caricare in memoria le credenziali AWS, memorizzate come segreti del repository.
  4. Seguendo le istruzioni dell'aggressore, la pipeline esegue il compito di trasmettere le credenziali AWS a un server sotto il controllo dell'aggressore.
  5. In possesso delle credenziali rubate, l'attaccante ottiene la capacità di infiltrarsi nell'ambiente di produzione.

DPI indiretti

La DPI indiretta si verifica quando la possibilità di D-PPE non è disponibile per un avversario con accesso a un repository SCM:

  • Se la pipeline è configurata per estrarre il file di configurazione CI da un ramo separato e protetto dello stesso repository.
  • Se il file di configurazione CI è archiviato in un repository separato dal codice sorgente, senza la possibilità per un utente di modificarlo direttamente.
  • Se la build CI è definita nel sistema CI stesso - invece che in un file memorizzato nel codice sorgente.

In questi scenari, l'aggressore può ancora avvelenare la pipeline iniettando codice dannoso nei file a cui fa riferimento il file di configurazione della pipeline, come gli script a cui si fa riferimento all'interno del file di configurazione della pipeline, i test del codice o gli strumenti automatici come i linters e gli scanner di sicurezza utilizzati nell'IC. Per esempio:

  • L'utilità make esegue i comandi definiti nel file Makefile.
  • Script a cui si fa riferimento all'interno del file di configurazione della pipeline, che sono memorizzati nello stesso repository del codice sorgente stesso (ad esempio, python myscript.py - dove myscript.py verrebbe manipolato dall'attaccante).
  • Test del codice: I framework di test eseguiti sul codice dell'applicazione all'interno del processo di compilazione si basano su file dedicati, archiviati nello stesso repository del codice sorgente. Gli aggressori che riescono a manipolare il codice responsabile del test possono poi eseguire comandi dannosi all'interno della build.
  • Strumenti automatici: I liner e gli scanner di sicurezza utilizzati nell'IC si basano comunemente su un file di configurazione che risiede nel repository e che in genere carica ed esegue codice esterno da una posizione definita all'interno del file di configurazione.

Piuttosto che avvelenare la pipeline tramite un DPI diretto, l'attaccante che lancia un attacco DPI indiretto inietta codice dannoso nei file a cui fa riferimento il file di configurazione. Il codice dannoso viene infine eseguito sul nodo della pipeline ed esegue i comandi dichiarati nei file.

Flusso dell'attacco di esecuzione della pipeline avvelenata indiretta

Figura 2: Flusso dell'attacco di esecuzione della pipeline avvelenata indiretta

In questo esempio di attacco I-PPE, la catena di eventi si svolge come segue:

  1. Un aggressore crea una richiesta di pull nel repository, aggiungendo comandi dannosi al file Makefile.
  2. Poiché la pipeline è configurata per attivarsi su qualsiasi PR contro il repository, la pipeline Jenkins viene attivata, recuperando il codice dal repository - compreso il Makefile dannoso.
  3. La pipeline viene eseguita in base al file di configurazione memorizzato nel ramo principale. Arriva alla fase di costruzione e carica le credenziali AWS nelle variabili d'ambiente - come definite nel file Jenkins originale. Poi, esegue il comando make build, che esegue il comando dannoso aggiunto nel Makefile.
  4. La funzione di compilazione dannosa definita nel Makefile viene eseguita, inviando le credenziali AWS a un server controllato dall'aggressore.
  5. L'aggressore può quindi utilizzare le credenziali rubate per accedere all'ambiente di produzione AWS.

DPI pubblici

Il DPI pubblico è un tipo di attacco DPI eseguito da aggressori anonimi su Internet. I repository pubblici spesso consentono a qualsiasi utente di contribuire, di solito creando richieste di pull. Se la pipeline CI di un repository pubblico esegue codice non revisionato suggerito da utenti anonimi, è suscettibile di un attacco DPI pubblico. Il DPI pubblico può anche esporre asset interni, come i segreti dei progetti privati, nei casi in cui la pipeline del repository pubblico vulnerabile viene eseguita sulla stessa istanza CI di quelli privati.

 

Importanza dell'esecuzione sicura della pipeline in CI/CD

L'esecuzione di codice dannoso non revisionato nel CI tramite un attacco PPE riuscito fornisce agli aggressori lo stesso livello di accesso e di capacità del lavoro di compilazione:

  • Accesso ai segreti disponibili per il lavoro CI, come i segreti iniettati come variabili d'ambiente o i segreti aggiuntivi memorizzati nel CI. Essendo responsabili della creazione di codice e della distribuzione di artefatti, i sistemi CI/CD contengono tipicamente decine di credenziali e token di alto valore, ad esempio verso un provider cloud, verso i registri degli artefatti e verso lo stesso SCM.
  • L'accesso alle risorse esterne per le quali il nodo di lavoro ha i permessi, come i file memorizzati nel file system del nodo, o le credenziali di un ambiente cloud accessibile attraverso l'host sottostante.
  • Possibilità di inviare codice e artefatti più avanti nella pipeline, sotto forma di codice legittimo costruito dal processo di compilazione.
  • Capacità di accedere a host e asset aggiuntivi nella rete/ambiente del nodo di lavoro.

Ma le organizzazioni possono salvaguardare i loro prodotti e infrastrutture software con una pipeline di esecuzione sicura, che garantisca che tutto il codice compilato, testato e distribuito sia legittimo e non manomesso.

Rischi associati all'esecuzione di condotte avvelenate

Le implicazioni dei DPI possono essere gravi, e vanno dall'accesso non autorizzato ai dati, alla compromissione dell'integrità del software, all'interruzione del sistema, alla violazione dei dati o addirittura all'acquisizione totale del sistema. Questi rischi rappresentano minacce significative sia per l'azienda che per i suoi clienti, sottolineando la gravità dei DPI.

Impatto a valle di una pipeline CI avvelenata

Figura 3: Impatto a valle di una pipeline CI avvelenata

Nell'operazione di compromissione della catena di approvvigionamento in otto fasi, vista nella figura 3, l'attaccante ottiene l'accesso alla pipeline CI e avvelena i componenti dell'applicazione SaaS. Tramite il componente avvelenato, l'aggressore costruisce una funzionalità backdoor nell'applicazione e invia i plugin avvelenati ai client a valle. Poiché le organizzazioni a valle probabilmente percepiscono il pacchetto avvelenato come legittimo, lo inseriscono nella loro infrastruttura cloud o locale.

Da una pipeline CI avvelenata, l'attaccante ottiene un danno collaterale esponenziale, avendo creato un accesso backdoor a innumerevoli organizzazioni. Questo è stato il caso dell'attacco SolarWinds.

LEGGI TUTTO: Anatomia di un attacco alla pipeline CI/CD

 

Prevenire l'esecuzione di pipeline avvelenate

La prevenzione e la mitigazione del vettore di attacco DPI comporta molteplici misure che riguardano sia i sistemi SCM che quelli CI:

  • Si assicuri che le pipeline che eseguono codice non esaminato siano eseguite su nodi isolati rispetto a quelli esposti a segreti e ambienti sensibili.
  • Valutare la necessità di attivare le pipeline sui repository pubblici di collaboratori esterni. Quando è possibile, si astenga dall'eseguire pipeline originate da fork e consideri l'aggiunta di controlli come la richiesta di approvazione manuale per l'esecuzione della pipeline.
  • Per le pipeline sensibili, ad esempio quelle esposte ai segreti, si assicuri che ogni ramo configurato per attivare una pipeline nel sistema CI abbia una regola di protezione del ramo correlata nell'SCM.
  • Per evitare la manipolazione del file di configurazione CI per eseguire codice dannoso nella pipeline, ogni file di configurazione CI deve essere esaminato prima dell'esecuzione della pipeline. In alternativa, il file di configurazione CI può essere gestito in un ramo remoto, separato dal ramo che contiene il codice da costruire nella pipeline. La filiale remota deve essere configurata come protetta.
  • Rimuove i permessi concessi sul repository SCM dagli utenti che non ne hanno bisogno.
  • Ciascuna pipeline deve avere accesso solo alle credenziali di cui ha bisogno per adempiere al suo scopo. Le credenziali devono avere i privilegi minimi richiesti.

 

FAQ sull'esecuzione del gasdotto avvelenato

Un server di compilazione è una macchina sulla quale viene eseguito il processo di compilazione di un progetto. Compila il codice sorgente in codice eseguibile.
Un ambiente di staging è una replica dell'ambiente di produzione utilizzato per i test. Aiuta a cogliere potenziali errori o problemi prima che si ripercuotano sull'utente finale.
Un linter è uno strumento che analizza il codice sorgente per segnalare errori di programmazione, bug, errori stilistici e costrutti sospetti. Se il linter segnala dei problemi, la pipeline può essere configurata per fallire, impedendo al codice di passare alla fase successiva. Questo aiuta le organizzazioni a distribuire solo il codice che soddisfa gli standard di qualità definiti.
La distribuzione blu/verde è una strategia di gestione dei rilasci che riduce i tempi di inattività e i rischi eseguendo due ambienti di produzione identici, denominati Blu e Verde. In qualsiasi momento, solo uno è in funzione, con l'ambiente live che serve tutto il traffico di produzione.
Il rollback è il processo di ritorno alla versione precedente di un'applicazione software, se la nuova versione presenta dei problemi. Si tratta di una misura di sicurezza che garantisce la stabilità del sistema in caso di distribuzioni problematiche.
Uno smoke test, noto anche come test di verifica della build, è un tipo di test del software che comprende un insieme non esaustivo di test che mirano a garantire il funzionamento delle funzioni più importanti.
Una release canary è una tecnica per ridurre il rischio dell'introduzione di nuove versioni di software nella produzione, distribuendo lentamente la modifica a un sottogruppo di utenti prima di distribuirla all'intera infrastruttura.
L'infrastruttura come codice è il processo di gestione e provisioning dei centri dati informatici attraverso file di definizione leggibili dalla macchina, piuttosto che la configurazione dell'hardware fisico o gli strumenti di configurazione interattivi.
L'integrazione continua è una pratica di sviluppo in cui gli sviluppatori uniscono regolarmente le loro modifiche al codice in un repository centrale, seguito da build e test automatizzati.
La consegna continua è la pratica di automatizzare l'intero processo di rilascio del software. Dopo aver superato i test automatizzati, le modifiche al codice vengono distribuite automaticamente in un ambiente simile alla produzione per ulteriori test e convalide.
Una pipeline di distribuzione è il percorso che una modifica del codice compie dal controllo di versione all'ambiente di produzione. Comprende fasi come la costruzione, il test e la distribuzione.
Indietro Che cos'è la configurazione insicura del sistema?