Admin-subdomajno ne haltigas CSRF: kvar kontroloj antaŭ lanĉo
Nova gastnomo estas nova origino, ofte la sama retejo, do same-site kuketoj kaj simplaj formularoj trapasas ĝin. Kontrolu la ĵetonojn, la pordegon kaj la rajtigon.
Movi la administran interfacon al admin.example.com estas reala plibonigo: ĝi tenas administrajn kuketojn for de publikaj paĝoj, donas al la du aplikaĵoj apartajn kaŝmemorojn kaj ebligas direkti pli striktan retpolitikon al unu gastnomo. Sed ĝi ne estas CSRF-kontrolo, kaj ĝi ne faras la kodon de la publika retejo sekura por lasi ĝin malfermita antaŭ ensalutinta administranto. La apartigo ŝanĝas tion, kion la retumilo konsideras limo, ne tion, kion la servilo kontrolas, do faru ĉi tiujn kvar kontrolojn antaŭ ol nomi ĝin finita.
Legu originon kaj retejon kiel du malsamajn vortojn
Origino estas skemo, gastiganto kaj pordo, do https://www.example.com kaj https://admin.example.com estas malsamaj originoj. Retejo, laŭ la senco de SameSite, estas skemo plus registrebla domajno, do tiuj du gastnomoj kutime estas la sama retejo. Tiu diferenco estas la tuta kaptilo: la atributo SameSite ne helpos vin inter frataj subdomajnoj, ĉar la retumilo tute ne konsideras la peton interreteja. Direktu la administran interfacon al vere alia registrebla domajno, ekzemple admin-example.net, kaj la peto vere fariĝas interreteja, kaj tie SameSite=Lax aŭ Strict komencas fari laboron, kiun vi povas fidi.
Testu ĝin en la retumilo anstataŭ rezonadi pri ĝi.
Ŝargu la publikan retejon, malfermu la programilojn por ellaborantoj, kaj rigardu, kiujn kuketojn la retumilo alkroĉas al peto al la administra gastiganto. Se la kuketo ne havas atributon Domain, ĝi estas nur-gastiganta kaj restas sur sia propra nomo; se ĝi portas Domain=example.com, ĝi vojaĝas al ĉiu frato, kaj la nova subdomajno donis al vi nenion por tiu kuketo.
Apartigu povas legi la respondon de povas sendi la peton
La samorigina politiko limigas legadon de respondoj inter originoj. Ĝi ne haltigas peton esti sendita, kaj ĝi ne malhelpas formularon porti legitimilojn, kiujn la retumilo jam havas. Simpla peto, kun formulara enhavtipo aŭ ordinara GET, estas liverata sen antaŭkontrolo; CORS poste decidas, ĉu la alvokanta skripto rajtas legi la respondon. CSRF vivas tute sur la senda flanko.
Tial la servilo bezonas eksplicitan kontrolon por statoŝanĝaj operacioj. Sinkroniga ĵetono ligita al la sesio, aŭ kuketo de duobla sendado komparata servile, kovras la kazon; komparo de Origin aŭ Referer indas aldoni kiel duan pordegon sed ne kiel la solan, ĉar ne ĉiu peto portas la kaplinion kaj ne ĉiu prokura servilo konservas ĝin. La gvidilo de OWASP pri malhelpado de CSRF traktas SameSite kiel unu tavolon inter pluraj ĝuste pro tiu kialo.
Decidu, kion la reta pordego efektive pruvas
Listo de permesitaj VPN-eliroj antaŭ la administra gastiganto estas bona kontrolo kaj malforta aserto pri identeco. Ĝi pruvas, ke la peto venis de adreso, kiun la VPN donas, kiun povas kunhavigi ĉiuj ĉe tiu eliro, kaj ĝi diras nenion pri tio, kiu persono aŭ aparato staras malantaŭ ĝi. Traktu ĝin kiel enirfiltron, ne kiel aŭtentikigon.
Tenu ĝin sendependa de la kontroloj ĉe la peta nivelo. Se la listo estas la sola afero inter atakanto kaj statoŝanĝa finpunkto, unu misagordita vojo, unu split-tunnel kliento aŭ unu prunteprenita tekkomputilo forigas la kontrolon tute.
Protokolu ankaŭ malakceptojn ekster la atendataj intervaloj. Ilia subita amaso estas la plej utila signalo, ke iu esploras la limon, kiun vi ĵus konstruis, kaj silento estas la signalo, ke la filtrilo tute ne estas atingata.
Tenu kuketojn, ensaluton kaj rajtigon eksplicitaj
La amplekso de la kuketo decidas la plej grandan parton de la rezulto. Kuketo de gepatra domajno estas sendata al la administra gastiganto, do skripta injekto en la publika retejo povas agi kun la sesio de administranto; kuketo nur por la gastiganto ne povas. Preferu la formon nur por la gastiganto, aldonu la atributon Secure, kaj uzu la antaŭmeton __Host- kie la platformo subtenas ĝin, ĉar tiu antaŭmeto postulas Secure, Path=/ kaj neniun atributon Domain. Legu la respondan kaplinion anstataŭ la kuketujon: Set-Cookie: __Host-admin_session=...; Secure; Path=/; HttpOnly; SameSite=Lax, sen atributo Domain. Retumilo forĵetas __Host- kuketon kun Domain, do kuketo, kiu ankoraŭ aperas ĉe frataj gastigantoj, pruvas, ke la antaŭmeto neniam aplikiĝis.
Poste tenu la rajtigon sur la servilo, por ĉiu peto, ĉe ĉiu administra finpunkto, ne nur ĉe ensaluto. Peto de permesita reto ankoraŭ devas esti aŭtentikigita kaj rajtigita por la operacio, kiun ĝi petas; la gastnomo ne estas aganto. Se la publika kaj la administra aplikaĵoj kunhavas ensalutan fluon aŭ sesian konservejon, skribu tiun rilaton, ĉar ĝi estas la plej mallonga vojo de cimo en la publika retejo al administra ago.
Rekontrolu la limon post la apartigo
Rulu la negativajn testojn, ne nur la feliĉan vojon: interreteja formularo sen ĵetono devas esti malakceptita, ĵetono el alia sesio devas esti malakceptita, kaj neniu GET rajtas ŝanĝi staton. Kontrolu la kuketajn atributojn en la programiloj por ellaborantoj, konfirmu, ke la Origin-kontrolo ekagas ĉe neegalanta peto, kaj provu la administran gastiganton de ekster la VPN-intervalo por vidi la filtrilon funkcii.
Nenio el tio forigas XSS-cimon ene de la administra aplikaĵo mem. Aparta gastnomo estas izola limo ĉe la retumila flanko kun reala valoro, kaj ĝi ne anstataŭas malhelpadon de nesekura koda plenumo aŭ protekton de petoj ĉe la servila flanko. Post la apartigo la listo estas pli mallonga ol ĝi aspektas: aparta origino, kuketoj nur por la gastiganto, ĵetono ĉe ĉiu ŝanĝo, enirfiltrilo, kiun vi ne fidas kiel identecon, kaj rajtigo decidita por ĉiu peto.