Flashback bygger pepparkakshus!
  • 1
  • 2
2013-12-11, 19:24
  #1
Medlem
.Chloes avatar
Jag har ett fåtal gånger sett hur personer misstolkat hur CSRF fungerar och vad som är möjligt. Så därför tänkte jag skriva en guide som kommer ta igenom hur CSRF fungerar, hur man detekterar sårbarheten och allmän analys utav patchar och exploits.

CSRF(Cross-site request forgery)(även XSRF) är en sårbarhet som påverkar webbläsaren och en hemsidas konfiguration. Denna sårbarhet har funnits ända sedan tidigt 2000-tal men har under senare tid blivit mer populär, dels för att den har potential att göra skada men även för att den är enkel att hitta med rätt verktyg och metoder.


Beskrivning

Sårbarheten ligger som sagt dels i webbläsarens arkitektur; hur den hanterar auktorisering. Men även i en hemsidas kod; hur den tillåter att man postar utifrån en domäns ursprung.

CSRF är alltså en teknik som låter mig skicka data från en domän till en annan utan vidare auktorisering från användaren. Just auktoriseringen ligger ju i webbläsaren i form utav session cookies och cookies.

GET
Om vi skapar ett enkelt HTML-dokument med följande kod:
HTML-kod:
<img src="http://i.imgur.com/vc8wWNJ.jpg" />

Och testar i vår webbläsare så kommer vi se katten och det är eftersom vi har tillstånd att få se bilden. Man kan påstå att en förfrågan skulle se ut på liknande sett:
Kod:
GET /vc8wWNJ.jpg HTTP/1.1
Cookie
authenticated 

Så vad skulle hända om samma dokument pekar på en URL som gör någonting annat, och där användaren är inloggad på sidan, dvs att webbläsaren har giltiga cookies.
HTML-kod:
<img src="http://site.com/buy.php?to=hacker@hx.se&value=700$" />

Ovanstående rad kod gör samma sak som innan, men taggen försöker inte visa en bild, utan den försöker besöka en adress, och om den försöker besöka en adress som faktiskt fungerar så kommer det ju fungera, men ingen bild kommer visas i detta fall.
Kod:
GET /buy.php?to=hacker@hx.se&value=700HTTP/1.1
Cookie
authenticated 

GET är intressant eftersom webbläsaren hämtar en URL, och i denna ser ni postfield med värden. to och value är de variabler som behövs fyllas i. Om vi redan skapar en URL med de parametrar som vi vill ha så räcker det endast med att en användare är inloggad på en hemsida för att köpet ska gå igenom.


POST
Motsatsen till GET är POST vilket innebär att man skickar data. Man besöker fortfarande en adress, men postfield finns inte längre i URL.
Kod:
GET /buy.php HTTP/1.1
POST
-DATAto=hacker@hx.se&value=700$
Cookieauthenticated 
Så skulle vår header se ut om vi tryckte på "Genomför köp" t.ex. Just denna POST-data ser man inte, den sker i bakgrunden. Ni ser ju att vi besökte endast buy.php men våra variabler och värden var i POST-datan.


Detektion

Nu vet ni skillnaden mellan POST och GET och de kan göra samma sak, dvs göra så en server förstår vad vi vill. Att detektera en potentiell GET-förfrågan som är sårbar mot CSRF är enkelt, allt du behöver göra är att kolla i adressfältet i webbläsaren. Skulle du se variabler som ser ut att faktiskt göra något innehållande värden så har du hittat en CSRF.

Låt oss säga att facebook har en sårbar GET:
www.facebook.se/message.php?to=234627834834&message=push eax!!&do=send

to, message och do är allting vi behöver för att skicka ett meddelande. Så allt du behöver göra är att skicka en GET-förfrågan till denna URL så kommer man skicka push eax!! till användaren 234627834834. Och variabeln do är ju send. Som ni ser så är det väldigt enkelt att detektera en sårbar GET.

För att skriva en exploit till detta så skapar man enkelt en HTML-rad innehållande denna URL. Skulle sedan en användare vara inloggad på facebook och göra en förfrågan mot denna URL så kommer meddelandet att skickas. Det smidigaste är så klart att lägga denna HTML-kod i ett email och så fort användaren öppnar mailet så görs GET-förfrågan mot facebook och därmed skickar meddelandet.


För att kolla din POST-data så rekommenderar jag ett Plug-in till Firefox med namnet Live HTTP Header vilket låter dig se den data du skickar, samt skicka om den.

Låt oss säga att vi har en sårbar POST:
http://s18.postimg.org/xacss1kax/face.png

Som ni ser på bilden är exakt samma variabler som i ovanstående GET-förfrågan, men denna gång hittar vi datan i POST-fältet. Skulle jag nu trycka på knappen "Replay" så kommer detta meddelande skickas och detta är eftersom inga tokens används, men jag ska förklara det mer lite senare.

