Mutarea interfeței de administrare pe admin.example.com este o îmbunătățire reală: ține cookie-urile de administrare departe de paginile publice, dă celor două aplicații cache-uri separate și vă permite să direcționați o politică de rețea mai strictă către un singur nume de gazdă. Dar nu este un control CSRF și nu face codul site-ului public sigur să fie lăsat deschis în fața unui administrator autentificat. Separarea schimbă ce consideră browserul o graniță, nu ce verifică serverul, așa că faceți aceste patru verificări înainte de a spune că e gata.

Citiți origine și site ca două cuvinte diferite

O origine este schemă, gazdă și port, deci https://www.example.com și https://admin.example.com sunt origini diferite. Un site, în sensul SameSite, este schemă plus domeniu înregistrabil, deci acele două nume de gazdă sunt de obicei același site. Această diferență este toată capcana: atributul SameSite nu vă va ajuta între subdomenii surori, pentru că browserul nu consideră deloc cererea ca fiind între site-uri. Îndreptați interfața de administrare către un domeniu înregistrabil cu adevărat diferit, cum ar fi admin-example.net, și cererea devine într-adevăr între site-uri, și acolo SameSite=Lax sau Strict începe să facă o muncă pe care vă puteți baza.

Testați-o în browser în loc să raționați despre ea.

Încărcați site-ul public, deschideți instrumentele pentru dezvoltatori și vedeți ce cookie-uri atașează browserul la o cerere către gazda de administrare. Dacă cookie-ul nu are atributul Domain, este doar pentru gazdă și rămâne pe propriul nume; dacă poartă Domain=example.com, călătorește la fiecare soră, iar noul subdomeniu nu v-a adus nimic pentru acel cookie.

Separați citirea răspunsului de trimiterea cererii

Politica aceleiași origini restricționează citirea răspunsurilor între origini. Nu oprește trimiterea unei cereri și nu împiedică un formular să poarte acreditările pe care browserul le are deja. O cerere simplă, cu tip de conținut de formular sau un GET simplu, este livrată fără verificare prealabilă; apoi CORS decide dacă scriptul apelant poate citi răspunsul. CSRF trăiește în întregime pe partea de trimitere.

De aceea serverul are nevoie de o verificare explicită pentru operațiile care schimbă starea. Un token de sincronizare legat de sesiune, sau un cookie cu trimitere dublă comparat pe server, acoperă cazul; o comparație Origin sau Referer merită adăugată ca a doua poartă, dar nu ca singura, pentru că nu fiecare cerere poartă antetul și nu fiecare proxy îl păstrează. Ghidul OWASP pentru prevenirea CSRF tratează SameSite ca un strat printre mai multe exact din acest motiv.

Decideți ce dovedește de fapt poarta de rețea

O listă de ieșiri VPN permise în fața gazdei de administrare este un control bun și o afirmație de identitate slabă. Dovedește că cererea a venit de la o adresă pe care VPN-ul o alocă, care poate fi partajată de toți cei de pe acea ieșire, și nu spune nimic despre ce persoană sau dispozitiv este în spate. Tratați-o ca filtru de intrare, nu ca autentificare.

Țineți-o independentă de verificările la nivel de cerere. Dacă lista este singurul lucru dintre un atacator și un punct final care schimbă starea, o rută configurată greșit, un client split-tunnel sau un laptop împrumutat elimină complet controlul.

Înregistrați și respingerile din afara intervalelor așteptate. Un val al acestora este cel mai util semnal că cineva sondează granița pe care tocmai ați construit-o, iar liniștea este semnalul că filtrul nu este deloc atins.

Țineți cookie-urile, autentificarea și autorizarea explicite

Amploarea cookie-ului decide cea mai mare parte a rezultatului. Un cookie al domeniului părinte este trimis gazdei de administrare, deci o injecție de script pe site-ul public poate acționa cu sesiunea unui administrator; un cookie doar pentru gazdă nu poate. Preferați forma doar pentru gazdă, adăugați atributul Secure și folosiți prefixul __Host- acolo unde platforma îl susține, pentru că prefixul cere Secure, Path=/ și niciun atribut Domain. Citiți antetul răspunsului, nu borcanul de cookie-uri: Set-Cookie: __Host-admin_session=...; Secure; Path=/; HttpOnly; SameSite=Lax, fără atribut Domain. Browserul aruncă un cookie __Host- care poartă Domain, deci un cookie care încă apare pe gazdele surori este dovada că prefixul nu a fost niciodată aplicat.

Apoi țineți autorizarea pe server, pentru fiecare cerere, la fiecare punct final administrativ, nu doar la autentificare. O cerere dintr-o rețea permisă trebuie totuși autentificată și autorizată pentru operația pe care o cere; numele gazdei nu este un actor. Dacă aplicațiile publică și administrativă împart un flux de autentificare sau un depozit de sesiuni, scrieți acea relație, pentru că este cea mai scurtă cale de la un defect pe site-ul public la o acțiune administrativă.

Verificați din nou granița după separare

Rulați testele negative, nu doar calea fericită: un formular între site-uri fără token trebuie respins, un token din altă sesiune trebuie respins și niciun GET nu trebuie să schimbe starea. Verificați atributele cookie-urilor în instrumentele pentru dezvoltatori, confirmați că verificarea Origin se declanșează la o cerere nepotrivită și încercați gazda de administrare din afara intervalului VPN pentru a vedea filtrul în acțiune.

Nimic din toate acestea nu elimină un defect XSS în interiorul aplicației de administrare. Un nume de gazdă separat este o graniță de izolare pe partea browserului cu valoare reală și nu înlocuiește prevenirea execuției de cod nesigur sau protecția cererilor pe partea serverului. După separare lista este mai scurtă decât pare: origine distinctă, cookie-uri doar pentru gazdă, un token la fiecare modificare, un filtru de intrare în care nu aveți încredere ca identitate și autorizare decisă pentru fiecare cerere.

Articole similare