Date: Fri, 10 Jul 1998 11:43:55 -0700
From: Zach Brown <zab@zabbo.net.>
To: [email protected]Subject: socks5 1.0r5 buffer overflow..
We on the LSAT have also been poking around code that people are likely to
be running on linux boxen. At work I was asked to install socks5 on our
gateway boxes and thought it would be a good idea to make sure it was ship
shape. I was quite impressed with the careful coding, till I ran across
this one foul up in lib/log.c:
void S5LogvUpdate(const void *handle, int level, int msgID, const char
*oformat, va_list pvar) {
char fmt_cpy[2*1024 + 2*10], format[2*1024 + 2*10];
... copy oformat to format ..
vsprintf(fmt_cpy, format, pvar);
Bummer. When combined with some environment variables this can lead to a
local exploit of anything liked with libsocks5. More disturbingly, if
you've compiled your socks5 server with libident and feed it just the
right info it seems possible to overflow it's stack in a similar fashion.
The attached patch fixes it under glibc, at least. Season to your
vsnprintf's return codes to taste. Or hook in a vsnprintf from
openbsd/glibc if your unix is hopeless enough to not have it.
the NEC guys have this patch, and a cool (but hairy enough for me to not
feel safe posting it) patch from Dave Blob that integrates openbsd's
vsnprintf, but they need some time to mull over the licsensing/liability
issues of using external code. I didn't want people to be bitten by this
in the mean time..
-- zach
- - - - - -
007 373 5963
diff -r -u socks-dist/lib/log.c socks5-v1.0r5/lib/log.c
--- socks-dist/lib/log.c Thu Feb 19 10:49:56 1998+ socks5-v1.0r5/lib/log.c Wed Jul 1 16:39:30 1998
@@ -77,7 +77,8 @@
}
void S5LogvUpdate(const void *handle, int level, int msgID, const char *oformat, va_list pvar) {
- char fmt_cpy[2*1024 + 2*10], format[2*1024 + 2*10];
+#define FMT_BUFLEN (2*1024 + 2*10)
+ char fmt_cpy[FMT_BUFLEN], format[FMT_BUFLEN];
S5LogHandle *h = (S5LogHandle *)handle;
int serrno = GETERRNO();
static int dontLoop = 0;
@@ -112,7 +113,9 @@
strcat(format, " ");
replacePercentM(oformat, format + strlen(format), sizeof(format) - strlen(format));
- vsprintf(fmt_cpy, format, pvar);
+ if(vsnprintf(fmt_cpy, FMT_BUFLEN-1,format, pvar)==-1) {
+ fmt_cpy[FMT_BUFLEN-1]='\0';
+ }
/* Log to the Local log facility, e.g. Stderr on Unix and maybe a window */
/* or something on NT. Neither system can deal with a NULL format so */