PDA

Bekijk Volledige Versie : FreeBSD kernel buffer overflow



gerarra@tin.it
17/09/04, 22:05
Topic: Buffer Overflow in FreeBSD
Versions: All the versions of FreeBSD are broken (4.x, 5.x, 6.0)
Arch: x86
Date: 16/09/2004

All discussion refers to CURRENT-6.0, for other versions some things coul=
d
change (btw bugged).
Discussion involves a lot of arch x32 dependant mechanisms, so, in some
points, could sound a little bit dark.


A buffer overflow has been found in i386/i386/trap.c syscall() function
of FreeBSD official
source tree.
In order to rule syscalls mechanism, the 'particular' interrupt 128 (0x80=
)
is provided in the
IDT vector. To serve this interrupt, i386/i386/exception.s int0x80_syscal=
l()
function is
done and, in the end, it calls syscall().
syscall() is responsible for loading arguments from a syscall and copying=

them in a kspace
pointer in order to accessing them. The code to do that is the following:=


void
syscall(frame)
struct trapframe frame;
{
caddr_t params;
struct sysent *callp;
struct thread *td =3D curthread;
struct proc *p =3D td->td_proc;
register_t orig_tf_eflags;
u_int sticks;
int error;
int narg;
int args[8];
u_int code;


...


narg =3D callp->sy_narg & SYF_ARGMASK; (<- you can see it's the only on=
e
check)

if (params !=3D NULL && narg !=3D 0)
error =3D copyin(params, (caddr_t)args,
(u_int)(narg * sizeof(int)));
else
error =3D 0;


...


and:

> grep SYF_ARGMASK /usr/src/sys/sys/sysent.h
#define SYF_ARGMASK 0x0000FFFF

It's obvious that the amount of selectable memory is beyond the (8 * size=
of(int))
limit of
args array, so it would overwrite the saved eip by syscall() (it's invoke=
d
through a call) or
making an interesting pointer corruption overwriting struct proc *p .

It's exploitable, but the only one way I discovered is to link a new sysc=
all
to the sysent
array and to do this you need to be root; I've no time to work on this vu=
lnerability,
but i think another way could be found. However it could give serious pro=
blems
(e.g. kernel
crashes).

A good patch could be a dinamyc memory allocation for args, but it's not
a good solution
in order to mantain a well performanced system; another one could be a st=
rongest
check, but
it's not a good solution in order to set a good flexibility.

You would get an attach containing proof of concept code (4.x, 5.x/6.0 ve=
rsions).


greetings

rookie


P.S: in order to try the code, compile and link module to the kernel, lat=
er
do 'make test' and start ./poc

Wesley Shields
18/09/04, 18:35
On Thu, Sep 16, 2004 at 11:48:21PM +0200, gerarra@tin.it wrote:

> Topic: Buffer Overflow in FreeBSD
> Versions: All the versions of FreeBSD are broken (4.x, 5.x, 6.0)
> Arch: x86
> Date: 16/09/2004

[snip]

Before this goes any further please read the thread[1] on hackers@ about
this. It's not a security problem as you need root access to "exploit"
it anyways.

-- WXS

[1]
http://lists.freebsd.org/pipermail/freebsd-hackers/2004-September/008280.html

Tim Newsham
18/09/04, 19:05
This is a non-issue.

On Thu, 16 Sep 2004 gerarra@tin.it wrote:
> narg = callp->sy_narg & SYF_ARGMASK; (<- you can see it's the only one
> check)

At this point, callp points to the sysent entry for a particular
system call that is to be called. These entries are not under
the control of the attacker (unless, as you point out, you
are root and you add a new system call to the system).

If there's an entry in the system call table with a sy_narg
field greater than 8, then yes, there will be a buffer overflow.
However, the programmers who wrote the kernel don't provide
you with any such system calls.

> It's exploitable, but the only one way I discovered is to link a new syscall
> to the sysent
> array and to do this you need to be root; I've no time to work on this vulnerability,
> but i think another way could be found. However it could give serious problems
> (e.g. kernel
> crashes).

> rookie

Tim N.