10.12. CORS și CSRF¶
CORS și CSRF sunt cele două protecții din partea browserului de care are nevoie o cameră expusă internetului, alături de HTTPS și autentificare. Fiecare necesită câteva linii pentru a fi configurată. Secțiunile de mai jos definesc termenul și arată integrarea cu microdot.
10.12.1. Ce face CORS¶
Cross-Origin Resource Sharing (CORS) este mecanismul browserului care permite unui server să accepte ca anumite alte origini să îi citească răspunsurile. Politica de aceeași origine implicită a browserului blochează acea citire: JavaScript de pe https://example.com nu poate citi răspunsuri de la https://yard-cam.example.com, deoarece un host diferit este considerat o origine diferită. CORS este modalitatea de pe partea de server de a acorda excepții pentru parteneri aleși.
Dacă tabloul de bord este servit chiar de cameră, fiecare cerere este de aceeași origine, iar CORS nu face nimic. Configurarea contează când tabloul de bord se află în altă parte – un URL public precum https://app.example.com care comunică cu o cameră de la 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 este lista de origini cărora li se permite să citească răspunsurile camerei. Originea tabloului de bord și doar originea tabloului de bord – nu * – astfel încât un site terț să nu poată citi din întâmplare răspunsurile camerei.
allow_credentials=True permite cererilor de origine încrucișată să includă cookie-ul de sesiune, ceea ce tabloul de bord are nevoie pentru a rămâne autentificat peste o limită de origine.
max_age=86400 îi spune browserului că poate stoca în cache rezultatul preflight timp de o zi. Browserele lansează o cerere OPTIONS suplimentară înaintea oricărui apel de origine încrucișată care folosește metode diferite de GET/HEAD/POST sau care trimite anteturi personalizate; max_age reduce această suprasarcină la un singur preflight pe zi pentru fiecare rută.
10.12.2. Ce face CSRF¶
Cross-Site Request Forgery (CSRF) este atacul prin care o pagină malițioasă face ca browserul utilizatorului să lanseze o cerere autentificată către un server de încredere. Chiar și cu CORS activat, un <form> ascuns pe evil.com care trimite POST către https://yard-cam.example.com/config va ajunge la cameră, iar browserul va atașa cookie-ul de sesiune al camerei – cookie-urile urmează hostul de destinație, nu originea paginii care face cererea – așa că, fără probleme, camera procesează POST-ul ca și cum ar veni de la proprietar.
Protecția CSRF respinge aceste cereri. microdot.csrf.CSRF adaugă un middleware care inspectează anteturul Sec-Fetch-Site la fiecare cerere care modifică starea și respinge orice nu este etichetat same-origin (sau care provine dintr-o origine permisă de CORS):
from microdot.csrf import CSRF
CSRF(app, cors=cors)
Transmiterea instanței cors permite middleware-ului să includă din oficiu originea permisă a tabloului de bord – camera tot acceptă POST-urile tabloului de bord, chiar dacă sunt de origine încrucișată.
Sec-Fetch-Site este setat automat de browserele moderne; camera nu trebuie să facă nimic pe partea de client. Pentru browserele mai vechi care nu trimit anteturul, lista de permise CORS este verificarea de rezervă.
10.12.3. Exceptarea webhook-urilor¶
Dacă camera are nevoie de un endpoint webhook pentru a accepta POST-uri de la un serviciu cloud terț – un callback de la furnizorul arhivei, de exemplu – marchează ruta cu @csrf.exempt astfel încât middleware-ul să o lase să treacă. Handlerul este responsabil pentru verificarea cererii într-un alt mod – de obicei un Hash-based Message Authentication Code (HMAC) peste payload, calculat cu un secret pe care camera și terțul îl partajează, care dovedește că cererea a venit de la cineva care cunoștea secretul. Camera din curtea din spate nu are niciuna dintre acestea, dar decoratorul este acolo când ai nevoie de el.
10.12.4. Linia de bază din patru linii¶
Odată ce HTTPS este activat, stiva recomandată pentru orice implementare a unei camere expuse internetului este:
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)
Sesiunea și autentificarea mai devreme în capitol, CORS și CSRF aici, HTTPS din subiectul anterior. Cele patru piese se suprapun una peste alta și rămân în afara căii fiecărei rute.
Camera poate acum să fie expusă în siguranță internetului deschis – HTTPS, autentificare, CSRF, CORS.