Admin-underdomenet stopper ikke CSRF: fire kontroller før lansering
Et nytt vertsnavn er en ny origin, ofte samme nettsted, så same-site-informasjonskapsler og enkle skjemaer krysser det. Kontroller tokens, porten og autorisasjonen.
Å flytte administrasjonsgrensesnittet til admin.example.com er en reell forbedring: det holder admin-informasjonskapsler unna offentlige sider, gir de to applikasjonene hver sin hurtigbuffer og lar deg rette en strengere nettverkspolicy mot ett vertsnavn. Men det er ikke en CSRF-kontroll, og det gjør ikke koden på det offentlige nettstedet trygg å holde åpen foran en innlogget administrator. Oppdelingen endrer hva nettleseren betrakter som en grense, ikke hva serveren kontrollerer, så gjør disse fire kontrollene før du sier det er ferdig.
Les origin og nettsted som to forskjellige ord
En origin er skjema, vert og port, så https://www.example.com og https://admin.example.com er forskjellige originer. Et nettsted, i SameSite-forstand, er skjema pluss registrerbart domene, så de to vertsnavnene er vanligvis samme nettsted. Forskjellen er hele fellen: SameSite-attributtet hjelper deg ikke mellom søsterunderdomener, fordi nettleseren ikke anser forespørselen som kryssnettsted i det hele tatt. Rett administrasjonsgrensesnittet mot et virkelig annet registrerbart domene, for eksempel admin-example.net, og forespørselen blir faktisk kryssnettsted, og det er der SameSite=Lax eller Strict begynner å gjøre arbeid du kan stole på.
Test det i nettleseren i stedet for å resonnere om det.
Last inn det offentlige nettstedet, åpne utviklerverktøyene og se hvilke informasjonskapsler nettleseren fester til en forespørsel mot admin-verten. Hvis kapselen ikke har Domain-attributt, er den bare for verten og blir på sitt eget navn; hvis den bærer Domain=example.com, reiser den til hver søster, og det nye underdomenet ga deg ingenting for den kapselen.
Skille lesing av svaret fra sending av forespørselen
Samme-origin-policyen begrenser lesing av svar på tvers av originer. Den stopper ikke en forespørsel fra å bli sendt, og den hindrer ikke et skjema i å bære påloggingsdata nettleseren allerede har. En enkel forespørsel, med skjemaets innholdstype eller en vanlig GET, leveres uten forhåndskontroll; CORS avgjør deretter om skriptet som kaller får lese svaret. CSRF lever helt på sendesiden.
Derfor trenger serveren en eksplisitt kontroll for tilstandsendrende operasjoner. Et synkroniseringstoken bundet til økten, eller en informasjonskapsel med dobbel innsending sammenlignet på serveren, dekker tilfellet; en Origin- eller Referer-sammenligning er verdt å legge til som en andre port, men ikke som den eneste, fordi ikke hver forespørsel bærer headeren og ikke hver proxy bevarer den. OWASPs veiledning for å forebygge CSRF behandler SameSite som ett lag blant flere nettopp av denne grunnen.
Avgjør hva nettverksporten egentlig beviser
En tillatt-liste over VPN-utganger foran admin-verten er god kontroll og en svak identitetspåstand. Den beviser at forespørselen kom fra en adresse VPN deler ut, som kan deles av alle på den utganger, og den sier ingenting om hvilken person eller enhet som står bak. Behandle den som et inngangsfilter, ikke som autentisering.
Hold den uavhengig av kontrollene på forespørselsnivå. Hvis listen er det eneste mellom en angriper og et tilstandsendrende endepunkt, fjerner én feilkonfigurert rute, én split-tunnel-klient eller én lånt bærbar PC kontrollen helt.
Logg også avvisninger utenfor de forventede områdene. En byge av dem er det mest nyttige signalet om at noen undersøker grensen du nettopp bygde, og stillhet er signalet om at filteret ikke nås i det hele tatt.
Hold informasjonskapsler, innlogging og autorisasjon eksplisitte
Kapselens omfang avgjør mesteparten av resultatet. En kapsel for foreldredomenet sendes til admin-verten, så en skriptinjeksjon på det offentlige nettstedet kan handle med en administratørs økt; en kapsel bare for verten kan ikke. Foretrekk formen bare for verten, legg til Secure-attributtet og bruk prefikset __Host- der plattformen støtter det, fordi prefikset krever Secure, Path=/ og ingen Domain-attributt. Les svarheaderen i stedet for kapselglasset: Set-Cookie: __Host-admin_session=...; Secure; Path=/; HttpOnly; SameSite=Lax, uten Domain-attributt. En nettleser forkaster en __Host--kapsel med Domain, så en kapsel som fortsatt vises på søsterverter er bevis for at prefikset aldri ble brukt.
Hold deretter autorisasjonen på serveren, per forespørsel, på hvert administrativt endepunkt, ikke bare ved innlogging. En forespørsel fra et tillatt nettverk må fortsatt autentiseres og autoriseres for operasjonen den ber om; vertsnavnet er ikke en aktør. Hvis den offentlige og den administrative applikasjonen deler en innloggingsflyt eller et øktlager, skriv ned det forholdet, fordi det er den korteste veien fra en feil på det offentlige nettstedet til en administrativ handling.
Kontroller grensen på nytt etter oppdelingen
Kjør de negative testene, ikke bare den lykkelige veien: et kryssnettstedsskjema uten token skal avvises, et token fra en annen økt skal avvises, og ingen GET skal endre tilstand. Kontroller kapselattributtene i utviklerverktøyene, bekreft at Origin-kontrollen utløses på en forespørsel som ikke stemmer, og prøv admin-verten utenfor VPN-området for å se filteret virke.
Ingenting av dette fjerner en XSS-feil inne i selve administrasjonsapplikasjonen. Et separat vertsnavn er en isolasjonsgrense på nettlesersiden med reell verdi, og det er ikke en erstatning for å hindre usikker kodekjøring eller for å beskytte forespørsler på serversiden. Etter oppdelingen er listen kortere enn den ser ut: egen origin, kapsler bare for verten, et token ved hver endring, et inngangsfilter du ikke stoler på som identitet, og autorisasjon avgjort per forespørsel.