Att skapa en exploit för att skicka POST-data är nästan lika enkelt, men vi behöver Javascript.
HTML-kod:
<form name="csrf" ENCTYPE="text/plain"
action="www.facebook.se/message.php" method="POST">
<input type="hidden" name='to=234627834834&message=push eax!!&do=send'>
</FORM>
<script>document.csrf.submit();</script>

Skulle ni spara ovanstående HTML-kod i ett dokuemt och öppna i en webbläsare så kommer alltså to=234627834834&message=push eax!!&do=send att skickas till www.facebook.se/message.php.


Åtgärd

Att åtgärda CSRF är enkelt, men något de flesta inte orkar med. Generellt sätt är det bättre att använda POST istället för GET, men skulle det behövas GET så fungerar det att använda sessions vilket kommer förhindra CSRF

När det kommer till GET så behöver man ange en session som är giltig. Utan denna session så får du helt enkelt ett error och kommer inte nå sidan.
Kod:
www.facebook.se/message.php?&to=234627834834&session=8237492730428340237420348273042834ng&message=push eax!!&do=send

POST kan vara lite annorlunda. Man kan först och främst sätta SAMEORIGIN i headern vilket innebär att man inte får tillstånd att skicka förfrågan utifrån domänens ursprung, t.ex från sida.se till facebook.se.

Flashback har den metoden att generera ett unikt stoken(Session Token) som läggs i POST-datan när du ska skicka datan. Detta stoken kontrolleras om det är samma i källkoden som i POST-datan. Jag har nämnt just detta här.

Men som ni vet så ligger inte allt ansvar på hemsidans kodare utan även användaren. RequestPolicy, NoScript och CsFire är exempel på plug-in som förhindrar att du blir drabbad utav CSRF-buggar.

Att inte använda "Håll mig inloggad" kan stoppa attacker då auktorisering kommer krävas vid en CSRF-attack.


Sammanfattning och vidareläsning

Du måste vara inloggad på en hemsida för att denna attack ska fungera. Du måste även besöka en länk.

Läs mer om CSRF:
http://en.wikipedia.org/wiki/Cross-site_request_forgery
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
http://www.codinghorror.com/blog/2008/10/preventing-csrf-and-xsrf-attacks.html
(FB) Hacka routerns firmware
(FB) Hacka routerns firmware
(FB) Hacka routerns firmware
__________________
Senast redigerad av .Chloe 2013-12-11 kl. 19:27.
Citera
2013-12-11, 19:31
  #2
Medlem
Tango1s avatar
Riktigt schysst jobbat - intressant och lärorikt som alltid, .Chloe! Stort tack ska du ha för att du tar dig an mödan att skriva dessa guider för oss it-säk.-intresserade
Citera
2013-12-11, 19:52
  #3
Medlem
Tackar ödmjukast!
Citera
2013-12-11, 19:54
  #4
Medlem
TheBlots avatar
Riktigt lärorikt och intressant, fortsätt så.
Citera
2013-12-11, 20:08
  #5
Medlem
Väldigt intressant och bra skrivet. Tack.
Citera
2013-12-11, 20:13
  #6
Medlem
epth0s avatar
Sett dina trådar och inlägg, alltid av massiv kvalitet. Önska att fler vore som dig. detta var anledningen till att jag blev medlem på flashback = för att lära mig

undrar varför du inte är mod eller nåt, du är ju den enda som gör något av nytta. om du lämnar fb så skriv pm så jag kan hänga efter
Citera
2013-12-12, 21:38
  #7
Medlem
.Chloes avatar
Thanks boys!

Jag tänkte ta en klassisk bypass när det kommer till token. Jag kommer även lite senare tala om mer avancerad CSRF samt hur man kan kombinera den med andra sårbarheter så som XSS och totalt komma förbi de flesta säkerhetshindren.

Föreställ er följande form:
HTML-kod:
<form action="script.php" method="POST" name="form"> 

<input type="text" value="" name="textone" /> 
<input type="password" value="" name="texttwo" /> 
<input type="hidden" value="89734583443STOKENHAHA" name="TOKEN" /> 
<input type="submit" value="submit" /> 

</form>

En vanlig form med tre inputs, en hidden som ska fungera som token. Detta skulle ju generellt sätt stoppa alla CSRF-försök eftersom sårbarheten handlar om att skicka data. Token i detta fall är hidden så vi kan ju inte skicka något som är hidden även något värde som är dynamiskt.
Att använda token vid POST är faktiskt rätt så bra, men problem som kan uppstå är att token aldrig kontrolleras. Detta kallas för chaining(inte bara inom CSRF-exploatering).

HTML-kod:
document.forms[0].textone.value="VÄRDE 1"; 
document.forms[0].texttwo.value="VÄRDE 2"; 
document.forms[0].submit();

Ovanstående kod skulle komma förbi hela tokenvalideringen pga just chaining. Anledningen till att just detta fungerar är för att javascript har tillgång till alla HTML-objekt via DOM.
Citera
2013-12-12, 21:55
  #8
Medlem
droles avatar
Citat:
Ursprungligen postat av .Chloe
Thanks boys!

