Private Release : UNIX System Security Research Labs : final.version[b#3rc2]
==============================================================================
B U F F E R O V E R F L O W S B Y E X A M P L E
BIND 8.2.3-REL & ProFTPd 1.2.0rc2
=============================================[ by slash <
[email protected]> ]===
(0x00) U v o d
==============
Evo odlucio sam malo pojasniti bugove u BIND-u te proftpd-u za koje slobodno
mozemo reci da su jedni od najkoristenijih DNS/FTP servisa danas. Preporucujem
ovaj tekst svatkom tko zna C ili se jednostavno bavi hackingom kako bih shvatili
gdje se nalazi bug, ili u drugom slucaju kako se nebi sve svelo na jednostavno
pokretanje exploita.
(0x01) BIND 8.2.3-REL Bug #1
============================
BIND-8.2.3-REL/src/bin/named/ns_update.c:1636
case T_SIG:
if (dlen < SIG_HDR_SIZE || size < dlen)
return (0);
memcpy(cp1, cp, SIG_HDR_SIZE);
size -= SIG_HDR_SIZE;
cp += SIG_HDR_SIZE;
cp1 += SIG_HDR_SIZE;
n = dn_expand(msg, eom, cp, (char *)cp1, size);
if (n < 0 || n + SIG_HDR_SIZE > dlen)
return (0);
cp += n;
n1 = dlen - n - SIG_HDR_SIZE;
n = strlen((char *)cp1) + 1;
cp1 += n;
/* #1 */
if (size < n1)
return (0);
memcpy(cp1, cp, n1);
cp1 += n1;
return (cp1 - cp1init);
Ova funkcija je zaduzena za procesiranje T_SIG "resouce records"-a unutar
UPDATE paketa. Buffer overflow se dogadja zato sto dolazi do asinkronizacije
pointera `cp1' i variable `size'. `cp1' je pointer u data buffer u koji se pise
kod procesiranja paketa a `size' je broj preostalih, neiskoristenih byteova
unutar buffera. U ovom slucaju autor je je zaboravio oduzeti broj byteova koji
se upisuju u buffer (putem funkcije dn_expand) od variable `size'. Ovo nam
omogucuje da prepisemo buffer sa 1025 byta (MAXDNAME) minus par byteova zbog
memcpy.
Da bi ispravili bug moramo kod oznake #1 unijeti sljedecu liniju:
size -= n;
(0x02) BIND 8.2.3-REL Bug #2
============================
BIND-8.2.3-REL/src/bin/named/ns_update.c:1655
case T_NXT:
n = dn_expand(msg, eom, cp, (char *)cp1, size);
if (n < 0 || (u_int)n >= dlen)
return (0);
size -= n;
/* #1 */
cp += n;
n1 = dlen - n;
n = strlen((char *)cp1) + 1;
cp1 += n;
if ((*cp & 0x80) == 0) {
if (n1 < 4 || n1 > 16)
return (0);
}
if (n1 > size)
return (0);
memcpy(cp1, cp, n1);
cp1 += n1;
return (cp1 - cp1init);
Ovdje autori BIND-a grijese ne znajuci svrhu svog API-a. Funkcija `dn_expand'
vraca broj byteova za koliko je povecan "processing pointer". Ali moze pisati
samo `size' byteova u uotput buffer, koji je zadan pointerom `cp1'. Ipak `size'
se smanjuje zbog pogresne vrijednosti (broja byteova za koliko se pomaknuo "source
pointer"), dok se pointer `cp1' krece normalno. Ovo moze dovesti do buffer overflowa
u kojem slucaju mozemo prepisati MAXDNAME byteova izvan buffera.
Ovi overflowi su interesantni, ali ne i korisni (osim u nekim slucajevima kad
imamo arhitekture sa razlicitim "stack layout"-om, ili imamo privilegije za
izdavanje UPDATE paketa itd.).
(0x02) ProFTPd 1.2.0rc2
=======================
proftpd-1.2.0rc2/modules/mod_ls.c:333
char *p = nameline + strlen(nameline);
...
snprintf(p, sizeof(nameline) - strlen(nameline) - 4, " -> %s", l);
Gdje je nameline buffer na stacku.
char nameline[MAXPATHLEN + MAXPATHLEN + 128] = {'\0'};
Problem se manifestira ako je strlen (nameline) > (sizeof (nameline) - 3)
zato jer parametar duljine kod snprintf funkcije postaje negativan, te se
ponasa kao normalna sprintf funkcija. Iako nije moguce postici velicinu
buffera vecu od 124 bytea, ovaj bug pokazuje da "sign conversion" bugovi
jos uvijek postoje unutar popularnih programa i danas.
(0x02) Z a k lj u c a k
=======================
U ovom tekstu sam zelio pokazati koliko je bitno citati kod programa pa i
svog po nekoliko puta, jer kod programa koji koriste puno funkcija cesto
dolazi do zabune da ni sami autori neznaju svrhu svojih API poziva.
Shouts: predator, sirius, random, #!/bin/zsh .
Unix System Security Research Labs
slash - 14. Listopad anno 2000 (18:04pm)
[email protected] /
[email protected] /
[email protected]
"Use the source Luke" - unknown
Freelance security consultant -
UNIX Administrator -
www.avalon.hr -
[email protected]