Înapoi la Noutăți
Amenințări

Alpine Linux și-a reconstruit serverul GitLab după un atac prin breșa Ruby cu scor CVSS 10.0

Un atacator a bombardat timp de două zile GitLab-ul self-hosted al Alpine Linux cu configurații CI construite pentru CVE-2026-97229. Proiectul nu a găsit dovezi că exploit-ul a reușit, dar a reconstruit serverul de la zero și a aflat că simpla actualizare a GitLab lasă bug-ul din Ruby neatins.

Alpine Linux și-a reconstruit serverul GitLab după un atac prin breșa Ruby cu scor CVSS 10.0

Alpine Linux și-a reconstruit serverul GitLab după un atac prin breșa Ruby cu scor CVSS 10.0

Alpine Linux și-a reconstruit de la zero serverul GitLab self-hosted și a resetat parolele tuturor utilizatorilor, după ce un atacator a încercat timp de două zile să exploateze CVE-2026-97229, o vulnerabilitate de execuție de cod la distanță cu severitate maximă, chiar pe instanța care găzduiește sursele pachetelor distribuției. Proiectul a făcut public incidentul pe 28 octombrie.

Ce s-a întâmplat

CVE-2026-97229 are un scor CVSS de 10.0. Slăbiciunea nu se află în codul GitLab, ci în Onigmo, motorul de expresii regulate integrat în Ruby. GitLab compilează cu Ruby expresiile regulate din configurațiile CI, așa că un tipar special construit într-un fișier .gitlab-ci.yml poate ajunge la motorul vulnerabil și, în anumite condiții, poate executa cod pe server. GitLab a livrat remedierea pe 12 octombrie, corectând versiunea de Ruby inclusă în pachetele sale Linux și în imaginile oficiale de container. Cod de exploatare funcțional, de tip proof-of-concept, a apărut public a doua zi.

Serverul Alpine este cel care găzduiește aports, depozitul din care se construiesc toate pachetele distribuției. Pe 13 octombrie, proiectul l-a actualizat la GitLab 19.3.4 în loc de 19.3.5, lucru pe care echipa îl recunoaște drept o greșeală: 19.3.4 fusese anunțată inițial ca versiune corectată pentru ramura 19.3, însă avizul de securitate a fost ulterior modificat și o listează ca afectată.

Pe 20 octombrie, un cont proaspăt înregistrat a început să sondeze serverul. Pe 20 și 21 octombrie a trimis configurații CI special construite, care au prăbușit procesele worker ale GitLab de opt ori, au generat erori 502 și au făcut joburile CI să eșueze. În patru dintre aceste prăbușiri, atacatorul a parcurs o parte din lanțul de exploatare înainte de a eșua la pasul următor. Același cont a descărcat și imaginea publică de container GitLab a proiectului, ceea ce Alpine interpretează ca o încercare de a calibra exploit-ul pe build-ul exact folosit.

Alpine a blocat contul pe 23 octombrie. Atacatorul a revenit pe 25 și 26 octombrie și a încercat să își recapete accesul, fără succes.

De ce actualizarea GitLab nu a fost suficientă

Pe 22 octombrie, Alpine a trecut serverul la GitLab 19.3.6 și a presupus că problema e rezolvată. Pe 26 octombrie a descoperit că instanța era în continuare vulnerabilă. Motivul e simplu odată ce îl vezi: remedierea GitLab stă în Ruby-ul pe care GitLab îl livrează în propriile pachete și imagini. Imaginea de container a Alpine instalează separat un Ruby standard, așa că actualizarea GitLab nu a atins niciodată motorul de expresii regulate vulnerabil.

Aceeași lacună se aplică oricărei instalări GitLab compilate manual sau oricărei imagini personalizate care vine cu propriul Ruby. Aceste servere au nevoie de Ruby 3.3.13, 3.4.12 sau 4.0.9 (ori mai nou), pe lângă o versiune GitLab corectată. Ruby 3.2 a ajuns la sfârșitul ciclului de viață în aprilie și nu va primi remedierea, și totuși ghidul GitLab pentru instalări compilate manual încă listează 3.2 ca versiune minimă, iar niciunul dintre anunțurile de patch-uri GitLab din octombrie nu le spune administratorilor acestor instalări să actualizeze Ruby.

Pe 27 octombrie, Alpine a închis accesul la GitLab pentru toți, cu excepția dezvoltatorilor și a serverelor de build, și a început reconstrucția. Noul server a fost gata pe 28 octombrie, cu Ruby 3.3.13 sau mai nou, chei secrete GitLab noi și resetare obligatorie a parolei pentru fiecare cont. Este testat înainte de a fi redeschis publicului.

Ce poate și ce nu poate exclude Alpine

Proiectul nu a găsit niciun semn că atacatorul ar fi reușit să execute cod: sondele de timing nu au arătat întârzieri, nu au existat fișiere, chei, hook-uri sau procese neașteptate și nicio dată privată nu a ieșit printr-o cerere web sau API pe care Alpine o poate vedea.

Asta nu echivalează însă cu o dovadă de siguranță. O exploatare reușită a acestei breșe nu lasă nicio prăbușire și nicio urmă în jurnalele web. O parte din jurnalele din zilele atacului s-au pierdut, inclusiv jurnalele joburilor de fundal și sistemul de fișiere al vechiului container, iar nici Alpine, nici furnizorul de găzduire nu înregistrau conexiunile de rețea de ieșire. Pentru că dovezile necesare pentru a confirma sau exclude execuția de cod nu mai există, Alpine a ales să trateze serverul ca fiind compromis și să îl reconstruiască.

