A la nostra publicació anterior sobre CI/CD Pipelines, vam veure com piratejar un CI/CD escenari que presumptament estava protegit.
Recordem el que vam dir a l'entrada anterior: vam començar amb alguns pipeline que era vulnerable a Enverinat indirectament Pipeline Execució (I-PPE) i, per solucionar-ho, vam decidir dividir el pipeline en dos:
- El 1st pipeline (Build CI), segur per a D-PPE i I-PPE, revisaria el codi PR, faria la compilació i generaria un artefacte.
- El 2n pipeline (CI de prova), també segur per a D-PPE i I-PPE revisarien el codi base (per evitar la modificació de scripts de shell) i executarien els scripts originals contra l'artefacte.
- Per sincronitzar el CI de prova pipeline per executar DESPRÉS del CI de compilació pipeline, hem utilitzat execució_flux_de_treball disparador.
Ho hem anomenat Escenari número 3.

Tot i que, com ja vam esmentar en aquella publicació, hi ha altres solucions, vam decidir implementar aquesta "solució" per motius pedagògics, per tal de poder aprofundir en les vulnerabilitats de CI/CD pipelines.
Després, vam veure com piratejar aquest escenari mitjançant enverinant l'artefacteAixò és el que anomenem Intoxicació per artefactes, és a dir, la capacitat de modificar (piratejar) el pipeline lògica modificant una pipeline artefacte.
Quin és el problema amb aquest plantejament? Vam veure que el problema sorgeix quan qualsevol usuari "crea" una nova pipeline.
Si un usuari obre una PR que conté una nova pipeline, GitHub ho executarà pipeline (donades algunes condicions, com hem vist a la publicació).
L'usuari podrà llavors crear-ne un de nou pipeline amb el mateix nom que Build CI!! Sí, és sorprenent, però GitHub et permet crear-ne dos pipelines amb el mateix nom!!
Quan l'usuari obre una PR amb aquests canvis, el "nou" pipeline s'executarà (carregant un artefacte enverinat) i el CI de desplegament pipeline s'executarà després d'això, cosa que farà que l'script de shell "modificat" sobreescrigui l'script de shell "original" que es troba a pipeline espai de treball. Per tant, aquesta "solució" no evita la vulnerabilitat I-PPE (com podem veure a continuació)

Quins són els problemes? Com a mínim, hi ha un parell de qüestions:
- En primer lloc, Com puc assegurar-me que el procés de construcció no ha estat manipulat? En aquest escenari, l'usuari maliciós ha pogut modificar el procés de compilació previst mitjançant el seu pipeline per crear un artefacte enverinat.
- En segon lloc, Com podem avaluar la procedència d'un artefacte?
Aquestes preguntes ens llancen als braços de Certificacions de programari domini!!
Certificacions de programari
An atestat és un tros de dades representant prova d'un esdevenimentAl món real, generalment anomenem això certificacions.
Per exemple, quan un laboratori fa una anàlisi de sang, les dades sobre la prova es registren i es certifiquen. Els resultats de l'anàlisi de sang són verificable i traçable.

Més a prop del nostre domini informàtic, podríeu endevinar quina seria una traducció d'aquest procés a, per exemple, un procés de compilació.

La informació sobre l'entorn i les eines del servidor de compilació, els materials (el codi font) i els productes/artefactes (el codi binari) formarien part d'aquesta atestació.
Òbviament, l'atestat ha de ser generat per un atestador autoritzat (autenticat i no repudiable) per donar credibilitat.
Probablement, alguns de vosaltres estareu pensant... i què és el diferència entre signatures i atestacions?
Signatures de codi i certificacions
A un alt nivell, un signatura es crea mitjançant un parell de claus i un artefacte. El parell de claus consta d'una clau pública i una clau privada.

L'usuari signa un artefacte utilitzant la clau privada i altres persones poden verificar la signatura utilitzant la clau pública. La clau privada s'ha de mantenir en secret, però la clau pública es distribueix àmpliament.
Es poden utilitzar signatures per demostrar que el titular de la clau privada va utilitzar la clau privada per signar l'artefacte.
Firmes no demostris
- L'usuari intenció per signar l'artefacte (potser els han enganyat), o
- La intenció de l'usuari de fer qualsevol afirmació específica sobre l'artefacte
Amb Atestacions, en lloc de signar un artefacte directament, els usuaris creen algun tipus de document que capta la seva intenció darrere de signar l'artefacte i qualsevol reclamacions concretes s'està fent com a part d'aquesta signatura.
Marc d'atestat integral
El marc més comú és el Marc d'atestat integral
- defineix una standard format per a les certificacions que vinculen els subjectes, els artefactes que es descriuen, a metadades autenticades sobre l'artefacte
- proporciona un conjunt de predicats predefinits per comunicar metadades autenticades a través de les cadenes de subministrament de programari
Aprofundim una mica en el format de l'atestat.
An Atestat és un document signat digitalment que conté Declaracions.
L' Declaració és la capa intermèdia de l'atestat, que la vincula a un enllaç concret Assumpte i identificant sense ambigüitats els tipus de Predicat:
- Assumpte : La referència criptogràficament segura a l'artefacte (normalment mitjançant un hash), i
- Predicats: un conjunt específic reclamacions sobre aquest artefacte es coneix com a Declaració. Aquestes afirmacions es poden utilitzar per expressar (i més tard demostrar) qualsevol cosa que se us pugui acudir! Poden representar l'aprovació manual, la procedència d'artefactes, els resultats de proves automatitzades, una pista d'auditoria o més!
Quan aquesta declaració està signada criptogràficament, es coneix com a Atestat

