Tweets by @buherablog
profile for buherator at IT Security Stack Exchange, Q&A for IT security professionals

A BitBetyár Blog

Túljártál a nagyokosok eszén? Küldd be a mutatványodat! (e-mail a buherator gmailkomra jöhet)

Full-Disclosure / Névjegy / Coming out


Promó

H.A.C.K.

Címkék

0day (110) adobe (87) adobe reader (21) anonymous (26) apple (60) az olvasó ír (49) blackhat (20) botnet (22) bug (200) buherablog (44) buhera sörözés (39) bukta (49) deface (38) dns (22) dos (29) esemény (82) facebook (26) firefox (64) flash (33) gondolat (31) google (59) google chrome (36) hacktivity (37) hírek (117) incidens (224) internet explorer (88) iphone (35) java (50) jog (22) kína (21) kriptográfia (68) kultúra (21) linux (24) malware (43) microsoft (142) móka (48) mozilla (23) office (26) oracle (40) os x (43) patch (197) php (20) politika (31) privacy (58) programozás (22) safari (34) sql injection (62) windows (85) xss (77) Címkefelhő

Licensz

Creative Commons Licenc

Rewrite Rule Rock'n'Roll

2010.06.23. 14:50 | buherator | 4 komment

Újabb cikk a Niobium Attack Research jóvoltából, építve a korábbi Apache információszivárgása is:

A téma az apacs, a rewriteengine és a rewriterule/regexp reverse engineering.

Ami fix az hogy "RewriteEngine on".

A rewriteengine elég sokat tud, de általában csak nagyon kevés fícsörét használják.

Kezdjük basic dolgokkal, alap rewriteokkal amivel sok helyen találkozhatunk, és gyakran el is cseszik:

RewriteRule ^index.html$  index.php

Mi ezzel a baj?

A pont (.) ezzel a baj: nincs escapelve (\.)

Mindkét request:

/index.html

/indexxhtml

rewriteol erre: /index.php

Ebben az esetben a . helyettesíthető %xx karakterekkel, de nem illeszkedik rá minden.

Ezek nem: {%2f, %0a, %00}, minden más igen.

Ha %xx formában küldöd.

Ha bájtként akkor ezekre nem fog meccselni a .: { 00, 09, 0A, 0B, 0C, 0D, 20, 23, 25, 3F}

Ennyit a pontról.

Következő challange:

RewriteRule ^pub/(.+)$ index.php?file=$1

Az index.php legyen mondjuk:

<?php

$dir = './pubHtmlDir/';

$fn = $_GET['file_name_2_open'];

print "$dir$fn\n"; // hogy lássuk mit próbálunk includolni

if(file_exists($dir.$fn) and is_file($dir.$fn))

    $inc = $fn;

else

    $inc = '404.html';

include($dir.$inc);

?>

Ez tiszta, de te nem tudod se a rewrite rule-t, se a változó nevét, se a könyvtárakat.

Te csak ennyit látsz:

http://valami.lofasz.tld/pub/main.html

Átverés mert könyvtárnak tűnik, és majdnem úgy is viselkedik.

Azt hogy könyvtár-e vagy rewrite, ki tudod szimatolni.

A kulcsszó: mod_dir.

Intermezzo: mod_dir

Micsinál a mod_dir?

Pl kezeli az indexfájlokat (amik DirectoryIndex-nél megadva azok végig keresi), illetve megnézi hogy van-e olyan nevű könyvtár.

Ha van akkor mögé rakva a /-t redirectel minket 301 Moved Permanently -vel, - ez ad alapot a wordlist attackra directorykhoz.

Ezt tutira vágod, most van egy ilyenünk:

http://valami.lofasz.tld/pubHtmlDir

Ha a mod_dir be van töltve akkor ez 301 redirectelni fog minket ide:

http://valami.lofasz.tld/pubHtmlDir/

...ellenkező esetben kapunk egy mezei 404-et.

Ha a /pub/ tényleg directory akkor a következő kérésnek...

http://valami.lofasz.tld/pub

...redirectelnie kéne ide:

http://valami.lofasz.tld/pub/

...de nem teszi mert erről a mod_dir mit sem tud.

Intermezzo vége

Na tehát ott tartottunk hogy látunk egy ilyen urlt:

http://valami.lofasz.tld/pub/main.html

Egyik előző posztból már megvan az infó hogy hogyan derítsük ki hogy mire rewriteol.

Lássuk:

# echo -ne "POST /pub/main.html HTTP/1.1\nHost: valami.lofasz.tld\nConnection: close\nContent-length: x\n\n" | nc valami.lofasz.tld 80; echo

HTTP/1.1 413 Request Entity Too Large

Date: Fri, 21 May 2010 18:23:11 GMT

Server: Apache

Connection: close

Content-Type: text/html; charset=iso-8859-1

 

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">

<html><head>

<title>413 Request Entity Too Large</title>

</head><body>

<h1>Request Entity Too Large</h1>

The requested resource<br />/index.php<br />

does not allow request data with POST requests, or the amount of data provided in

the request exceeds the capacity limit.

</body></html>

... és itt jön a body, de azt nem copyzzuk be... :P

A lényeg hogy megtudtunk hogy az /index.php kapja majd paraméterként... valahogy.

Nekiláthatunk variable scannel megkeresni a változót aminek átadja, de a 'file_name_2_open' az nem nagyon wordlist gyanús...

Ergo így nem fogjuk megtalálni a változót, mert ez a cikk most nem arról szól... azért adtam neki hülye nevet. :D

Szedjük össze mit látunk ebből tisztán támadóként:

  • van egy könyvtárnak álcázott bullshit
  • ami egyébként rewrite az /index.php-ra
  • és paraméterként kap egy fájlnevet vagy elérési utat: main.html vagy pub/main.html - ezt még nem tudjuk

hmm... nézzük:

Küldjük be a requestet:

/pub/../../../../../../../../../etc/passwd

Ez biza egy 400 Bad Request, mert az apache először normalizálja a pathot.

El se jutott a rewrite-ig...

/pub/%2fmain.html

Ebből mi lesz?

Ííígy van: 404.

Miért?

Mert az apache amikor bejött a request első körben urldekódolta azt, így a requestből /pub//main.html lett, és ilyen könyvtár vagy fájl nincs.

Dehát rewriteolve lett, nem?

Nem.

El sem jutott a rewrite-ig.

Ez így nem is fog menni, nem lehet a stringben / (%2f) jel. (sem %00, sem %0a)

Akkor most szopás van?

Nem van.