Dacă atacul ar fi reușit, datele expuse ar fi putut include numele, adresele de e-mail și adresele IP ale utilizatorilor, hash-uri de parole, secrete pentru autentificarea în doi pași, variabile CI/CD, token-uri de runner, credențiale de webhook și de push mirror, token-uri personale de acces (stocate ca hash), depozite private, precum și issue-uri și merge request-uri confidențiale. Dincolo de resetarea parolelor și de noile chei secrete, Alpine nu a precizat încă dacă token-urile de runner, variabilele CI/CD, token-urile de acces sau credențialele de integrare stocate pe server au fost înlocuite.

Pachetele par curate

Marea îngrijorare pentru întregul ecosistem este manipularea lanțului de aprovizionare, iar aici veștile sunt mai bune. Alpine a verificat că fiecare modificare din aports intrată între 20 și 22 octombrie a venit printr-un push înregistrat al unui dezvoltator cunoscut și a confruntat acest lucru cu înregistrări la care atacatorul nu putea ajunge: copia locală a depozitului de la un dezvoltator și toate cele 45 de servere de build. Toate pachetele construite între 20 și 24 octombrie, precum și lansările din 21 octombrie, inclusiv fișierele minirootfs din care se construiesc imaginile oficiale Alpine pentru Docker, corespund acestor modificări verificate. Verificările sunt extinse până pe 27 octombrie, ziua în care serverul a fost închis. Cheile care semnează pachetele și lansările Alpine nu au fost niciodată stocate pe serverul GitLab.

Ce servere GitLab sunt expuse

GitLab.com și GitLab Dedicated sunt deja corectate. Pentru serverele self-managed, versiunile remediate sunt 19.4.2, 19.3.5 și 19.2.8, iar lansările din 21 octombrie (19.5.1, 19.4.3, 19.3.6, 19.2.9, 19.1.9, 19.0.10 și 18.11.13) sunt cele mai noi pe fiecare ramură; ele închid și CVE-2026-110264, o breșă separată tot în zona expresiilor regulate. Ramurile 19.5, 19.1, 19.0 și 18.11 nu sunt listate ca afectate.

Proof-of-concept-ul public are nevoie mai întâi de acces de scriere: atacatorul trimite un fișier CI malițios și o cale de fișier cu caractere UTF-8 într-un branch al unui proiect public, după care doar cererea finală de CI lint rămâne neautentificată. Această barieră dispare pe serverele unde utilizatorii noi se pot înregistra singuri și pot crea proiecte. Nu se știe încă în ce fel raportul original către GitLab, încă privat, evită pasul de scriere, iar Alpine nu a spus cum au ajuns configurațiile CI ale atacatorului pe server. CVE-ul nu figura în catalogul CISA al vulnerabilităților exploatate activ la data de 28 octombrie.

Ce e de făcut

  • Pachet Linux sau imagine oficială de container: actualizați la cea mai nouă versiune de pe ramura folosită.
  • Instalare compilată manual sau imagine personalizată cu propriul Ruby: actualizați GitLab și treceți Ruby la 3.3.13, 3.4.12, 4.0.9 sau mai nou. Serverele rămase pe 19.3.4 ar trebui să treacă la 19.3.6.
  • Nu puteți actualiza imediat: restricționați accesul anonim la proiectele publice, împiedicați utilizatorii neverificați să creeze sau să scrie în proiecte publice, ori blocați ruta de CI lint. Aceste măsuri acoperă doar ruta de exploatare cunoscută și nu repară motorul în sine.
  • Căutați urme de exploatare: GitLab a publicat șase reguli de detecție în format Sigma, care urmăresc tipare ostile în avertismentele regexp din CI și în cererile GraphQL ciLint, căi de fișier neobișnuit de lungi cu caractere non-ASCII și rapoarte de crash Ruby care indică Onigmo. Verificați și fișierele deținute de utilizatorul git în /tmp, procesele copil neașteptate ale Puma sau Sidekiq, conexiunile de ieșire, precum și crontab-urile sau cheile SSH modificate. Orice semn de execuție înseamnă tratarea serverului ca fiind compromis și rotirea secretelor din gitlab-secrets.json, a tuturor variabilelor CI/CD, token-urilor de runner și token-urilor de acces.
  • Reduceți suprafața de atac: limitați cine poate crea conturi și token-uri personale de acces.
  • Utilizatori Alpine: setați o parolă nouă prin „Forgot your password?" după redeschiderea serverului și schimbați-o oriunde ați refolosit-o; Alpine a observat încercări de credential stuffing cu parole scurse de pe alte site-uri. Cei care folosesc imaginea alpinelinux/gitlab trebuie să descarce din nou tag-ul 19.3.6, pentru că doar imaginea publicată pe 27 octombrie conține Ruby 3.3.13. Pachetele Ruby ale Alpine sunt deja corectate (3.4.12 pe Alpine 3.22, 3.23, 3.24 și edge; 3.3.13 pe 3.21), iar apk upgrade le instalează.

Dezvoltatorii Ruby precizează că bug-ul contează doar pentru programele care compilează o expresie regulată dintr-un text controlat de atacator și că setarea Regexp.timeout nu oferă nicio protecție.

Lecția pe care Alpine a învățat-o pe pielea proprie este că actualizarea unei aplicații nu spune nimic despre runtime-ul de dedesubt. O simplă verificare a versiunii GitLab expuse ar fi trecut; doar un test al comportamentului real, sau un inventar care include și build-ul de Ruby, ar fi prins problema. Exact această diferență dintre „corectat pe hârtie" și „corectat în practică" este ceea ce serviciul nostru de scanare de vulnerabilități este construit să scoată la iveală în infrastructura voastră expusă la internet, înainte ca fișierul CI al altcuiva să o facă în locul vostru.

DISTRIBUIE