SRT2003-04-24-1532 - Options Parsing Tool library buffer overflows.

From: KF (
Date: 04/24/03

  • Next message: Gary Flynn: "Re: Cracking preshared keys"
    Date: Thu, 24 Apr 2003 16:45:38 -0500
    From: KF <>


    Secure Network Operations, Inc.
    Strategic Reconnaissance Team
    Team Lead Contact

    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 :
    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.

    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
    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.

    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
    [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
    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 for information on how
    to obtain exploit information.

  • Next message: Gary Flynn: "Re: Cracking preshared keys"

    Relevant Pages