Fantastiske sårbarheder og hvor man kan finde dem (del 1) - Scripting på tværs af sider med Django-formfejl

Sårbarheder ved XSS-scripting

Hvorfor er Cross-Site Scripting (XSS) stadig den mest almindelige websårbarhed? Teorien om at identificere XSS er temmelig ligetil, der er mange statiske analyseværktøjer, der er oprettet til at opdage det, og alligevel er der så mange uopdagede sårbarheder. Så hvad giver?

Nå, en af ​​grundene er, at traditionelle programanalysemetoder ofte ikke identificerer hensigten med et givet kodestykke. F.eks. Kan et værktøj kæmpe med at finde ud af, hvilke objekter i programmet der kan indeholde brugerinput.

I mit forrige indlæg beskrev jeg, hvordan vi løste dette problem ved at opbygge et system, der lærer sikkerhedspecifikationer fra tusinder af Open Source-projekter og bruger dem til at finde reelle sårbarheder. Jeg lovede også at dele nogle seje eksempler på, hvad den lærte.

Jeg besluttede at starte med en interessant og temmelig uventet kilde til mulige problemer i projekter, der bruger Django. Dette indlæg er en guide til identifikation og udnyttelse af XSS-sårbarheder ved hjælp af valideringsfejl i Django-formularer. Her er et rigtigt eksempel: https://github.com/mozilla/pontoon/pull/1175.

Lad os hoppe lige ind i det og begynde med en lille quiz. Hvor mange gange har du skrevet / set kode, der ligner følgende uddrag?

Hvad med denne her?

Eller denne?

Alle af dem er udbredte eksempler på, hvordan du normalt fortæller brugeren, at det angivne input er ugyldigt, ikke? Inputet er hentet fra HTTP-anmodningsparametrene og pænt ikke-sammenlagt til et MyForm-objekt. Hvis nogen af ​​felterne indeholder ugyldig input (f.eks. Nogen indtastede strengen "foobar" i et numerisk felt), returneres en 400 Bad Request-side med en beskrivelse af fejlen. Forskellen mellem uddrag er formatet på den returnerede fejl - en HTML-liste, almindelig tekst eller JSON.

Nu et spørgsmål på en million dollar - hvilket af disse uddrag vil gøre din webapp XSSable?

For at svare på det, lad os undersøge Django-formularen API fra to synsvinkler:

  1. Er angriberen i stand til at injicere ondsindet input på den webside, der vises i brugerens browser?
  2. Vil dette ondsindede input altid undgås korrekt, før det returneres til brugeren?

I henhold til Djangos dokumentation er måden at opbygge dynamiske fejlmeddelelser til feltvalideringsfejl at hæve en django.core.exceptions.ValidationError-undtagelse med den tilsvarende meddelelse. En sådan undtagelse, der smides fra en af ​​valideringsfunktionerne i formularen (f.eks. Metoderne ren () og ren_ () i django.forms.BaseForm-klassen) vil medføre, at beskeden gemmes i formens fejlordbog (django) .forms.utils.ErrorDict) og senere muligvis vist for brugeren.

En måde at udnytte en sådan undtagelse er at bruge nogle af de indbyggede formfelter, der bekvemt afspejler det defekte input i undtagelsesmeddelelsen. Jeg prøvede alle Django-formfelttyper, der er anført her og fik følgende liste: ChoiceField, TypedChoiceField, MultipleChoiceField, FilePathField. Hver af disse genererer en fejlmeddelelse som "Vælg et gyldigt valg.% (Værdi) s er ikke et af de tilgængelige valg.", Hvor værdien er det defekte input. for sejren .

Den anden mulighed er at udnytte tilpassede felter og / eller valideringsprocedurer. Overvej for eksempel følgende uddrag (hentet fra et rigtigt projekt og ændret til kortfattethed):

Her ville en god nyttelast være noget som foo. .

Jej, du har ret, ValidationError-undtagelserne alene giver ikke os en XSS. For en ordentlig sårbarhed har vi brug for endnu en ingrediens - muligheden for at injicere fejlmeddelelser på den endelige HTML-side, der returneres til brugeren.

Ovennævnte ErrorDict-klasse har følgende metoder til at udtrække fejlmeddelelser:

  1. as_data () - ingen rensning
  2. get_json_data (escape_html = False) - ingen rensning, hvis escape_html == False (standard)
  3. as_json (escape_html = False) ingen rensning, hvis escape_html == False (standard)
  4. as_ul () - sikkert
  5. as_text () - ingen rensning
  6. __str __ () (opkald som_ul ()) - sikkert

Lad os nu vende tilbage til vores lille quiz. Det er let at se, at uddrag 1 er sikkert, fordi det bruger metoden __str __ (), der slipper for input. Uddrag 2 og 3 er imidlertid farlige og kan resultere i XSS.

Der er to vigtigste takeaway-meddelelser her. Den for udviklere er mantraet “altid sanitere upålidelige input”. Den for sikkerhedsforskere er: en simpel grep -R "ValidationError" kan muligvis udvide angrebsoverfladen for dig.

I øvrigt har du min respekt, hvis du har bestået quizzen korrekt uden at læse det fulde indlæg.

Opbygning af en web- eller mobilapp?

Crowdbotics er den hurtigste måde at opbygge, lancere og skalere en applikation.

Udvikler? Prøv Crowdbotics App Builder for hurtigt at stillads og implementere apps med en række populære rammer.

Optaget eller ikke-teknisk? Deltag i hundredvis af glade teams, der bygger software med Crowdbotics PM'er og ekspertudviklere. Omfangets tidslinje og omkostninger med Crowdbotics Managed App Development gratis.