mini-cms-mcp

Costin Pietraru

Audit de securitate făcut de un alt AI: ce a găsit în CMS-ul meu

Un alt AI a auditat securitatea mini-cms-mcp. A găsit trei probleme mici, rezolvate în aceeași zi; una dintre soluțiile propuse era incompletă.

Securitate mini-cms-mcp AI

Am cerut unui alt AI un audit complet de securitate pentru mini-cms-mcp. Raportul a verificat șase aspecte, de la arhitectura codului până la site-ul care îl folosește deja, și le-a apreciat pe toate pozitiv: patru au primit calificativul „excelent” sau „foarte bun”. Auditorul a făcut și cinci recomandări. Trei s-au dovedit întemeiate, niciuna nu permitea accesul unei persoane din afară la conținut sau la cod, iar toate trei au fost rezolvate în aceeași zi.

Cel mai util lucru nu au fost însă notele, ci faptul că una dintre soluțiile propuse de auditor era incompletă.

De ce am cerut auditul altui AI?

Codul mini-cms-mcp l-am scris lucrând cu Claude, asistentul AI de la Anthropic. Tot Claude a scris și testele automate care încearcă să-l atace; în ziua auditului erau 282.

Orice autor care își verifică singur lucrarea are aceeași problemă: vede ce a vrut să scrie, nu ce a scris efectiv. De aceea, programatorii își dau codul la verificat unui coleg (code review).

Eu i-am cerut auditul unui model de la altă firmă, care nu mai văzuse proiectul: Gemini 3.8 Flash de la Google, cu nivelul de raționament „High”, în mediul de dezvoltare Antigravity. Cererea mea a avut trei rânduri: unde se află codul pe GitHub, un site care folosește deja acest CMS și rugămintea de a face un audit complet de securitate.

Cererea de audit trimisă lui Gemini și primul tabel din raport, cu nota pentru fiecare aspect verificat
Cererea trimisă și primul tabel din raport: nota pentru fiecare dintre cele șase aspecte verificate, de la arhitectură până la site-ul cinesunt.info.

Ce note a dat auditorul?

Ce a verificatNotaPe ce se sprijină nota
Arhitectura generalăExcelentănu există bază de date SQL, deci nici atacuri prin injecție SQL; nu folosește framework-uri; nu conține funcții care execută cod primit din afară
Ce are voie AI-ul să facăExcelentăAI-ul modifică doar conținutul, niciodată codul sau configurarea; cheia care permite actualizarea codului nu ajunge la AI
AutentificareaFoarte bunăserverul păstrează doar amprentele criptografice ale cheilor, nu cheile; conectarea prin OAuth cere protecția PKCE
Filtrul de HTMLFoarte bunarticolele pot conține doar etichete și atribute dintr-o listă strictă; browserul execută doar scripturile marcate de site (Content-Security-Policy)
Testele automateValidatetoate cele 282 de teste trec
Site-ul în funcțiune (cinesunt.info)Securizatantetele de securitate sunt prezente; dosarele interne nu pot fi accesate din internet

Auditorul a verificat și site-ul cinesunt.info, din exterior: fișierele de configurare și de date nu pot fi descărcate, iar adresa prin care AI-ul comunică cu site-ul acceptă doar cereri de tip POST. Raportul se încheie cu aprecierea că proiectul are o „maturitate de securitate remarcabilă pentru un CMS personalizat”.

Ce probleme a găsit?

Raportul conține cinci recomandări. Nu le-am aplicat imediat. I-am dat raportul lui Claude și i-am cerut să verifice fiecare punct direct în cod și să-l testeze, nu să-l accepte pe încredere.

RecomandareaGravitatea, după auditorRezultatul verificării
Când site-ul descarcă o imagine de pe internet, filtrul care blochează adresele interne avea o breșă la adresele IPv6medieÎntemeiată și mai extinsă decât arăta raportul. Rezolvată pentru toată categoria de adrese.
Pagina de actualizare a codului se deschidea chiar și atunci când actualizarea era dezactivatămedie spre micăÎntemeiată, dar pagina afișa doar un formular gol. Acum răspunde cu eroarea 404.
Un anumit identificator (atributul id) pus într-un articol ar putea bloca Google AnalyticsmicăNu se confirmă în forma descrisă, dar se confirmă pentru un nume asemănător. Aceste nume nu mai sunt acceptate în articole.
Protecția dosarului de date depinde de regulile serverului (.htaccess)informativăRezolvată deja: instalarea se oprește singură dacă datele pot fi descărcate din internet.
Verificarea automată de după o actualizare nu controlează certificatul HTTPS al site-uluiinformativăAcceptată ca atare: cererea nu transmite nicio informație secretă.

De ce un audit trebuie verificat înainte de aplicare?

Prima recomandare privea imaginile preluate de pe internet. Când AI-ul îi dă site-ului adresa unei imagini, serverul o descarcă singur. De aceea trebuie să refuze adresele la care are acces doar el: rețeaua internă a găzduirii sau adresa la care serverele din cloud își păstrează datele de configurare.

Acest tip de atac se numește SSRF: serverul este păcălit să ceară, în numele atacatorului, date din propria rețea.

Auditorul a observat că o adresă internă poate fi ascunsă în interiorul unei adrese IPv6, formatul mai nou al adreselor de internet, și că lista de adrese interzise nu recunoștea una dintre aceste forme. Avea dreptate.

Soluția propusă era un filtru inclus în PHP. L-am testat: recunoaște adresa internă doar când este scrisă într-un anumit fel. Aceeași adresă, scrisă altfel, trecea de filtru. Pentru rețea, destinația era aceeași; pentru filtru, era alt șir de caractere.

