Ú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
misnyo 2010.06.23. 16:29:29
amugy +1, tetszik
asd 2010.06.23. 17:12:32
# /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 :)
asd 2010.06.23. 17:13:32
_2501 2010.06.24. 10:22:38
[ ] 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?