D'aquesta manera, per exemple, l'Alícia crea una declaració sobre un artefacte i la signa amb la seva clau privada, creant una atestació.
- En Bob pot llavors verificar la signatura en aquella attestació, permetent-li confiar en les afirmacions a l'interior.
Aleshores, en Bob pot utilitzar aquestes afirmacions per decidir si permetre o no que s'utilitzi aquest artefacte.

Podrien les atestacions ajudar a resoldre la intoxicació per artefactes?
Després d'aquesta introducció a les Attestacions, tornem al nostre problema. Com ens poden ajudar les atestacions a resoldre el nostre problema, és a dir, a evitar la intoxicació per artefactes?
L'usuari maliciós va ser capaç de crear un artefacte evitant el mecanisme "oficial", és a dir, utilitzant el seu pipeline per generar l'artefacte.
Seria increïble si poguéssim demostrar que els artefactes que s'estan descarregant s'han creat amb l'oficial pipelines. Aquest és només un exemple del que podríem anomenar «punts de manipulació», però n'hi podria haver molts altres.

Com podeu veure a la imatge superior, els punts de manipulació són múltiples. D'aquesta manera, el consumidor pipeline (La prova CI en el nostre exemple) ha d'avaluar la integritat del procés de construcció així com la integritat del propi artefacte.
En el nostre exemple, l'artefacte enverinat s'ha creat introduint un nou artefacte (enverinat) pipeline que altera el procés de compilació. Però l'usuari maliciós podria haver estat capaç de:
- modificar el codi després de ser retirat del SCM per generar un binari maliciós
- substitueix el binari correcte produït per la compilació per qualsevol altre binari maliciós
- comprometre el Registre d'Artefactes i carregar un artefacte enverinat construït de qualsevol altra manera
- etcètera...
Com podeu veure, hi pot haver diversos punts de "manipulació".
Què és important aquí? Evidentment, protegir tots aquests punts de "manipulació". Però, al final, el més important és que el "consumidor" de l'artefacte pot avaluar la integritat d'aquest i decidir si hi continua o no.
Podem avaluar la integritat d'un artefacte de dues maneres.
Una és avaluant la procedència de l'artefacte.
Generant un Certificació de procedència, proporcionem metadades útils (degudament autenticades i no repudiades) sobre l'artefacte. En els exemples següents, utilitzarem SAL Xygeni (Capa d'atestats de programari per a la confiança), el component per generar, registrar i verificar attestacions de programari.