A jó hír az hogy doubdecode van a processing flow-ban. :DD (buzzword factory roxx lol :"DD)

Mondom a megoldást aztán mondom hogy miért:

/pub/..%252f..%252f..%252f..%252f..%252f..%252f../etc/passwd

0x25 == %

Megkapja az apacs, lekezeli a %xx-et, úgyhogy a .php-nak már csak ez megy át:

..%2f..%2f..%2f..%2f..%2f..%2f../etc/passwd

Ezt pedig már a php maga fogja elintézni hogy a %2f -ekből / legyék.

A végeredmény pedig... egy pwd fájl. minő váratlan fordulat.

A dupla kódolással nem tudodmegkerülni a "magic_quotes_gpc = on" paráját, tehát a %2500 -ból természetesen így is \0 lesz.

Ugyanez van amikor SQLi-t így akarsz átpasszolni és szeretnéd használni a /* stringet.

Jópofa de ennyi elég a témáról... amit érdemes megjegyezni az a dupla dekódolós cucc.

Nyahh... ennyi csoki elég volt mára, jöjjön a szarabbik fele.

Szedjük vissza hogy mi a rewriteRule.

Legyen mondjuk az url:

/id/65551

menjünk lépésről lépésre, nézzük az eredményt hogy mit kapunk:

  • /id -> 404 -> nem matchel a rulera
  • /id/ -> 404 -> ez sem
  • /id/6 -> ez mar igen

Eddig annyit tudunk hogy a rule-ban szerepel az "/id/" string.

tovább... ha nam para hogy megtoljuk a logot, vagy nagyon furcsa a helyzet akkor nekiláthatunk ciklusból rápörgetni az összes bájtot, én ezt preferálom mert legyünk precízek :P

Viszont többnyire elég kézzel is.

  • /id/a -> 404
  • /id/' -> 404

Ha /id/0 -tól /id/9 -ig mind jó lesz, és semmi más nem akkor joggal feltételezhetjük hogy a keresett minta a \d.

Ez nézhet ki úgy hogy:

  • /id/(\d+)
  • /id/([\d]+)
  • /id/([\d]{1,})
  • /id/([\d]{1,x})

A \d után biztos hogy nem * van mert a sima "/id/" kérésünk elhasalt 404-el, tehát mindenképpen kell utána lennie legalább egy \d -nek

Most kiderítjük mi van a \d után. 

  • 1 db \d: /id/1 -> OK
  • 2 db \d: /id/11 -> OK
  • 4 db \d: /id/1111 -> OK
  • 8 db \d: /id/11111111 -> OK
  • 16 db \d: /id/1111111111111111 -> OK

... ennyi itt most elég is

4096 db-nál már 403 Forbiddent dob az apacs, és kicsit sem látszik meg a logban amúgy :D

szóval ha 16 \d és még mindíg okék vagyunk tehát rajta vagyunk a rewrite rulon akkor ezt:

  • /id/([\d]{1,x})

kizárhatjuk, nincs hossz korlátozás.

A rule valahogy így néz ki eddig:

  • /id/(\d+)
  • /id/([\d]+)
  • /id/([\d]{1,})

Ha a rule karakterkészletre van szűrve, mint nálam az url:

http://niobium.hu/id/cec77b8f0178cacbc2538ee3bc2b0a03

Akkor ezzel a módszerrel elég jól be tudod határolni hogy a rule valami olyasmi hogy /id/, aztán ([0-9a-f]{32}) vagy ([\da-f]{32}) vagy ki tudja... :)

Érdemes megpörgetni mind a 256 bájt értéket azt mondom, mert hasznos ha tudod hogy milyen karakterek állnak rendelkezésedre és mik nem.

...illetve ki tudja hogy baszta el az admin/programozó.

No... Van ugye egy rulunk aminek csak \d -t tudunk átadni.

Sovány. Ahhoz hogy ezt bypassolni lehessen meg kell tudni a változót ami kapja a (jelen esetben) $1-et.

Tovább bonyolíthatja a helyzetet ha minden request rewrite áldozatául esik, ebben az esetben az utolsó reménysugár ha [QSA] -t is használnak a rule után. (Query String Append)

Ebben az esetben, illetve ha van akkora mázlink és tudjuk is a változó nevét, akkor ezt könnyen kideríthetjük mivel azt még hozzácsapja (?var=valami).

Pl.: /id/1?id=2, és a php azt látja hogy: $_GET['id'] == 2

A reverzelést kb lehetetlenné tudja tenni a chainelt ruleok használata is. ( [C] )

No de hagyjuk ezt, ilyenkor már a francnak van kedve ezzel foglalkozni... :D

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

misnyo 2010.06.23. 16:29:29

az utolsó példánál direkt nem valami.lofasz.tld az url, vagy csak nem cserélődött le?:)
amugy +1, tetszik

asd 2010.06.23. 17:12:32

# /id/([\d]+)
# /id/([\d]{1,})

Ezek nem mukodnek ugy ahogy vartad, [ ] kozott megadott karakterolsztalyban csak a ^ es - jeleknek van specialis jelentese. Szamokra pont nem illeszkedik egy sem :)

_2501 2010.06.24. 10:22:38

@asd: ezt fejtsd ki bovebben pls mert amit írtál az számomra inkonzisztens egy picit.
[ ] a character class-t (vagy set) jelöli.
Bármilyen karakterre illeszthető ami fel van sorolva benne, jelen esetben a \d-re illeszkedik a 0-9.

Továbbá a niobium.hu az nekem 404-et dob, szóval milyen reklám?
süti beállítások módosítása