Verificarea a descoperit și o formă de scriere pe care raportul nu o menționa deloc.

Reparația nu mai încearcă să enumere toate formele interzise. La IPv6, serverul acceptă acum doar adresele publice, adică pe cele folosite de site-urile obișnuite. Orice altă adresă este refuzată, indiferent de forma în care este scrisă. Filtrul din PHP a rămas și el, ca protecție suplimentară.

A treia recomandare susținea că un articol care conține un element cu un anumit identificator (atributul id) ar putea bloca Google Analytics. Explicația: în browser, identificatorul unui element devine automat și numele unei variabile globale, iar scriptul de măsurare ar găsi acel nume deja ocupat.

Am creat o pagină de test și am deschis-o în browser. Pentru numele indicat de auditor, problema nu apare: scriptul Google se află în antetul paginii, rulează înaintea articolului și își creează singur variabila, iar un identificator care apare mai târziu în pagină nu o mai poate înlocui.

Același test a arătat însă că problema apare pentru un alt nume, pe care scriptul Google îl citește abia după încărcarea paginii. Prin urmare, filtrul elimină acum din articole identificatorii care folosesc numele rezervate scriptului de măsurare. Exemplul auditorului era greșit, dar problema semnalată era reală.

Un audit bun îți arată unde să cauți. Nu îți spune și cum să repari. Dintre cele cinci recomandări, una avea diagnosticul corect, dar soluția incompletă; una avea exemplul greșit, dar problema reală; iar una era deja rezolvată. Diferența o face verificarea fiecărui punct în cod, cu un test care eșuează înainte de reparație și trece după ea.

Cât de grave erau problemele?

Niciuna nu permitea accesul unei persoane din afară.

  • Breșa de la descărcarea imaginilor putea fi folosită doar cu cheia de scriere, pe care o au numai proprietarul site-ului și AI-ul care îl administrează în numele lui.
  • Identificatorul care blochează o variabilă cerea tot cheia de scriere, fiindcă doar cu ea se pot scrie articole. Iar cine are această cheie poate dezactiva oricum Google Analytics din setările site-ului.
  • Pagina de actualizare afișa doar un formular gol. Trimiterea lui era deja refuzată, iar codul nu putea fi modificat fără cheia de cod, o a treia cheie, pe care AI-ul nu o primește niciodată.

Reparațiile nu au fost inutile. Sunt exact detaliile care îi scapă celui care scrie codul și pe care le observă cel care îl citește pentru prima dată.

Ce s-a schimbat în cod?

Versiunea 0.15.2, publicată pe GitHub și instalată pe cele trei site-uri pe care le administrez cu mini-cms-mcp, aduce trei modificări:

  • la descărcarea imaginilor de pe internet, serverul acceptă doar adrese IPv6 publice;
  • pagina de actualizare nu mai poate fi deschisă când actualizarea este dezactivată;
  • identificatorii care ar putea bloca variabilele Google Analytics sunt eliminați din articole, iar răspunsul îi spune AI-ului ce a fost eliminat.

Numărul testelor automate a crescut de la 282 la 285. Fiecare dintre cele trei teste noi a fost rulat mai întâi pe codul vechi, unde eșuează, și abia apoi pe codul reparat, unde trece. Un test care trece și pe codul vechi nu dovedește nimic. Unul care eșuează pe codul vechi face ca problema să nu poată reveni fără să fie observată.

Ce nu dovedește un astfel de audit?

Nu este un test de penetrare. Auditorul a citit codul și a verificat site-ul din exterior, fără să încerce să pătrundă în el. Un specialist care atacă un site ore în șir poate găsi probleme pe care simpla citire a codului nu le scoate la iveală.

Nu este o certificare. Niciun site nu este imposibil de spart. Un raport bun arată doar că, la data verificării, nu s-a găsit o cale ușoară de atac.

Nu înlocuiește verificarea. Două modele AI s-au corectat unul pe altul, dar fiecare recomandare a fost acceptată sau respinsă pe baza unui test, nu după cât de convingătoare părea.

Întrebări frecvente

Poate un AI să facă un audit de securitate?

Poate citi atent codul, poate face verificări din exterior și poate găsi probleme reale: în cazul de față, a găsit trei. Nu înlocuiește însă un test de penetrare făcut de un specialist, iar recomandările lui trebuie verificate în cod înainte de a fi aplicate.

De ce nu a făcut Claude auditul propriului cod?

Pentru că autorul unui cod vede ce a vrut să scrie. Claude scrisese atât codul, cât și testele; un model al altei firme, care nu cunoștea istoria proiectului, l-a citit fără idei preconcepute. Abia apoi a primit Claude raportul, ca să verifice fiecare recomandare.

Ce înseamnă SSRF?

SSRF (Server-Side Request Forgery) este un atac în care serverul este păcălit să descarce date de la o adresă la care are acces doar el, de exemplu din rețeaua internă a găzduirii. Protecția constă în refuzarea oricărei adrese care nu este publică și în conectarea exact la adresa care a fost verificată.

Putea oricine să folosească problemele găsite?

Nu. Primele două cereau cheia de scriere, pe care o are doar cine administrează site-ul. Pagina de actualizare nu permitea nicio modificare fără cheia de cod, pe care AI-ul nu o primește niciodată.

Pot verifica și eu codul?

Da. mini-cms-mcp este open source și se află pe GitHub; codul poate fi citit integral într-o după-amiază. Dacă găsești o problemă, scrie-mi prin pagina de contact.

Surse

← Toate articolele