10.12. CORS ja CSRF

CORS ja CSRF ovat ne kaksi selainpuolen suojausta, joita avoimeen internetiin kytketty kamera tarvitsee HTTPS:n ja kirjautumisen rinnalla. Kumpikin vie muutaman rivin pystyttämiseen. Alla olevat osiot määrittelevät termin ja näyttävät microdot-integraation.

10.12.1. Mitä CORS tekee

Cross-Origin Resource Sharing (CORS) on selainmekanismi, jonka avulla palvelin voi sallia tiettyjen muiden alkuperien lukea sen vastauksia. Selaimen oletusarvoinen same-origin-käytäntö estää tämän lukemisen: JavaScript osoitteessa https://example.com ei voi lukea vastauksia osoitteesta https://yard-cam.example.com, koska eri isäntä lasketaan eri alkuperäksi. CORS on palvelinpuolen tapa myöntää poikkeuksia valituille vertaisille.

Jos kojelauta tarjoillaan itse kameralta, jokainen pyyntö on samaa alkuperää eikä CORS tee mitään. Asetuksella on merkitystä, kun kojelauta sijaitsee muualla – julkinen URL kuten https://app.example.com, joka kommunikoi kameran kanssa osoitteessa https://yard-cam.example.com:

from microdot.cors import CORS

cors = CORS(
    app,
    allowed_origins=['https://app.example.com'],
    allow_credentials=True,
    max_age=86400,
)

allowed_origins on luettelo alkuperistä, joiden on sallittua lukea kameran vastauksia. Kojelaudan alkuperä ja vain kojelaudan alkuperä – ei * – jotta kolmannen osapuolen sivusto ei voi lukea kameran vastauksia vahingossa.

allow_credentials=True antaa eri alkuperää olevien pyyntöjen sisällyttää istuntoevästeen, mikä on mitä kojelauta tarvitsee pysyäkseen kirjautuneena alkuperärajan yli.

max_age=86400 kertoo selaimelle, että se voi tallentaa esitarkistuksen tuloksen välimuistiin päiväksi. Selaimet laukaisevat ylimääräisen OPTIONS-pyynnön ennen mitä tahansa eri alkuperää olevaa kutsua, joka käyttää muita metodeja kuin GET/HEAD/POST tai lähettää mukautettuja otsakkeita; max_age leikkaa tämän lisäkuorman yhteen esitarkistukseen päivässä reittiä kohden.

10.12.2. Mitä CSRF tekee

Cross-Site Request Forgery (CSRF) on hyökkäys, jossa haitallinen sivu saa käyttäjän selaimen laukaisemaan todennetun pyynnön luotettuun palvelimeen. Vaikka CORS olisi käytössä, piilotettu <form> sivulla evil.com, joka tekee POST-pyynnön osoitteeseen https://yard-cam.example.com/config, tavoittaa kameran, ja selain liittää mukaan kameran istuntoevästeen – evästeet seuraavat kohdeisäntää, eivät pyynnön tekevän sivun alkuperää – joten kamera käsittelee POST-pyynnön mielellään aivan kuin se tulisi omistajalta.

CSRF-suojaus hylkää nuo pyynnöt. microdot.csrf.CSRF lisää väliohjelmiston, joka tarkastaa Sec-Fetch-Site-otsakkeen jokaisesta tilaa muuttavasta pyynnöstä ja hylkää kaiken, jota ei ole merkitty arvolla same-origin (tai joka tulee CORS-sallitusta alkuperästä):

from microdot.csrf import CSRF

CSRF(app, cors=cors)

cors-instanssin välittäminen antaa väliohjelmiston päästää sisään kojelaudan sallitun alkuperän – kamera hyväksyy yhä kojelaudan POST-pyynnöt, vaikka ne ovat eri alkuperää.

Sec-Fetch-Site asetetaan automaattisesti modernien selainten toimesta; kameran ei tarvitse tehdä mitään asiakaspuolella. Vanhemmille selaimille, jotka eivät lähetä otsaketta, CORS-sallintaluettelo on varatarkistus.

10.12.3. Webhookien vapauttaminen

Jos kamera tarvitsee webhook-päätepisteen vastaanottamaan POST-pyyntöjä kolmannen osapuolen pilvipalvelulta – esimerkiksi takaisinkutsun arkistopalvelun tarjoajalta – merkitse reitti dekoraattorilla @csrf.exempt, jotta väliohjelmisto päästää sen läpi. Käsittelijä on vastuussa pyynnön varmentamisesta jollain muulla tavalla – yleensä Hash-based Message Authentication Code (HMAC) hyötykuorman yli, laskettuna salaisuudella jonka kamera ja kolmas osapuoli jakavat, mikä todistaa pyynnön tulleen joltakulta joka tunsi salaisuuden. Takapihakameralla ei ole mitään näistä, mutta dekoraattori on siellä kun sitä tarvitset.

10.12.4. Neljän rivin perustaso

Kun HTTPS on käytössä, suositeltu pino mille tahansa internetiin näkyvälle kameran käyttöönotolle on:

Session(app, secret_key=SECRET,
        cookie_options={'http_only': True, 'secure': True})
login = Login()
cors = CORS(app, allowed_origins=[...], allow_credentials=True)
CSRF(app, cors=cors)

Istunto ja kirjautuminen aiemmin luvussa, CORS ja CSRF tässä, HTTPS edellisestä aiheesta. Nämä neljä osaa pinotaan päällekkäin ja pysyvät poissa jokaisen reitin tieltä.

Kamera on nyt turvallinen kytkettäväksi avoimeen internetiin – HTTPS, kirjautuminen, CSRF, CORS.