packet-fu 1.

Azt beszéltük apuval 🙂 hogy a kiddós feltörések már mocskos unalmasak. Az a terv, hogy néhány módszert és technikát írásos formába öntök, ennek első morzsájaként született ez a post. Nem túl mély, de feltételezem hogy valamennyire képben van az olvasó a hálózati protkollokkal, és remélem hogy annak is tudok újat mondani aki arccal benne van a paketolásban.

Egy penteszt során amikor aktív paketolásra kerül a sor, az elsők között lefut egy portscan, többnyire nmap, -de ugye kinek mi a kedvenc scannere- amiből látszani fog néhány open port. Ezzel is meg lehet elégedni, hiszen ennyi információ elég ahoz hogy a szolgáltatásra lehessen uszítani az X/Y vulnscannert, ami böködi egy darabig a szolgáltatást/alkalmazást, aztán vagy mond valamit vagy nem. Az automatizált eszközök mindenféle okosságot elmondanak, de ne hagyjuk hogy elvakítson a könnyű haszon. Hasznosak -persze-, de nem mindenhatóak, elsiklanak a részletek fölött. Ezt majd egy másik alkalommal elpanaszkodom. 🙂

Most csak az open portokkal foglalkozunk, de a scannelésre még ebben a sorozatban visszatérek. Még annyit hogy a cikk méretére tekintettel nem fejtek ki mindent részletekbe menően, viszont feltüntetem hogy hol tudsz utánanézni. Most viszont lássuk miből élünk (és tényleg).

/1 játék a TTL -ekkel

Egy stock portscanből annyi látszik hogy X/Y IP címen N darab szolgáltatás figyel. Más kérdés hogy tényleg azon a vason fut-e a szolgáltatás, vagy épp csak ki van a port forwardolva/natolva. Ha erre zoomolunk, akkor egyrészt érdemes megvizsgálni a TTL-eket. Legyen egy egyszerű scenario: tűzfal mögött webszerver, amiről a tcp/80 ki van forwardolva. Az ICMP-re a tűzfal fog válaszolni, viszont a TCP/80-ra érkező csomagot hátradobja a webszervernek, aki visszaküldi a SYNACK-ot, és az esetek nagy részében a TTL-ek ilyenkor eltérnek. Valami ilyesmi van az rh.com-nál, úgyhogy vele fogok példálózni. Kapjunk elő egy Scapy-t.

>>> sr1( IP(dst="rh.com") / ICMP() ).ttl
56
>>> sr1( IP(dst="rh.com") / TCP(sport=12345, dport=80) ).ttl
55

Az rhdotkom tőlem 8 hop távolságra (network distance) van ha icmp-t nézek, 9 hop tcp-n.

56 és 55 (icmpttl=56, tcpttl=55) ha tippelhetnék akkor azt mondanám hogy ez két linux, de ha beesik egy ilyen hogy 61/123, akkor valószínűsíthetjük a linuxtűzfal mögött windows szerver felállást. Bár ez nem a végső bizonyság, nem mondhatom azt, hogy ha eltér a TTL akkor az portforward, de ha nem akkor az a szolgáltatás ott helyben fut. Túl egyszerű lenne. Az ao.com-ra pl a fenti script 55/56 -ot mond. Nincs ebben semmi meglepő. Az ilyen kis vizsgálatokat célszerű egy kis scripteléssel leegyszerűsíteni:

import logging, sys
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *
conf.verb = 0

dst = sys.argv[1]
dport = sys.argv[2]

icmp = sr1(IP(dst=dst)/ICMP(), verbose=None, timeout=0.1)
tcp = sr1(IP(dst=dst)/TCP(sport=43432, dport=int(dport)), timeout=0.1)
if (tcp is not None):
print “%-16s %3d/%-3d %-4s” % (dst, icmp.ttl, tcp.ttl, tcp.sprintf(“%TCP.flags%”))

A logger és a conf.verb azért kell hogy a scapy ne irkálja mindíg az ipv6 route és egyéb marhaságokat. Így fog kinézni ha használatba veszed:

# python ttltest.py rh.com 80
rh.com            56/55  SA

No de piszkálódjunk tovább.

/2 az IP options és a Record Route

A továbbiakban RR-ként fogok rá hivatkozni. Az IP options RR olyat tud, hogy az útnak indított csomag (IP) fejlécében az options mezőben szépen összegyűjti hogy kiken ment keresztül. Pontosabban amikor egy router megkapja, belenéz az options-be, mert hátha valami fontos dolog van ott, és ha azt látja hogy RR van akkor szépen beleírja magát a következő szabad helyre. A ping a -R kapcsolóval tud RR-es csomagokat küldeni:

ping -R -c1 rh.com

Traceroute feeling igen, de a traceroute a TTL-ekkel játszik, ez más tészta. Bár a RR csak 9 IP-t tud rögzíteni az options mező korlátozott méretéből adódóan, mégis van egy nagyon jó fícsöre, amit a traceroute nem tud. Az előbb ugye icmp/echorequest csomagokat eresztettünk útnak, de mi van akkor ha egy tcp/syn csomag IP options-ben állítom be az RR-t? Az van hogy visszajön a synack, immáron a routerek címeivel, és ha ez a port esetleg ki volt forwardolva egy belső IP-ről és még 9 hopon belül is vagyunk… akkor bizony ott fog sasolni néhány belső IP is a route-ok között. Ezt nem tudja a traceroute. Erre mindjárt visszatérünk, csak fontos hogy előbb lássunk bele a RR lelkébe.

Na akkor hogyisvanez? Rakjunk össze egy RR paketot. Scapy.

sr1(IP(dst="<IP>", options=IPOption('\x07\x27\x04' + '\x00'*36))/TCP(sport=12345, dport=80)).options[0].routers

Az IPOption összerakásához innen és innen lehet puskázni, (illetve javaslom a RFC791-et) de most úgyis csak az első 3 byte az érdekes.

\x07 – type: a 7 jelenti azt hogy Record Route
\x27 – length: itt most 0x27 az 39 byte
\x04 – pointer: ez mutatja hogy melyik az aktuális pozíció, ugyanis: A RR úgy működik hogy a host/router aki megkapja, megnézi ezt a pointert és ahova mutat, beleírja a saját címét, és növeli a pointert 4-el. Ha ez meghaladja az option méretét akkor nem nem veszi figyelembe.

A maradék \x00 a routerek címének a helye.

Térjünk vissza a portforwardos példához. Hogy néz ki ez élesben? Most a példa kedvéért két ismertebb weboldal lesz a szemléltetés eszköze.

>>> sr1(IP( dst="[cenzúrázva]", options=IPOption('\x07\x27\x04' + '\x00'*36))/TCP(sport=10203, dport=80)).options[0].routers

A kimenetek…. egyik:

['[cenzúrázva]', '[cenzúrázva]', '10.10.2.4', '10.10.2.2', '10.10.2.2', '[cenzúrázva]', '[cenzúrázva]', '[cenzúrázva]', '0.0.0.0']

másik…

