Securitatea lanțului de aprovizionare software pare o problemă a organizațiilor care au o funcție dedicată de securitate, iar încadrarea aceasta induce în eroare. O echipă mică ce ține în aer o mână de servicii depinde de obicei de sute de pachete pe care nimeni din ea nu le-a citit vreodată, aduse la momentul build-ului din registre pe care nu le controlează și care rulează scripturi de instalare pe mașini unde stau credențialele de deployment.
Expunerea nu este proporțională cu mărimea companiei. Este proporțională cu numărul de dependențe și cu gradul de automatizare a build-ului, iar echipele mici au adesea mai mult din primul și mai puțin control asupra celui de al doilea decât organizațiile care vorbesc public despre subiect.
Aritmetica incomodă: aplicația ta are poate o duzină de dependențe directe și câteva sute de dependențe tranzitive. Duzina ai ales-o tu. Restul, nu, nu ai citit niciuna dintre ele, iar oricare dintre ele, în momentul în care rulează un script de instalare, primește exact aceleași drepturi ca procesul tău de build. Aceasta este suprafața reală de atac și nu se vede deloc din lista de dependențe pe care ai scris-o tu.
Securitatea lanțului software începe la instalare
Momentul periculos de obicei nu este rularea codului. Este instalarea lui.
Managerele de pachete permit rularea de scripturi în timpul instalării, ceea ce înseamnă că un pachet compromis sau rău intenționat rulează cu privilegiile celui care a pornit instalarea. Pe o mașină de dezvoltare acelea sunt credențialele lui. Într-un pipeline de build sunt cheile de deployment, iar asta e considerabil mai rău.
Trei tipare de atac explică majoritatea incidentelor reale.
Typosquatting. Un pachet cu un nume care diferă cu un singur caracter de al unuia popular, publicat și lăsat să aștepte o comandă de instalare scrisă greșit. Ieftin de pus la punct și eficient la scară.
Compromiterea contului unui pachet legitim. Un pachet folosit pe scară largă, al cărui întreținător a rămas fără credențiale în urma unui furt, actualizat cu ceva dăunător. Este cel mai greu de apărat, pentru că nici numele, nici numărul de descărcări nu arată nimic în neregulă.
Dependency confusion. Un pachet public publicat sub numele unuia dintre pachetele tale interne, în timp ce un resolver configurat greșit preferă registrul public celui privat. Este integral o problemă de configurare și integral evitabilă.
Niciunul dintre aceste atacuri nu cere ca cineva să te vizeze pe tine anume, și exact acesta este punctul. Sunt oportuniste și scalează.
Controale care merită efortul la scară mică
Pune lockfile-ul în repository și instalează din el. Un lockfile fixează versiunile exacte și amprentele lor. Instalarea din manifest rezolvă în schimb versiuni proaspete la momentul build-ului, ceea ce face build-ul nereproductibil și lasă o modificare din amonte să ajungă în producție fără nicio revizuire. Folosește comanda de instalare care eșuează atunci când lockfile-ul nu corespunde, nu pe cea care îl actualizează în tăcere.
Dezactivează scripturile de instalare acolo unde poți. Multe ecosisteme permit lucrul acesta, iar cele mai multe pachete nu au nevoie de ele. Este cea mai mare reducere de expunere pe care o poți obține fără unelte suplimentare, iar puținele pachete care se strică sunt exact acelea despre care merită să știi.
Automatizează alertele de vulnerabilitate, apoi tratează-le pe rând. Scanerele produc mai multe rezultate decât poate duce o echipă mică, iar modul de eșec nu este alerta ratată, ci ignorarea tuturor alertelor pentru că cele mai multe nu au legătură cu tine. Filtrează pe ceea ce este cu adevărat accesibil din codul tău și acționează asupra acelor cazuri. O coadă pe care nu o citește nimeni valorează mai puțin decât nicio coadă.
Fixează și uneltele de build. Imaginea de container, versiunea de runtime și acțiunea sau plugin-ul pe care le apelează pipeline-ul sunt tot dependențe, iar referirea la o etichetă mutabilă în loc de o amprentă imuabilă înseamnă că build-ul tău se schimbă fără tine.
Separă credențialele de build de tot restul. Un pipeline care poate face deployment nu ar trebui să dețină credențiale cu care se poate face ceva în plus, iar un build compromis nu ar trebui să poată ajunge la datele din producție.
Ce îți spune și ce nu îți spune un SBOM
Un inventar al componentelor software, pe scurt SBOM, enumeră ce se află în aplicația ta, iar valoarea lui stă în a răspunde repede la o singură întrebare: ne afectează?
Întrebarea aceea lua înainte zile întregi. Când o componentă folosită pe scară largă se dovedește vulnerabilă, o organizație cu un inventar actualizat răspunde în minute, iar una fără el petrece o săptămână căutând. Diferența aceasta este tot argumentul și este motivul pentru care adoptarea SBOM este împinsă înainte ca practică de bază, nu ca un control avansat.
Ce nu face este să te facă sigur. Un inventar este o listă, nu o apărare. Nu îți spune dacă o vulnerabilitate listată este accesibilă în codul tău, dacă ea contează în configurația ta sau dacă ceva a fost deja compromis. Echipele care generează unul și îl arhivează au adăugat un document, nu un control.
Generează-l din build, ca să descrie ce a fost livrat cu adevărat și nu ce pretindea manifestul. Păstrează-l pe cel care corespunde fiecărei versiuni lansate. Și acceptă că valoarea lui stă integral în viteza cu care vei răspunde la o întrebare care ți se va pune sub presiune.
Unde se lovesc cu adevărat echipele mici
Rareori de o compromitere exotică a unui pachet. De lucruri obișnuite.
Secrete în repository, care rămân în istoric după ștergere și sunt găsite de scanere automate în câteva minute de la un push. O dependență veche de trei ani cu un exploit publicat și fără cale de actualizare, fiindcă upgrade-ul a fost amânat până a devenit un proiect în sine. Pipeline-uri de build cu permisiuni excesive, unde un pull request venit dintr-un fork rulează cu accese pe care nu ar trebui să le aibă. Nimeni care să se uite, așa că o compromitere se prelungește pentru că nicio alertă nu ajunge vreodată în fața unui om.
Concluzia lipsită de strălucire este că menținerea dependențelor la zi înseamnă în practică cea mai mare parte din securitatea lanțului software. Costul mentenanței software pe care echipele îl tratează ca opțional este exact aceeași muncă, iar amânarea lui transformă un upgrade de rutină într-o urgență cu un exploit atașat.
Un punct de plecare proporționat
Pentru o echipă mică, în ordinea aceasta: scoate secretele din repository și rotește tot ce a fost expus. Pune lockfile-urile în repository și instalează strict din ele. Pornește alertele pe dependențe și tratează-le săptămânal, nu continuu. Fixează uneltele de build pe referințe imuabile. Redu permisiunile pipeline-ului la minimul necesar. Generează un SBOM pentru fiecare versiune lansată, odată ce restul stă în picioare.
Secvența aceasta acoperă amenințările realiste fără o funcție dedicată de securitate, iar fiecare pas se măsoară în ore, nu în săptămâni. Controalele de dincolo de ea, atestarea provenienței, build-urile reproductibile și artefactele semnate, au o valoare reală și aparțin unei etape în care bazele stau deja bine.
Mecanik analizează și întărește pipeline-urile de build ca parte din analiza de securitate a aplicațiilor. Ce găsim nu este aproape niciodată o compromitere sofisticată. Este un token în repository și o dependență pe care nimeni nu a mai actualizat-o din ziua în care a fost aleasă.
Întrebări frecvente
De ce instalarea pachetelor este momentul riscant? Pentru că managerele de pachete permit rularea de scripturi în timpul instalării, cu privilegiile celui care a pornit instalarea. Pe o mașină de dezvoltare înseamnă credențialele lui; într-un pipeline de build înseamnă cheile de deployment. Codul nici măcar nu trebuie executat de aplicația ta ca să facă pagube.
Ce este dependency confusion? Un atac în care un pachet public este publicat sub numele unuia dintre pachetele tale interne, iar un resolver configurat greșit preferă registrul public celui privat. Nu cere ca cineva să te vizeze pe tine anume și poate fi prevenit integral prin configurarea corectă a resolverului.
Ce îți dă de fapt un SBOM? Un răspuns rapid la o singură întrebare: ne afectează? Cu un inventar actualizat durează minute; fără el durează o săptămână de căutat. Nu îți spune dacă o vulnerabilitate listată este accesibilă în codul tău și nici dacă ceva a fost deja compromis, așa că un SBOM generat și arhivat rămâne un document, nu un control.
Trebuie să pun lockfile-ul în repository? Da, și să instalezi strict din el, cu comanda care eșuează atunci când lockfile-ul nu corespunde, nu cu cea care îl actualizează. Instalarea din manifest rezolvă versiuni proaspete la momentul build-ului, face build-urile nereproductibile și lasă o modificare din amonte să ajungă în producție fără nicio revizuire.
De unde ar trebui să înceapă o echipă mică? Scoate secretele din repository și rotește tot ce a fost expus, pune lockfile-urile în repository și instalează strict, activează alertele pe dependențe și tratează-le săptămânal, fixează uneltele de build pe referințe imuabile, redu permisiunile pipeline-ului, apoi generează un SBOM pentru fiecare versiune lansată. Fiecare pas se măsoară în ore, nu în săptămâni.
Comentarii