redir hry s arp a icmp
existuju bugy a existuju features. castokrat je rozdiel medzi oboma iba v oku
vsemohuceho. chcem ukazat dva legitimne protokoly, ARP a ICMP, ktore ked sa
spravne implementuju, dokazu spravit cosi co nie je, ehm, nie je ziaduce.
kym pasivne utoky (sniffing) ktore zneuzivaju rootovsky pristup po LANke su
extremne popularne a aj lamerske rootkity maju vzdy aspon nejaky jeden net sniffer,
aktivne utoky zase nie su az take rozsirene. ale aktivna ucast v zivote vasej
LANky vam moze priniest kopec zabavy a radosti. to ste asi uz vedeli, akurat technicke
detajly boli nejak zahmlene. takze, budiz svetlo.
postupy ktore vysvetlim zahrnuju spoofing a DoS. aj ked ine druhy spoofingu,
ako napriklad IP blind spoofing, su omnoho vseobecnejsie a silnejsie, z pohladu
vyuzitelnosti pozaduju kopu roboty, hadania, a tazko sa implementuju. ARP spoofovanie je
naproti tomu velmi jednoduche a robustne.
aj ked ARP spoofovanie je mozne iba na lokalnej sieti, moze to znamenat seriozny
bezpecnostny problem ktory rozsiri uz existujucu dieru v bezpecnosti. ak sa niekto nabura
na jeden server na subnete, ARP spoofing moze byt pouzity na napadnutie ostatnych masin na nom.
zoberme si takuto hypoteticku siet
IP 10.0.0.1 10.0.0.2 10.0.0.3 10.0.0.4
hostname cat rat dog bat
hw addr AA:AA BB:BB CC:CC DD:DD (pre skratenie)
to vsetko mame pospajane na ethernete jednoduchym sposobom (t.j. ziadne switche,
ziadne smart huby). dajme tomu ze si hackol masinu cat, mas na nej roota a chces sa
dostat na dog. vies ze dog ma trust vztah s rat, takze ak dokazes uspesne spoofnut rat, mozes
cosi ziskat.
prva vec co nas napadne (myslim ze kazdeho to asi raz napadlo) je "preco si nenastavim
svoju IP adresu na adresu tej druhej masiny a..." To zial nefunguje, alebo aspon nefici to
poriadne. ak povies ethernetovemu driveru na cat ze jeho IP adresa je 10.0.0.2, zacne odpovedat na
ARP requesty na tej IP adrese. ale takisto aj rat. je to race podmienka a neexistuje v nej
vitaz. ale lahko sa moze stat ze sa z teba stane porazeny, pretoze tato konkretna situacia
sa odohrava dost casto ked sa nejaka masinka zle nastavi na uz existujucu IP adresu, takze kopu
softwaru si takuto vec hned vsimne a okamzite spustaju poplach. aj vselijake traffic analyzere na taketo
nieco upozornuju. riadok v syslogu ktory hovori cosi neprijemne (spominajuc ethernetovu adresu cat-u) na
konzole LAN administratora nie je zrovna to co potrebujes. a to co ty chces nemusis vobec mat,
cize dostat fungujuce spojenie.
tomuto ale mozeme samozrejme pomoct. program na konci tohoto clanku, send_arp.c,
moze byt uzitocny nastroj. ako hovori jeho meno, posle ARP packet [presnejsie povedane
ARP reply: pretoze v ARP protokole bude reply s radostou privitany aj ked si ho nikto nevyziadal.
request by tiez v pohode fungoval, toto je dost divna logika ARP protokolu] na siet a mozes spravit
z tohoto packetu co chces. co potrebujes je schopnost specifikovat zdrojovu a cielovu IP a hardwarova adresu.
zaprve nechces aby bol tvoj ethernet driver moc ukecany, a to sa lahko docieli
prikazom ifconfig -arp. samozrejme bude potrebovat aj tak ARP info, takze ho budes
musiet krmit do kernelu manualne cez arp(8). najdolezitejsia cast je presvecit svojich
susedov. v tomto pripade chces aby dog veril ze hardwarova adresa rat je ta co ma cat (AA:AA),
takze posles ARP reply so zdrojovou IP adresou 10.0.0.2, zdrojovou hw adresou AA:AA,
cielovou IP adresou 10.0.0.3 a cielovou hardwarovou adresou CC:CC. teraz si mysli dog ze
rat je na AA:AA. samozrejme zaznam v cache expajruje, takze ho musime updatovat (request musime
znovu a znovu posielat). ako casto, to zalezi od konkretneho systemu, ale kazdych 40 sekund
by malo stacit vo vacsine pripadov. kludne to poslite aj castejsie, nic sa neublizi.
moze nastat komplikacia v suvislosti s ARP caching. niektore systemy, napr. Linux sa budu
snazit updatovat cache vyslanim unicast ARP requestu na cachovanu adresu (ako ked ti manzelka
zavola aby sa presvecila ze si tam). takyto request moze vsetko posrat, pretoze zmeni
ARP zaznam obete, ktory si prave fejkol, takze tomu musime zabranit. toto dosiahneme tak,
zze nakrmime "manzelku" s reply packetmi ktore si nikdy nevyziadala. prevencia je najlepsi liek,
ako vzdy. tentokrat, skutocny packet z dog na rat by mal byt zaslany, akurat ho posle cat, a nie dog,
ale rat to nedokaze rozlisit. opat, pokial to spravime kazdych 40 sekund, vacsinou to staci.
takze postup je jednoduchy. nabehni aliasovy interface, napr. eth0:1 (alebo pouzi uz existujuci,
to je fuk), s IP adresou rat a so zapnutym ARP protokolom - najprv musis nastavit cache vstupy,
a nebude to fungovat na ne-arpovom interfaci. nastav host route pre dog cez spravny interface. nastav
cache vstup pre dog, vypni arp, a vsetko mas nastavene.
teraz posli send_arp (na dog aj na rat) a teraz si dog mysli ze si rat. pamataj na to ze mas
dookola posielat tieto ARP packety na dog aj rat.
tento utok funguje iba na lokalnej sieti, samozrejme (vo vseobecnosti sa da povedat
ze ho mozes pouzit tak daleko ako mozu ist ARP packety, vacsinou to vsak nie je velmi daleko, pretoze
sa skoro nikdy ARP packety neroutuju). zaujimave rozsirenie je vymenit hardwarovu adresu v hore nacrtnutom
sceneriu s routerovou adresou. ak to funguje (nie som si isty ze to vzdy bude fungovat, implementacia ARP
routeru sa tazsie da okaslat a kedze to nechcem skusat na skutocnych routeroch, neviem, ale jednoducho
neexistuje dovod preco nie) mozes sa lahko tvarit ako masina na lokalnej sieti pre cely svet. takze
cielova masina moze vlastne byt hocikde, ale masina na ktoru sa tvaris musi byt na tej istej LANke.
co este mozeme robit
okrem spoofovania mozes s ARP robit este kopec veci. jedinym limitom je obloha. DoS je
najzavnejsou aplikaciou.
krmit obet zlou hardwarovou adresou je silny sposob ako ju umlcit. mozes zabranit aby
komunikovala s konkretnou masinou (a velkost ARP cache zvycajne umoznuje zahrnut do toho
celu siet, takze dokazes efektivne zabranit komunikacii s celou sietou). zjavnou obetou
je router. Zaplnanie cache je opat dvoj-smerne: mal by si krmit aj victim system, aj
system na ktory nexces aby victim komunikoval. Najjednoduchsi sposob je krmit neexistujucu
adresu. Ale nie je to ta najefektivnejsia metoda, pretoze system rychlo pride na to ze
s nikym nekomunikuje a posle ARP request. Samozrejme ze tvoj dalsi vyslany jed to vynuluje, ale
musis to robit dost casto. Efektivnejsi sposob je krmit victim hardwarovou adresou nespravnej
masiny, ktora sama o sebe je v pohode na sieti. zalezi to na konkretnej situacii, ale casto
sa stava ze victim vysiela packety rozneho druhu ktore prijdu na zlu masinu, a ta zla masina
posle naspat ICMP Xxx Unreachable odkaz, co nejakym perverznym sposobom emuluje spojenie.
Taketo pseudo-spojenie moze predlzit expiraciu cache. Na linuxe, napriklad, pseud-spojenie
predlzi expiraciu cache z beznej 1 minuty na zhruba 10 minut. do vtedy vacsina alebo vsetky
TCP spojenia su v kybli. to moze dost nasrat. takymto sposobom moze ARP packet niekoho fest dokaslat.
ARP je aj seriozny nastroj na profesionalny cierny humor. predstavte si ze niekto si
nastavi relay, alebo tunel, tak ze presvedci dve susediace masiny aby posielali packety
urcene pre vzajomnu komunikaciu na Ethernet relay. Ak relay jednoducho forwarduje packety na
ich spravnu destinaciu, nikto si nic nevsimne. Ale jednoducha modifikacia datoveho toku moze
spravit uchvatne zmeny v mentalnom stave jedinca. Jednoduchy CPU-nenarocny "filter" moze
prehadzovat randomne dva bajty v nepravidelnych casovych intervaloch. Ak filter udrie na
datovu cast, vacsinu checksumu sa nezmeni, t.j. datovy tok sa bude zdat byt neposkodeny, avsak
divne a nevysvetlitelne veci sa _budu_ diat bez akehokolvek zjavneho dovodu.
ICMP redirekty
stejneho efektu jako ARP kes poisoning muzete dosahnout i jinak, pouzitim
legitimni soucasti ICMP protokolu - ICMP route redirekt.
v normalnich situacich je route redirekt pouzivan routerem, ktery se vam
snazi sdelit, ze existuje i kratsi cesta k nejake konkretni masine nez pres
nej. puvodne se pocitalo jak s redirekty na site tak na jednotlive masiny, ale
pozdeji se od pouzivani net redirektu upustilo a jsou vetsinou zpracovavany
jako obycejny host redirekt. spravne zkonstruovany ICMP paket, ktery projde
vsemi kontrolami spravnosti (napr. musi prijit z defaultniho routeru pro
tu destinaci kterou redirektuje, novy router by mel byt na primo pripojene
siti apod.) zpusobi pridani host-route zaznamu do systemovych routovacich
tabulek.
tento pristup je stejne bezpecny jako samotny protokol ICMP, to jest vubec.
falsovani IP adresy routeru je velmi jednoduche, prilozeny program
icmp_redit.c dela presne co potrebujeme. pozadavky kladene RFCkem rikaji, ze
system MUSI vzdy akceptovat ICMP redirekt, a jedinou vyjimku maji routery.
jednotlive implementace to samozrejme dodrzuji, funguje to vsude kde jsem to
zkousel. (tedy s vyjimkou cisteho kernelu 2.0.30, kde je kod nejak pokaslany.
jinak to funguje na 2.0.29 i na 2.0.31pre9).
ICMP redirekt se primo nabizi pro denial-of-service utoky. host-route
zaznamy v routovacich tabulkach nejsou casove omezeny, takze jejich platnost
nevyprsi tak jako u ARP kese. navic jeho pouzitelnost neni omezena na
lokalni sit, takze utok muze prijit odkudkoliv. takze v pripade, ze cil
prijima ICMP redirekty (a je pristupny po siti), muze mu byt zabraneno v
komunikaci s kteroukoliv konkretni adresou na siti (samozrejme s vyjimkou
masin na stejnem subnetu, kde se routing nepouziva). idealnim cilem jsou
treba nameservery.
co s tim
ARP je protokol pouzivany na nizke urovni, tudiz se s nim obvykle nesetkate,
respektive setkate, ale nevite o tom. obcas se s nim potykaji administratori
siti, ale pokud vse facha jak ma, nikdo se o nej nestara. kdokoliv se muze
podivat do ARP kese prikazem arp(8), ale obvykle to jen tak nekoho
nenapadne, leda pokud se vyskytl nejaky naprosto totalne zahadny problem.
dokonce i windows 95 maji prikaz arp, a jeho znalost vam muze obcas dobre
pomoct. (nicmene neexistuje zpusob, jak poznat ze jste cilem utoku
prichazejicho z cizi site pres gateway arp spoofing.) stejne jako u ARP kese
neni tezke najit zaznamy "host-route" zaznamy zpusobene ICMP redirektem,
proste se podivejte do systemovych routovacich tabulek. (ve vetsine verzi
route(8) takovy zaznam poznate podle flagu "D"). jen abyste vedeli.
hore prezentovane schema ARP utoku funguje perfektne na obycejnem 10Base2
ethernetu. nicmene pokud jsou masiny propojeny nejaky pokrocilejsim
zpusobem, trebas nejakymi smart huby nebo switchi, utok muze byt velmi
napadny, ne-li rovnou nemozny. (a to plati i pro pasivni utoky). takze to je
dalsi z duvodu proc byste meli investovat do fakt poradneho sitoveho zeleza.
bude se vam o poznani lepe spat.
osobne vubec nerad vidim, ze veci jako ICMP redirekt byly implementovany
jako defaultni soucast systemu. za prve - vetsina siti ma velmi jednoduchou
strukturu, takze si v pohode vystacite s obycejnou routovaci tabulkou. za
druhe - i v sofistikovanejsich sitich lze zmeny delat rucne, neni to zadna
dynamicka zalezitost, tak proc to delat pres ICMP? a do tretice - je to tak
nebezpecne, ze bych to nejradsi na mych systemech vypnul, i za cenu ze budou
mene kompatibilni s RFC1122. bohuzel to nemusi byt tak jednoduche. na linuxu
nebo kteremkoliv jinem open-source systemu muzu prinejhorsim upravit
zdrojaky kernelu a deaktivovat kod pomoci #define. na IRIXech 6.2 (a mozna i
jinejch verzich) lze nastavit icmp_dropredirects=1 nastrojem systune (jo,
fakt se mi libi ze to tam je, fakt jo.) jine OS mohou byt podobne
konfigurovatelne, ale nemam podrobnejsi informace.
u ARP protokolu se setkavame se situaci, kdy je resolvovani jmen vyreseno
dynamicky bez nejakeho centralniho serveru. ale nemusi tomu tak byt vzdy.
kdyz nekdo chce prevest hostname na IP, posle se dotaz na nameserver, nebo
se pouzije /etc/hosts, to znamena, ze je pouzito nejake staticke mapovani.
nevidim duvod proc tento pristup nepouzit i u ARP. ethernetove hardwarove
adresy se nemeni casto, a kdyz uz nahodou, tak to prece admina nijak
nezabije provest zmeny v prislusne tabulce. ethernet muze byt provozovan v
no-cache modu, potrebujete se jen ujistit ze zaznamy v ARP cache budou
permanentni. jako bonus usetrite trochu sitoveho provozu. ARP mapy muzete
distribuovat beznymi zpusoby, napriklad rdist, rsyns (ano, NIS by se take
dalo pouzit, ale predpokladam, ze jestli pri zajisteni bezpecnosti jdete tak
do hloubky ze se zabyvate ARP protokolem, nepouzivate asi NIS). stara
tradice /etc/ethers se muze znovu probrat k zivotu. ale zprovozneni nejakeho
poradneho ethernetoveho switche mi prijde lepsi (s jeho zaplacenim je to ale
horsi, heh).
stara moudrost je platna naveky: nepouzivejte autentifikaci zalozenou na
hostname. ti kteri tak ucini, budiz uvrzeni v nemilost sitovych bohu.
cheers,
yuri, volobuev@t1.chem.umn.edu
P.S. jeste k firewallum
presne vidim, jak hodne z vas po precteni sekce o ICMP svrbi prsty, abyste
mi napsali, ze ICMP pakety jdou v pohode odfiltrovat na firewallu. nepiste
mi. ja to vim.
znam hodne lidi, kteri se svym "ja mam firewall, je to super,
a kdo nepouziva firewall, je totalni blb" rikaji ze plno bezpecnostnich
problemu se vyresi jako mavnutim kouzelnym proutkem jen tak, ze mezi sebe a
zle hochy date firewall. samozrejme souhlasim ze firewall je skvela vec, ale
podotykam, ze jeho pouziti nemusi byt vzdy mozne nebo efektivni.
predstavte si prostredi, kde vsechny masiny jsou primo pripojeny na
internet, kde musite sdilet subnet s lidmi ktere vubec neznate (a kteri
samozrejme maji krasna nova vylestena SGIcka... kricici "tu jsem. pojdte si
me hacknout". tihle lide prece znaji UNIX, vzdyt ho videli v Jurskem
Parku.), nebo kde ma nad vasim routerem kontrolu cizi organizace. vitejte na
akademicke pude ... tady firewally nepouzivame. dalsi vec je, ze v techto
prostredich se nemusite tak bat cizich utocniku tolik jako insideru. bez
pecliveho zabezpeceni jednotlivych stroju je to totalni dzungle, ve ktere
ale nekteri lide potrebuji (kupodivu) pracovat. takze priste az budete
nekoho lamat do firewallu, uvedomte si prosim, ze to je krasna vec, ale
nehodi se pro kazdeho.
/* send_arp.c
tento program posle jeden ARP packet so zdrojovou/cielovou IP a ethernetovou
hardwarovou adresou zadanou uzivatelom. da sa to skompilovat a bezi to pod
linuxom ale pravdepodobne to funguje na hocijakom unixe co ma SOCK_PACKET
yuri, volobuev@t1.chem.umn.edu
*/
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <sys/socket.h>
#include <linux/in.h>
#include <arpa/inet.h>
#include <linux/if_ether.h>
#define ETH_HW_ADDR_LEN 6
#define IP_ADDR_LEN 4
#define ARP_FRAME_TYPE 0x0806
#define ETHER_HW_TYPE 1
#define IP_PROTO_TYPE 0x0800
#define OP_ARP_REQUEST 2
#define DEFAULT_DEVICE "eth0"
char usage[]={"send_arp: sends out custom ARP packet. yuri volobuev'97n
tusage: send_arp src_ip_addr src_hw_addr targ_ip_addr tar_hw_addrnn"};
struct arp_packet {
u_char targ_hw_addr[ETH_HW_ADDR_LEN];
u_char src_hw_addr[ETH_HW_ADDR_LEN];
u_short frame_type;
u_short hw_type;
u_short prot_type;
u_char hw_addr_size;
u_char prot_addr_size;
u_short op;
u_char sndr_hw_addr[ETH_HW_ADDR_LEN];
u_char sndr_ip_addr[IP_ADDR_LEN];
u_char rcpt_hw_addr[ETH_HW_ADDR_LEN];
u_char rcpt_ip_addr[IP_ADDR_LEN];
u_char padding[18];
};
void die(char *);
void get_ip_addr(struct in_addr*,char*);
void get_hw_addr(char*,char*);
int main(int argc,char** argv){
struct in_addr src_in_addr,targ_in_addr;
struct arp_packet pkt;
struct sockaddr sa;
int sock;
if(argc != 5)die(usage);
sock=socket(AF_INET,SOCK_PACKET,htons(ETH_P_RARP));
if(sock<0){
perror("socket");
exit(1);
}
pkt.frame_type = htons(ARP_FRAME_TYPE);
pkt.hw_type = htons(ETHER_HW_TYPE);
pkt.prot_type = htons(IP_PROTO_TYPE);
pkt.hw_addr_size = ETH_HW_ADDR_LEN;
pkt.prot_addr_size = IP_ADDR_LEN;
pkt.op=htons(OP_ARP_REQUEST);
get_hw_addr(pkt.targ_hw_addr,argv[4]);
get_hw_addr(pkt.rcpt_hw_addr,argv[4]);
get_hw_addr(pkt.src_hw_addr,argv[2]);
get_hw_addr(pkt.sndr_hw_addr,argv[2]);
get_ip_addr(&src_in_addr,argv[1]);
get_ip_addr(&targ_in_addr,argv[3]);
memcpy(pkt.sndr_ip_addr,&src_in_addr,IP_ADDR_LEN);
memcpy(pkt.rcpt_ip_addr,&targ_in_addr,IP_ADDR_LEN);
bzero(pkt.padding,18);
strcpy(sa.sa_data,DEFAULT_DEVICE);
if(sendto(sock,&pkt,sizeof(pkt),0,&sa,sizeof(sa)) < 0){
perror("sendto");
exit(1);
}
exit(0);
}
void die(char* str){
fprintf(stderr,"%sn",str);
exit(1);
}
void get_ip_addr(struct in_addr* in_addr,char* str){
struct hostent *hostp;
in_addr->s_addr=inet_addr(str);
if(in_addr->s_addr == -1){
if( (hostp = gethostbyna