['[cenzúrázva]', '[cenzúrázva]', '[cenzúrázva]', '192.168.200.71', '192.168.200.71', '[cenzúrázva]', '[cenzúrázva]', '[cenzúrázva], '0.0.0.0']

A webszerver IP-je az lesz, amelyik kétszer szerepel egymás után a listában, a többi meg routolás kérdése. Most egy picit térjünk vissza a TTL-hez. Ha elküldesz egy RR paketot, úgy hogy a TTL lejár mielőtt megérkezne a célhoz, a legtöbb host/router illedelmesen – a protokollnak megfelelően -, visszaválaszol egy ICMP time-exceed üzenettel. Ebből is hasznos infókat lehet levonni: Az ICMP csomag tartalmazni fogja a teljes IP/TCP packetot, beleértve a RR tartalmát is. Tömören annak az állapotnak megfelelő csomagot kapod vissza, amit az a host látott, akinél kihűlt a ttl. Az ICMP csomagok TTL-jéből lehet következtetni az eszköz típusára, és a RR adataival összevetve képet lehet kapni a hálózat kiépítéséről/routolásról. Egyes routerek a válasz ICMP IP headerjébe is beállítják az RR-t (, és ha jól sejtem akkor pont a linuxok ilyen barátságosak, de ez most lényegtelen).

Ezt a tesztet is célszerű lescriptelni, nekem is le van, de nem másolom be ide mert picinkét hosszú, Gitoriouson kint lesz hamarosan.

/3 TimeStamp-fu

Ez is egy IP option, csak ezzel a timestampeket lehet lekérdezni. Ez a módszer kicsit összetettebb mint a fentiek, de hatékony eszköz a hostok feltérképezésében. Most kicsit fordítok a sorrenden. Eddig azt mondtam el hogy hogyan működik, és aztán hogy mire lehet használni. Ez utóbbival kezdeném.

A TS-fu -val fel lehet térképezni hogy egy host milyen egyéb IP címeket tud a magáénak, milyen címek vannak felvéve. (RR segítségével a belső hálós gépeken is.) Játszadoztam egy ideje ezekkel, de miközben ezt a postot írtam, találtam meg Marek Majkowski levelét az nmap-dev listán, ami pont arról szól hogy belegyógyította az nmapba az IP optionst, és ő is leírta ezt a lehetőséget, szóval nem új.

Legelőször vizsgáljuk meg az ipoptions/timestamp-et. Arra való hogy az egyes hostokon le lehessen kérdezni a timestampet. Ez az option 4 Byte-tal kezdődik, amit a fent említett okok miatt nem fejtek ki részleteiben, de a networksorcery-n nagyon szépen le van írva. A 4 Bájtból az utolsó bájt utolsó 4 bitje a flag, amivel ki lehet választani a működést. Ennek a négy bitnek a lehetséges értékei:

  • 0: a hostok/routerek csak timestampeket rögzítik (4 byte / host)
  • 1: a saját IP címüket és a timestampet is rögzítik (8 byte/host – 4byte IP – 4byte TS)
  • 3: te adhatod meg hogy mely hostok timestampjére vagy kiváncsi!

Ez utóbbi segít nekünk most. Ennek a működési mechanizmusának a megértése adja a kulcsot. Az ip option amit készíteni fogunk az 20 byte hosszú lesz headerrel együtt, a következő képpen fog kinézni:

header  IP1     ts1     IP2     ts2

Nézzük akkor hogy hogyan néz ki a header 4 bájtja:

\x44\x14\x05\x03

\x44 – TS
\x14 – a teljes option hossza headerrel együtt: 2×8 + 4 = 20 = 0x14
\x05 – a pointer, az 5-ik bytera mutat
\x03 – a fent már említett “hogyan működjön a timestamp lekérdezés”

Amikor egy host megkapja ezt a csomagot, belenéz, látja hogy TS kérdés, megnézi hogy hova mutat a pointer. Jelenleg a pointer értéke 5, vagyis az IP1 -re mutat! Amennyiben a saját IP címét találja ott, úgy beleírja a timestampet, és inkrementálja a pointer értékét 8-al, ami így már az IP2-re fog mutatni.

Ez tömören az a működés amit ki fogunk használni. Ha úgy küldjük el ezt a csomagot hogy az IP1 valamelyik router címe, akkor addig senki nem fogja piszkálni az értékeket. Amikor megkapja az a host akihez tartozik, akkor a pointer az IP2-re irányítja. Eddig azt sikerült elérni hogy egészen az IP1-ig senki ne bolygassa a paketunkat.

A zsiványság ott kezdődik hogy az IP2 értékét is te adod meg. Ha 127.0.0.1 -et írsz bele akkor a következő host beleírja a timestampjét, mivel ezt az IP-t ő birtokolja. Ha 192.168.12.34 -et adsz, és az övé a cím, akkor beleírja a timestampet. Megvan a lényeg igaz? Na tömören: Ha az N-edik host által ownolt IP-ket akarjuk lekérdezni akkor az N-1 -ik host-ot állítjuk be IP1-nek, és az IP2 értékében bruteforce-oljuk ki a címeket.

Na csak hogy ne legyen annyira egyszerű, van még egy csavar a történetben: Mi van akkor ha nem az N-edik hosté az IP2, hanem valahol a visszafelé routon valaki másé? Honnan fogod tudni hogy a célpont (az N-edik host) rakta bele a TS-t vagy valaki utána? Hmm.. hmm… pontosítani kell a technikán. Szerencsére nem kell túl messzire menni a megoldásért, egy kis agyalással ez sem bonyolultabb feladat mint kirakni az aknakeresőt.

Három lehetséges megoldás:

  1. Elméletileg megoldható a TTL-el játszadozva, de ezt nem teszteltem ki.
  2. Ha az N-edik hostot akarod vizsgálni akkor felveszel még 8 bytot, és akkor az N+1-edik lesz az IP3, aminek a routeban látott valós címet adsz meg. Ha ez nem lesz kitöltve akkor tudod hogy nem az N-esik host írta bele magát. Ez elég megbízható így.
  3. A header 4.-ik byteja, ami jelen esetben 0x03 volt, az 2x4bit, aminek az első fele az overflow, a másik fele a flag. Na de mit csinál az overflow? Ha egy host azt látja hogy pointer nagyobb mint az option mérete, akkor növeli az overflow értékét, márpedig az IP2-n túl mindegyik ezt fogja tenni. Tömören fogalmazva: ennek az értékéből tudjuk meg hogy hány host lett kihagyva a játékból. Úgy tudjuk felhasználni ezt a működést, hogy a legelső vizsgálatnál az IP2-ben lekérdezzük a 127.0.0.1 -et, amire ténylegesen a célzott host fogja magát beleírni. Ekkor kell megvizsgálni az overflow értékét: ebből megtudjuk hogy hány host volt még utána. Az összes többi cím vizsgálatakor ezzel fogjuk összehasonlítani az overflow értékeket. Ha egy cím vizsgálatakor ez kevesebb, akkor a kettő különbségéből tudjuk meg azt hogy a cél gép után hanyadik host tudja magáénak.

Én ezt a metódust implementáltam a tooljaimba, amit hamarosan kipakolok a gitre, TS-fu vagy valami hasonló néven fogjátok megtalálni. Ízelítőnek itt egy kis output (bocs a cenzúrákért -_-):

# python TS-fu.py rr [cenzúrázva] 80
RR:
[cenzúrázva]
[cenzúrázva]
[cenzúrázva]
192.168.8.110
192.168.8.110
[cenzúrázva]
[cenzúrázva]
[cenzúrázva]
0.0.0.0


# python TS-fu.py tsfu [cenzúrázva] 80 [cenzúrázva]
TS-fu:
doin some test...
ref: 127.0.0.1 (ptr=21 ovrflo=3)
scanning nets...
Net found: 192.168.8.0 (ptr=21 ovrflo=3)
scanning IPs...
IP found: 192.168.8.1 addr used by another box behind this one. (distance=1 hop ptr=21 ovrflo=2)
IP found: 192.168.8.2 addr used by another box behind this one. (distance=1 hop ptr=21 ovrflo=2)
IP found: 192.168.8.7 addr used by some local iface (ptr=21 ovrflo=3)
IP found: 192.168.8.11 addr used by some local iface (ptr=21 ovrflo=3)
IP found: 192.168.8.110 addr used by some local iface (ptr=21 ovrflo=3)

Záró akkordok…

A fent leírt módszereknek egyéb felhasználási területei is lehetnek, pl. egyes loadbalancing megoldások (nem proxyzó) mögött a backendek számának bemérése, ezek súlyozásának becslése. Most nem térek ki ezekre. Az IPoptions kitiltásával lehet védekezni.

/EOF

Átemelve http://buhera.blog.hu/2013/01/27/packet-fu

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s