Tema
/
Interneto svetainių serverio dalies kūrimas GO
📖 Teorija

Kas yra CSRF ir kodėl dviejų dalių apsauga

Tavo formos dabar POST'ina laimingai — ir tai yra pažeidžiamumas. Ši pamoka jį uždaro, ir tai darydama pataikysi į labiausiai neteisingai suprantamą klaidą Go web kūrime. Priversim tave į ją pataikyti sąmoningai, nes jos derinimas ir yra būdas iš tikro suprasti, ką CSRF apsauga daro.

Ataka. Esi prisijungęs prie SignFlow (tavo sesijos slapukas naršyklėje). Aplankai kažkokią nesusijusią svetainę — forumą, reklamą. Tas puslapis turi:

<form action="https://signflow.app/logout" method="post" id="x"></form>
<script>document.getElementById('x').submit()</script>

Naršyklė ją pateikia — ir automatiškai prideda tavo SignFlow sesijos slapuką, nes taip slapukai veikia. SignFlow mato galiojančią sesiją ir tave atjungia. Pakeisk /logout į „pakeisti mano el. paštą" tašką ir tai — paskyros perėmimas. Tai Cross-Site Request Forgery: kitas šaltinis sukelia autentifikuotą veiksmą naudodamas tavo slapuką. Vartotojas SignFlow nieko nepaspaudė.

Apsauga turi dvi puses, ir būtent šią dalį visi išmoksta tik pusiau.

  1. Slaptas žetonas. SignFlow įdeda atsitiktinį žetoną į slapuką ir reikalauja jį atkartoti paslėptame formos lauke kiekviename POST. Įsilaužėlio puslapis negali perskaityti tavo slapuko (SameSite/HttpOnly padeda) ir negali atspėti žetono, tad negali įdėti atitinkamo lauko. Tikros SignFlow formos jį neša; suklastotos — ne.
  2. Origin/Referer patikra. Be žetono, middleware tikrina, kad užklausa atėjo iš paties SignFlow šaltinio. Tai pusė, kurią žmonės pamiršta — ir būtent ji tuoj tave įkąs.

Naudojam gorilla/csrf. Vienas middleware, csrf.Protect, užtikrina abi puses kiekvienam nesaugiam metodui. Formos įdeda žetoną per paslėptą gorilla.csrf.Token lauką.

Spąstai, kuriuos tuoj sutiksi. gorilla/csrf daro prielaidą, kad aptarnauja per HTTPS. Origin/Referer pusei jis reikalauja, kad užklausa įrodytų atėjusi iš to paties saugaus šaltinio — o paprasta http://localhost užklausa to įrodyti negali. Tad vos įjungęs apsaugą, tavo dev formos bus atmestos su pranešimu, kuris nieko iš to nepaaiškina. Įjungsim, pažiūrėsim, kaip lūžta, ir tik tada pataisysim — nes taisymas prasmingas tik pajutus problemą.

Ši pamoka:

  1. Pridėk csrf.Protect (config gauna paslaptį, main išveda raktą) — ir pateik formą, kad pataikytum į 403.
  2. Diagnozuok, pridėk tik-dev plaintext išimtį, pridėk žetono lauką į kiekvieną formą ir žiūrėk, kaip veikia.