[Full-Disclosure] cdp buffer overflow vulnerability

From: Shaun Colley (shaunige_at_yahoo.co.uk)
Date: 03/31/04

  • Next message: Luigi Auriemma: "RogerWilco: new funny bugs"
    To: full-disclosure@lists.netsys.com
    Date: Wed, 31 Mar 2004 18:02:55 +0100 (BST)
    
    

    ~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

    Product: cdp - console cd player
    Versions: All
    Bug: Buffer overflow
    Impact: Attackers can execute arbitrary code
    Risk: Medium/High
    Date: March 31, 2004
    Author: Shaun Colley
                  Email: shaunige yahoo co uk
                  WWW: http://www.nettwerked.co.uk

    ~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*

    Introduction
    #############

    cdp is... "cdp is a program that plays CDs at the
    linux console. It has a full-screen ncurses mode, and
    a command-line mode suitable for scripts that wish to
    play audio CDs. I consider cdp to be the CD equivalent
    of mpg123." - Taken from project page:
    <http://cdp.sourceforge.net/>.

    Despite cdp's usual robustness (and all credit to the
    authors), cdp is vulnerable to a stack-based buffer
    overflow vulnerability which may allow a potential
    attacker to craft a malicious audio CD, social
    engineer a user into playing the CD with 'cdp',
    triggering a buffer overflow.

    Details
    ########

    The buffer overflow occurs in the routine which
    displays the information for each track, printTOC().
    This function prints the track number, track name, and
    track time information to the screen when a user plays
    a CD with cdp. Due to lack of bounds checking when
    preparing and printing this information, a track with
    a songname which exceeds 200 bytes in length will
    trigger a buffer overflow. Below is the offending
    code:

    --- from cdp.c ---
    [...]

    char buffer[ 200 ], ch;

    [...]

    printf( "Track Num Start Time Length Name \n" );
        for ( ind = 0; ind < cdStatus.thiscd.ntracks;
    ind++ ) {
            trk = &cdStatus.thiscd.trk[ ind ];
            if ( trk->songname != NULL ) {
                sprintf( buffer, "%s", trk->songname );
            } else
                buffer[ 0 ] = 0;

    [...]
    --- end of snippet ---

    As can be seen above, an sprintf call is made, copying
    trk->songname, if a songname exists, into a buffer
    which is only 200 bytes long. cdp gets the songname
    (name of the track) when a call to load() is made,
    which calls search_db() during it's execution flow.
    In this function, a songname possibly as long as 502
    bytes is copied into a cdinfo type struct pointer
    (safely), which is later used by printTOC() (the
    vulnerable function) to be copied into 'buffer', which
    has only 200 bytes allocated, as seen and explained
    above, thus presenting the possibility of a
    stack-based buffer overflow, as 'buffer' can often be
    overflowed by up to 302 bytes.

    An attacker could create a specially crafted audio CD,
    and give it to a user, presenting an opportunity for
    exploitation of the issue, as very few people check
    the authenticity of audio CDs given to them.

    Exploitation
    #############

    Exploitation of this issue would require that an
    attacker create a CD which has a track name (songname)
    exceeding 200 bytes, specially crafted to overwrite
    the instruction pointer (EIP) to redirect the
    execution flow elsewhere, causing execution of
    arbitrary code. Once a working exploit audio CD had
    been created, an attacker needs to simply pass the CD
    to a privileged user, and social engineer them into
    believing that the CD contains good music.

    I have not developed a proof-of-concept for this
    issue, but arbitrary code execution is most definately
    possible.

    Solution
    #########

    I contacted the author around 5 days ago, but I
    haven't heard any response. This could be because the
    cdp project isn't maintained much anymore. The latest
    release was in January 2000.

    I have produced a patch to fix the issue, since the
    vendor hasn't contacted me back. The patch implements
    an snprintf() call rather than an sprintf()
    invokation, which fixes the vulnerability because
    bounds checks are performed.

    --- songname.patch ---

    --- cdp.c 2004-03-31 15:48:55.000000000 +0100
    +++ cdp.1.c 2004-03-31 15:44:35.000000000 +0100
    @@ -154,7 +154,7 @@
         for ( ind = 0; ind < cdStatus.thiscd.ntracks;
    ind++ ) {
             trk = &cdStatus.thiscd.trk[ ind ];
             if ( trk->songname != NULL ) {
    - sprintf( buffer, "%s", trk->songname );
    + snprintf( buffer, strlen(buffer), "%s",
    trk->songname );
             } else
                 buffer[ 0 ] = 0;

    --- eof ---

    The patch can also be obtained from
    <http://www.nettwerked.co.uk/code/songname.patch>.

    The following steps can be taken to fix the problem:

    1) Create a file containing the above patch
    2) Apply the patch

    bash# patch cdp.c songname.patch

    3) Rebuild 'cdp'

    bash# make && make install

    The issue should now be fixed.

    No proper workarounds exist, except for running an
    application which guards against stack-based
    overflows, such as StackGuard.

    Credit
    #######

    This issue was discovered and researched by Shaun
    Colley - <shaunige yahoo co uk>.

    Thank you for your time.
    Shaun.

            
            
                    
    ___________________________________________________________
    WIN FREE WORLDWIDE FLIGHTS - nominate a cafe in the Yahoo! Mail Internet Cafe Awards www.yahoo.co.uk/internetcafes

    _______________________________________________
    Full-Disclosure - We believe in it.
    Charter: http://lists.netsys.com/full-disclosure-charter.html


  • Next message: Luigi Auriemma: "RogerWilco: new funny bugs"