RO EN

Securitate aplicată pentru formulare web (1/4): ce vrea atacatorul și designul formularului

Securitate aplicată pentru formulare web (1/4): ce vrea atacatorul și designul formularului ✨ Imagine generată cu AI
Doru Bulubașa
09 noiembrie 2026
5 vizualizări

În articolul despre atacul asupra formularului nostru de contact am povestit cum site-ul a devenit, pentru o zi, infrastructura de phishing a altcuiva: 109 emailuri trimise către victime de pe domeniul nostru, de pe 41 de IP-uri închiriate în cloud. Partea cea mai incomodă nu a fost atacul în sine, ci bilanțul apărării: honeypot-ul a prins 2 mesaje din 167, timpul minim de completare a prins 50 până când bot-ul a învățat să aștepte, iar limita de trei mesaje pe oră per IP n-a contat deloc în fața a 41 de adrese care se rotesc.

Concluzia greșită ar fi că măsurile astea sunt inutile. Concluzia corectă e alta: fiecare măsură oprește un singur tip de atacator, iar un formular public are nevoie de mai multe straturi, fiecare pentru alt tip. Seria asta e partea practică de după postmortem: la ce folosește un atacator un formular, ce straturi de apărare există, cum arată fiecare în ASP.NET Core și un checklist pe care îl poți aplica pe orice formular, de la contact și newsletter la resetare de parolă.

Seria Securitate aplicată pentru formulare web:

La ce îi folosește unui atacator formularul tău

Primul pas nu e să alegi un CAPTCHA, ci să înțelegi ce poate obține cineva din formular. Un formular public e un endpoint care acceptă date de la oricine și declanșează efecte: trimite emailuri, scrie în baza de date, afișează conținut într-un panou de administrare, uneori costă bani. Fiecare efect e o țintă.

Abuz Ce câștigă atacatorul Ce te costă
Releu de email (confirmări trimise la adresa introdusă) Phishing trimis de pe domeniul tău, cu SPF și DKIM valide Reputația domeniului, contul de email restricționat
Spam și linkuri SEO către tine Backlinkuri, oferte, tentative de fraudă Timp, zgomot, mesaje reale îngropate
Injecție în emailul primit de echipă Linkuri sau HTML controlat de el în inbox-ul vostru Phishing intern, credibil, pentru că vine din propriul formular
Stored XSS în panoul de administrare Cod executat în browserul administratorului Sesiuni furate, acces la date
Enumerare (login, reset, newsletter) Lista adreselor care au cont la tine Ținte pentru credential stuffing și phishing
Endpoint-uri care costă (SMS, AI, upload) Venit din fraudă sau simplu sabotaj Factura ta

Observă că doar primul rând a fost incidentul nostru. Celelalte sunt la fel de reale, doar că fac mai puțin zgomot.

Formularele care costă bani

Un formular de contact abuzat îți strică reputația. Alte formulare îți golesc direct contul, pentru că fiecare trimitere declanșează o operație plătită:

  • Coduri prin SMS (verificare de telefon, autentificare în doi pași). Frauda numită SMS pumping sau trafic artificial umflat folosește formularul tău ca să trimită mii de SMS-uri către numere cu tarif special, din care atacatorul încasează o parte. Contramăsurile: limite per număr de destinație și per prefix de țară, o listă de țări permise și un plafon zilnic de cost la furnizorul de SMS.
  • Endpoint-uri AI (chatboți, generare de conținut). Fiecare cerere înseamnă tokeni plătiți. Ai nevoie de cote per utilizator sau per licență, de un cache pentru întrebările repetate și de o alertă de buget la furnizorul de model.
  • Upload de fișiere. Stocare, scanare antivirus, procesare. Limitează dimensiunea și tipul fișierului înainte de a-l accepta, nu după.

Regula generală: pentru orice endpoint public care declanșează o operație plătită, pune un plafon de cost, nu doar o limită de cereri.

Straturi, nu ziduri

Atacatorii nu sunt toți la fel. Un bot naiv completează toate câmpurile instant. Un bot răbdător așteaptă câteva secunde. Un bot serios rotește IP-uri din cloud. Iar la capătul scării stă un om plătit, sau o fermă care rezolvă CAPTCHA-uri pe bandă, pentru fracțiuni de cent. Tabelul de mai jos arată de ce niciun strat nu ajunge singur:

Strat Bot naiv Bot răbdător IP-uri rotative Om plătit
Design (nimic trimis la adresa vizitatorului) Elimină câștigul Elimină câștigul Elimină câștigul Elimină câștigul
Honeypot și timp minim Oprește Parțial Parțial Nu
Challenge (Turnstile, reCAPTCHA, hCaptcha) Oprește Oprește Oprește Nu
Rate limiting per IP Oprește Oprește Nu Nu
Rate limiting global pe endpoint Plafonează Plafonează Plafonează Plafonează
Scorarea conținutului Depinde de reguli Depinde de reguli Depinde de reguli Parțial

În serie trecem prin opt straturi: designul formularului, validarea și encoding-ul, honeypot-ul și timpul minim semnate pe server, challenge-ul, rate limiting-ul, scorarea conținutului, izolarea trimiterii de emailuri și monitorizarea. Primul rând din tabel e singurul care funcționează împotriva tuturor, pentru că nu încearcă să oprească atacatorul. Îi ia motivul de a veni. De acolo începem.

Stratul 1: designul formularului

Regula cea mai importantă din toată seria: nu trimite niciodată conținut controlat de vizitator la o adresă controlată de vizitator. Un formular care trimite o confirmare la adresa introdusă, cu numele sau mesajul introdus, este un serviciu gratuit de trimis emailuri, semnat cu domeniul tău. Exact asta a exploatat atacul nostru, iar eliminarea confirmării a fost decizia cu cel mai mare efect.

  • Confirmarea se afișează pe pagină, nu prin email. Vizitatorul vede imediat că mesajul a ajuns, iar tu nu mai trimiți nimic în afară.
  • Dacă trebuie neapărat un email (newsletter, cont nou), folosește double opt-in, cu un text complet fix: fără numele introdus, fără mesaj, doar linkul de confirmare. Un atacator poate trimite cel mult un email plictisitor, pe care nu-l controlează.
  • Răspunsuri identice pentru existent și inexistent. La resetare de parolă și la newsletter, mesajul trebuie să fie același, de exemplu „Dacă adresa există, vei primi un email”. Altfel formularul devine un instrument de enumerare.
  • Ce nu există nu poate fi abuzat. Câmpurile opționale, atașamentele și selectorul de destinatar sunt toate suprafață de atac. Păstrează doar ce folosești.

Un exercițiu util înainte de a scrie vreo linie de cod: ia fiecare formular de pe site și răspunde la două întrebări. Ce efecte declanșează? Și ar putea fi vreunul dintre ele folosit în numele altcuiva? Dacă răspunsul la a doua întrebare e da, schimbă designul înainte să adaugi protecții.

Ce urmează

Designul elimină motivul celui mai periculos abuz, dar formularul tot primește date ostile. În partea a doua intrăm în cod: limite de lungime și encoding, inclusiv în emailul primit de echipă, un token de timp semnat pe server cu Data Protection din ASP.NET Core și verificarea pe server a unui challenge Cloudflare Turnstile.