Jag tänkte ta en klassisk bypass när det kommer till token. Jag kommer även lite senare tala om mer avancerad CSRF samt hur man kan kombinera den med andra sårbarheter så som XSS och totalt komma förbi de flesta säkerhetshindren.

Föreställ er följande form:
HTML-kod:
<form action="script.php" method="POST" name="form"> 

<input type="text" value="" name="textone" /> 
<input type="password" value="" name="texttwo" /> 
<input type="hidden" value="89734583443STOKENHAHA" name="TOKEN" /> 
<input type="submit" value="submit" /> 

</form>

En vanlig form med tre inputs, en hidden som ska fungera som token. Detta skulle ju generellt sätt stoppa alla CSRF-försök eftersom sårbarheten handlar om att skicka data. Token i detta fall är hidden så vi kan ju inte skicka något som är hidden även något värde som är dynamiskt.
Att använda token vid POST är faktiskt rätt så bra, men problem som kan uppstå är att token aldrig kontrolleras. Detta kallas för chaining(inte bara inom CSRF-exploatering).

HTML-kod:
document.forms[0].textone.value="VÄRDE 1"; 
document.forms[0].texttwo.value="VÄRDE 2"; 
document.forms[0].submit();

Ovanstående kod skulle komma förbi hela tokenvalideringen pga just chaining. Anledningen till att just detta fungerar är för att javascript har tillgång till alla HTML-objekt via DOM.
För trött just nu men detta måste vara en XSS också eller?
Menar när du injectar JS.

Eller menar du att man på något annat magiskt sätt ska göra det?

Checkas inte token förstår jag inte heller varför du måste injecta JS, det skulle räcka med att posta datan till rätt ställen direkt.
__________________
Senast redigerad av drole 2013-12-12 kl. 21:58.
Citera
2013-12-12, 21:58
  #9
Medlem
.Chloes avatar
Citat:
Ursprungligen postat av drole
Menar när du injectar JS.
Japp, det stämmer!

Citat:
Ursprungligen postat av drole
Checkas inte token förstår jag inte heller varför du måste injecta JS, det skulle räcka med att posta datan till rätt ställen direkt.

Token kollas ju eftersom den hade ett värde redan i HTML-formen.
Citera
2013-12-12, 22:48
  #10
Medlem
droles avatar
Citat:
Ursprungligen postat av .Chloe
Token kollas ju eftersom den hade ett värde redan i HTML-formen.
Då är jag med, läste lite snabbt bara.
Sett allt för många sårbarheter på senaste tiden där man kunnat skicka vilket värde som helst token och det har gått igenom så antar jag läste lite slarvigt.

Edit, jag hävdar dock att felet ligger på endast hemsidan.
Ingen idé att skylla på webbläsaren.
Annars var väl det mesta bra, skummade dock bara igenom texten.

Om du är ute efter lite credit av folk här så kolla gärna in Flashbacks hantering utav tokens, iaf senast jag kollade så var den galet dålig.
De gjorde dock om en del efter det, vet inte om allt blev fixat.
__________________
Senast redigerad av drole 2013-12-12 kl. 22:55.
Citera
2013-12-12, 22:53
  #11
Medlem
.Chloes avatar
Citat:
Ursprungligen postat av drole
Sett allt för många sårbarheter på senaste tiden där man kunnat skicka vilket värde som helst token och det har gått igenom så antar jag läste lite slarvigt.
Jo precis. Detta har jag även sett ett par gånger. Om du kollar på hur Flashback har löst det så fungerar det fint. Flashback har ju nämligen sitt stoken i en hidden-tag som sedan skickas med POST-datan, det stoken som är med i POST ska vara densamma som i hidden-taggen.

Citat:
Ursprungligen postat av drole
Edit, jag hävdar dock att felet ligger på endast hemsidan.
I detta fall så är det endast så eftersom denna CSRF-sårbarhet skulle ju kunna ligga på sidans ursprung, t.ex om man kunde köra Js här på forumet och då skulle inget plug-in hjälpa dig då de endast kollar om du skickar till en annan domän.
Citera
2013-12-12, 22:57
  #12
Medlem
droles avatar
Citat:
Ursprungligen postat av .Chloe
Jo precis. Detta har jag även sett ett par gånger. Om du kollar på hur Flashback har löst det så fungerar det fint. Flashback har ju nämligen sitt stoken i en hidden-tag som sedan skickas med POST-datan, det stoken som är med i POST ska vara densamma som i hidden-taggen.

Snabbt test med tamperdata visar att det fortfarande inte sköts korrekt här, har dock inte tid att leka runt allt för mycket.
Får dra en koll med Burp sen om jag får tid så borde man få en bättre bild utav det hela.
__________________
Senast redigerad av drole 2013-12-12 kl. 23:00.
Citera
  • 1
  • 2

Skapa ett konto eller logga in för att kommentera

Du måste vara medlem för att kunna kommentera

Skapa ett konto

Det är enkelt att registrera ett nytt konto

Bli medlem

Logga in

Har du redan ett konto? Logga in här

Logga in