- name: Building ...
run: |
# mvn will compile and create target/MyApp.war
mvn clean package
- name: Generating provenance
run: |
#!/usr/bin/env bash
shopt -s expand_aliases
alias salt=$PWD/salt_pro/xygeni_salt/salt
echo " "
echo "-----------"
echo "Generating Provenance with CLI ..."
salt at slsa \
--basedir ${GITHUB_WORKSPACE}/target \
--key="${PRIVATE_KEY}" \
--public-key=${GITHUB_WORKSPACE}/Test1_public.pem \
--key-password=${KEY_PASSWD} \
--output-unsigned=${GITHUB_WORKSPACE}/cli_provenance_${PIPELINE}_unsigned.json \
--pipeline ${PIPELINE} --pretty-print \
--file ./MyApp.war
En el codi anterior, podeu veure que hi ha un pas que crea el fitxer war i un segon pas que genera el Certificació de procedènciaPer fer-ho, el pipeline utilitza la clau privada i també inclou la clau pública en l'atestat.
Darrere de les càmeres, Xygeni's sal L'ordre emmagatzema l'atestat en un llibre major (també conegut com a registre d'atestats, registre en el nostre cas, però podeu utilitzar qualsevol altre). Fet això, el consumidor pipeline pot incloure Xygeni Motor de verificació per verificar la procedència de l'artefacte i avaluar-ne la integritat.
- name: 'Verifying the attestation'
run: |
#!/usr/bin/bash
echo " "
echo "-------"
# Calculate sha256sum for the artifact
SHA_SUM=$(sha256sum ./MyApp.war | cut -f1 -d ' ')
# Recover the attestation Id from the sha256sum
ATT_ID=$(echo $(salt -q registry search --digest sha256:$SHA_SUM --format json) | jq -r .[-1].gitoidSha256)
echo " "
echo "-------"
# Download the provenance attestation
echo "Downloading the provenance attestation ..."
salt -q reg get --id=$ATT_ID --format=json > ${GITHUB_WORKSPACE}/provenance_kk.signed.json
echo " "
echo "-------"
echo "Verifying provenance ..."
salt verify \
--basedir ${GITHUB_WORKSPACE} \
--attestation=${GITHUB_WORKSPACE}/provenance_kk.signed.json \
--public-key=${GITHUB_WORKSPACE}/Test1_public.pem \
--file ./MyApp.war
El procés de verificació avalua:
- L' L'artefacte sha256sum és vàlid (és a dir, hi ha una atestació sobre aquest «tema»), i
- L' l'atestat està degudament autenticat (s'ha generat utilitzant la clau privada adequada)
Aquest procés de verificació pot avaluar que tant l'artefacte com l'atestat siguin vàlids.
Però, com recordareu, en el nostre cas, l'artefacte va ser generat per un "maliciós" pipeline (és a dir, no l'original per una modificació) pipeline). Aleshores hem de comprovar un altre aspecte: que l'artefacte ha estat generat per l'"original" pipeline, no cap altre.
Per fer això, només cal incloure una línia senzilla per comprovar aquesta condició, per exemple:
echo " "
echo "-------"
# Download the provenance attestation
echo "Downloading the provenance attestation ..."
salt -q reg get --id=$ATT_ID --format=json > ${GITHUB_WORKSPACE}/provenance_kk.signed.json
WFR=$(jq -r .payload ${GITHUB_WORKSPACE}/provenance_kk.signed.json |base64 -d | jq -r .predicate.buildDefinition.internalParameters.environment.GITHUB_WORKFLOW_REF)
echo $WFR | grep cicd_top10_3_salt\/.github\/workflows\/build.yml
Aquesta comprovació addicional fallarà si l'artefacte no ha estat generat per la nostra "segurança". pipeline.
Si l'artefacte va ser generat pel nostre original pipeline (cicd_top10_3_salt/.github/workflows/build.yml), l'ordre grep tindrà èxit, en cas contrari, fallarà i trencarà el pipeline i avortant qualsevol pas posterior.
El "constructor" pipeline és només un punt de manipulació a comprovar, però, com s'ha esmentat abans, hi ha altres punts de manipulació que hauríem de comprovar.
Per exemple, Què passa si el codi font ha estat manipulat després de la comprovació del repositori i abans de l'ordre de compilació? En aquest cas, el codi que s'ha de construir no és el mateix que s'emmagatzema a SCM.
Comprovar aquest punt de manipulació és tan fàcil com comprovar els hashes del material a cada pas.
SHA_ATT_MATERIAL=$(jq -r .payload ${GITHUB_WORKSPACE}/provenance_kk.signed.json | base64 -d | jq -r .predicate.attestations[0].predicate.materials[].digest[])
SHA_STEP_MATERIAL=$(jq -r .payload ${GITHUB_WORKSPACE}/provenance_kk.signed.json | base64 -d | jq -r .predicate.attestations[3].predicate.materials[0].digest[])
Conclusions
En resum, un Atestació de programari és una afirmació feta sobre un programari, és a dir, una declaració autenticada (metadades) sobre un artefacte de programari o una col·lecció d'artefactes de programari.
Les certificacions de programari són una generalització de la signatura de codi/artefactes en brut. La certificació és un document signat (en un format determinat, normalment basat en JSON) que associa metadades amb un artefacte. Representen proves que vinculen les entrades (materials) i les sortides (artefactes produïts) a cada pas de construcció.
Les atestacions proporcionen un registre verificable dels passos realitzats per construir els artefactes de programari finals, incloent-hi els materials d'entrada per a cada pas i les ordres de compilació executades.
En conclusió, les attestacions de programari són un mecanisme excel·lent per comprovar molts aspectes d'integritat diferents del nostre procés de compilació.
Has acabat la sèrie? No et preocupis! Pots tornar a 'Intoxicats Pipeline Execució (EPI)' o qualsevol altra publicació que torni a despertar el teu interès!
Estigueu atents, aprofundirem en les certificacions de programari i build security en futures entrades del blog.







