Secure Network Operations, Inc. http://www.secnetops.com Strategic Reconnaissance Team research@secnetops.com Team Lead Contact kf@secnetops.com Our Mission: ************************************************************************ Secure Network Operations offers expertise in Networking, Intrusion Detection Systems (IDS), Software Security Validation, and Corporate/Private Network Security. Our mission is to facilitate a secure and reliable Internet and inter-enterprise communications infrastructure through the products and services we offer. Quick Summary: ************************************************************************ Advisory Number : SRT2003-04-24-1532.txt Product : Options Parsing Tool shared library Version : <= opt-3.18 Vendor : http://nis-www.lanl.gov/~jt/ Class : local Criticality : Low Operating System(s) : Linux (other unix based?) High Level Explanation ************************************************************************ High Level Description : Error messages can cause buffer overflow What to do : recompile and link against newest libopt.a Technical Details ************************************************************************ Proof Of Concept Status : No PoC needed for this issue. Low Level Description : The Options Parsing Tool shared library is a subroutine library which facilitates the convenient input of parameters to a C or C++ program. The package attempts to provide a direct and relatively full-featured input interface to the end user of the program, and at the same time impose a minimal amount of work on the programmer to "attach" the package to his or her software. I am not aware of any suid programs linking against this library but at the very least Debian provides it as a .deb package. Obvious issues are raised if a suid application makes use of the OPT libraries. http://packages.debian.org/stable/devel/opt.html The error messages in opt pass through one of several functions in order to print the error to the screen. Either opt_warn_1(), opt_warn_2(), opt_warn_3(), opt_fatal_1(), opt_fatal_2(), or opt_fatal_3() will be used when an error occurs. Several similar functions could cause issues with buffer overflows. This simple test will show the problems associated with using <= opt-3.18 [dotslash@vegeta test]$ cat > test.c main(int *argc, char **argv) { /* use lubc atoi() */ int x = atoi(argv[1]); printf("atoi(): %i\n", x); /* use OPT opt_atoi() */ int y = opt_atoi(argv[2]); printf("opt_atoi(): %i\n", y); } [dotslash@vegeta test]$ cc -o test test.c ../src/libopt.a [dotslash@vegeta test]$ ./test 1 2 atoi(): 1 opt_atoi(): 2 [dotslash@vegeta test]$ ./test `perl -e 'print "A" x 986'` B atoi(): 0 OPT Warning: String [B] is not a valid integer, will use [0] opt_atoi(): 0 [dotslash@vegeta test]$ ./test A `perl -e 'print "A" x 986'` atoi(): 0 OPT Warning: String [AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA... is not a valid integer, will use [0] opt_atoi(): 0 Segmentation fault strace tells us that we are able to overwrite the eip. [41414141] --- SIGSEGV (Segmentation fault) @ 0 (0) --- This occurs because of the following code is triggered when reading input from the user. long opt_atoi(char *s) { int valid; long x; x = (long)atof(s); /* Call atof() whether or not string is valid, * because some strings, eg '15x' can still be * interpreted as numeric. But give a warning * unless the string really is valid */ valid = opt_isvalidnumber(s); if (!valid || (valid & OPT_NUM_FLOAT)) { opt_warn_2("String [%s] is not a valid integer, will use [%ld]",s,x); } return x; } This particular segfault was caused by the opt_warn_2 definition in opt_p.h. You can see that the data passed on by the user is used in a sprintf() into a static sized buffer. #define OPT_ERRMAXSTRLEN 1024 /* shouldn't be fixed length, but it is! */ ... #define opt_warn_2(fmt,var1,var2) do { \ char gstr[OPT_ERRMAXSTRLEN]; sprintf(gstr,fmt,var1,var2); \ opt_warning(gstr); } while(0) A diff with the new version shows the implementation of snprintf as a valid fix. < char gstr[OPT_ERRMAXSTRLEN]; sprintf(gstr,fmt,var1,var2,var3); \ --- > char gstr[OPT_ERRMAXSTRLEN]; \ > opt_snprintf_3(gstr,OPT_ERRMAXSTRLEN,fmt,var1,var2,var3); \ A quick test compile against the new version of libopt.a appears to take care of the problem. [dotslash@vegeta test]$ pwd /home/dotslash/opt/opt-3.19/test [dotslash@vegeta test]$ cc -o test test.c ../src/libopt.a [dotslash@vegeta test]$ ltrace ./test A `perl -e 'print "A" x 1986'` ... snprintf("String [AAAAAAAAAAAAAAAAAAAAAAAA"..., 1024, "String [%s] is not a valid integ"... Patch or Workaround : Relink applications that use libopt.a against the new version of opt at http://nis-www.lanl.gov/~jt/Software/opt/opt-3.19.tar.gz Vendor Status : Author has responded and applied a fix to the problem. Bugtraq URL : to be assigned ------------------------------------------------------------------------ This advisory was released by Secure Network Operations,Inc. as a matter of notification to help administrators protect their networks against the described vulnerability. Exploit source code is no longer released in our advisories. Contact research@secnetops.com for information on how to obtain exploit information.