Avatud ümbersuunamine (open redirect) on iga teie saidi leht, mis saadab külastaja brauseri kasutaja sisendist võetud URL-ile ilma seda kontrollimata. See tundub tähtsusetu. Praktikas võimaldab see ründajal saata andmepüügilingi, mis näitab teie tegelikku domeeni, ning OAuth-i keskkonnas võib see lekitada autoriseerimiskoode ja juurdepääsutõendeid.
Miks ümbersuunamine on enamat kui kosmeetiline viga
CWE-601 kirjeldab nõrkust nii: veebirakendus aktsepteerib kasutaja kontrollitavat sisendit, mis määrab lingi välisele saidile, ja kasutab seda linki ümbersuunamisel. Ohver järgib linki teie usaldusväärsele saidile, kuid jõuab lehele, mida kontrollib ründaja. OWASP-i cheat sheet toob selle kuju:
http://example.com/example.php?url=http://malicious.example.com
Muudetud lingi serverinimi on identne algse saidi omaga, mistõttu tundub andmepüügikatse usaldusväärsem. Kasutaja poole pealt vaadatuna leiate selle kohta teavet meie lingikontrollist.
OAuth-i puhul ulatub sama viga kaugemale. RFC 9700 ütleb, et kliendid ja autoriseerimisserverid EI TOHI avalikustada URL-e, mis suunavad brauseri päringuparameetrist võetud suvalistele URI-dele, sest avatud ümbersuunajad võivad võimaldada autoriseerimiskoodide ja juurdepääsutõendite väljavoolu.
Sarnane juhtum on edasisuunamised (forward). Kui kasutaja sisend valib sisemise sihtkoha, nagu näites function.jsp?fwd=admin.jsp, võib spetsiaalselt koostatud URL pääseda juurdepääsukontrollist mööda ja jõuda administreerimisfunktsioonini. Rakendus peab kontrollima, kas kasutajal on sihtkoha jaoks õigus.
Parameetrite leidmine
Nimed varieeruvad: OWASP-i näidetes esinevad url, fwd ja returnUrl, teie koodis on aga ilmselt veel teisi. Otsige mustrit, mitte nime.
| Tehnoloogia | Ohtlik muster |
|---|---|
| Java | response.sendRedirect(request.getParameter("url")) |
| PHP | header("Location: " . $redirect_url) with $_GET['url'] |
| C# .NET | Response.Redirect(url) with request.QueryString["url"] |
| Rails | redirect_to params[:url] |
| Java forward | getRequestDispatcher(fwd).forward(...) |
Esimene grep-läbivaatus annab teile nimekirja, mida läbi lugeda. Kohandage tee ja failitüübid oma hoidlale vastavaks.
grep -rnE 'sendRedirect\(|Redirect\(|redirect_to params|header::LOCATION' src/
grep -rn -A3 'header(.Location' src/
Teine käsk on mõeldud PHP jaoks. Lugege iga leiu järel olevaid ridu: kui header("Location... järel puudub exit, jätkab ülejäänud skript tööd. Brauser, mis on seadistatud ümbersuunamist eirama, võib siis kuvada ülejäänud lehe.
.NET-i meeskonnad peaksid esimesena vaatama sisselogimistoiminguid. Cheat sheet'i järgi on ASP.NET MVC 1 ja 2 saidid eriti haavatavad ning selle MVC 2 LogOn näide suunab ilma igasuguse valideerimiseta aadressile returnUrl. Parandusena soovitatakse üle minna MVC 3-le.
Enamik leide on kahjutud. Iga ümbersuunamise kohta, mille argument ei ole sõnaliteraal ega serveripoolne otsing, tuleb esitada üks küsimus: kust see väärtus tuli? Arvesse lähevad küpsised, peidetud vormiväljad, päised ja andmebaasi sisu. Paljud avatud ümbersuunamised on olemas seetõttu, et arendaja eeldas, et küpsist või peidetud välja ei saa muuta.
Leiu kinnitamiseks ärge piirduge ühe tavalise välise aadressiga. Saatke parameetris iga järgmine väärtus ja jälgige Location päist:
http://malicious.example.comhttps://yoursite.example@malicious.example(userinfo:yoursite.examplemuutub kasutajanimeks)https://yoursite.example.malicious.example(hostinimi, mis algab teie omaga)https://malicious-yoursite.example(hostinimi, mis lõpeb teie omaga)
Cheat sheet nimetab userinfo't ja eksitavaid hostinimesid viisidena, kuidas eesliite- ja järelliitekontrollidest mööda pääseda. Kui mõni neist läheb läbi, kus tavaline URL blokeeriti, on kontroll tõenäoliselt sõnede võrdlus. See on järeldus, mitte tõend, aga asendage kontroll igal juhul.
Skannerid tabavad osa neist. OWASP Web Security Testing Guide märgib, et sellised tööriistad on üldised ja neil puudub rakendusespetsiifiline kontekst, seega kontrollige iga leid käsitsi üle.
Parandamine eelistusjärjekorras
- Ärge suunake ümber kasutaja sisendi põhjal. Kui sihtkoht on koodis fikseeritud, ei saa ründaja seda muuta.
- Vastendage ID-d sihtkohtadega serveris. Kasutaja annab lühinime või ID ja server otsib üles täieliku URL-i, lükates tagasi kõik muu. Veenduge, et ID-sid ei saa läbi käia, muidu saab külastaja loetleda kõik sihtkohad.
- Kasutage kohalike tagasisuunamiste jaoks raamistiku abifunktsiooni. ASP.NET Core'is tähendab see
LocalRedirect-i võiIsLocalUrl-i, mis lükkavad mittekohalikud sihtkohad tagasi. - Pange välised sihtkohad lubatud nimekirja. Kasutage hooldatavat URL-i parserit ning võrrelge parsitud skeemi, kanoonilist hosti ja efektiivset porti selgesõnalise nimekirjaga. Kui lubatud on vaid kindlad lõpp-punktid, piirake ka tee.
- Soovi korral nõudke nonce'i. CWE kirjeldab ettearvamatut, rakenduse loodud nonce'i igas ümbersuunamispäringus, kusjuures ilma selleta päringud lükatakse tagasi. XSS võib selle mööda minna, seega täiendab see parandust, kuid ei asenda seda.
Lubatud nimekirja kontrolli reeglid:
- Lükake userinfo ja mitmetähenduslik sisend tagasi.
- Suunake ümber valideeritud URL-iga, mitte versiooniga, mida pärast muudate.
- Ärge kunagi kasutage toorest eesliite- ega järelliitevõrdlust. Cheat sheet toob näiteks GitLabi, kus userinfo ja eksitavad hostinimed sellised kontrollid ületasid.
Halbade väärtuste keelunimekiri on nõrk peamine kaitse, kuigi CWE aktsepteerib seda rünnakute tuvastamiseks. Kasutage selle asemel põhimõtet "aktsepteeri ainult teadaolevalt hea".
Kui inimesed peavad teie saidilt lahkuma, lisab täiendava kaitsekihi vahelehekülg, mis nimetab sihtkoha ja nõuab klõpsu. Vältige selle lehe koostamisel XSS-i.
OAuth-i külg
RFC 9700 nõuab, et autoriseerimisserverid võrdleksid kliendi ümbersuunamis-URI-sid eelregistreeritutega täpse sõnevõrdlusega, välja arvatud natiivrakenduste localhost'i ümbersuunamis-URI-de pordinumbrid. Minu tõlgendus, mitte RFC-i tekst: täpne vastavus tõestab, et tagasikutse aadress on registreeritu, nii et kui see registreeritud host avab ka avatud ümbersuunaja, võib kood liikuda edasi. RFC viitab üksikasjade jaoks oma jaotisele 4.11. Lugege see läbi, enne kui minu kokkuvõttele tuginete.
Kust alustada
- Käivitage ülaltoodud grep-mustrid oma koodil ja koostage nimekiri kõigist ümbersuunamistest ja edasisuunamistest, mille sihtkoht pärineb päringust, küpsisest või salvestatud väärtusest. Kontrollige esimesena sisselogimise ja OAuth-i tagasikutsete töötlejaid.
- Kontrollige PHP leide puuduva
exit-i suhtes ja .NET-i projekte MVC 1 või 2 sisselogimistoimingute suhtes. - Testige iga leidu ülaltoodud nelja sisendiga, sealhulgas userinfo kujuga, ning registreerige, millised neist saadavad brauseri teie domeenist välja.
- Asendage kasutaja antud URL-id serveripoolse ID-vastendusega, kus vähegi võimalik, tagasipöördumisaadresside jaoks ainult kohalikke raamistiku abifunktsioone ja vähestele vajalikele välistele sihtkohtadele parsitud URL-i lubatud nimekirja.
- Vaadake üle oma OAuth-i klientide registreeringud täpsete ümbersuunamis-URI-de osas ja veenduge, et ükski teie host ei avalda avatud ümbersuunajat.
- Lisage ümbersuunamise test koodiülevaatusele ja oma penetratsioonitestimise mahtu, et viga ei naaseks.
