Index | Thread | Search

From:
"Theo de Raadt" <deraadt@openbsd.org>
Subject:
Re: System calls cookie, a security mitigation idea
To:
Keisuke Hiei <keisukehiei@mail.com>
Cc:
tech@openbsd.org
Date:
Wed, 29 Oct 2025 09:55:31 -0600

Download raw body.

Thread
Keisuke Hiei <keisukehiei@mail.com> wrote:

> Motivation of implementing another system call use protection when
> pledge is already implemented?
> Because pledge does not protect apps that require the use of dangerous
> system calls like execve. An example app of this kind is openssh.

Please be more precise.  Do you mean ssh, or ssh-agent, or sshd? I suspect
you mean sshd.

> An attacker can also call execve and pledge will allow it.

How does the attacker call it?

You claim ret2libc.

You mention pledge, but there are multiple other mitigations you are not
listed. The sshd binary is ASLR mapped.  The base executable is mapped
somewhere, and libc.so is mapped somewhere else.  Offsets between these
may possibly be found as detritus on the stack, but this depends precisely
on toolchain effects, the moment of the bug, and requires reading stack in
a particular running process.  fork+execve privesep is also involved, so
you cannot learn everything you need from one probing attempt, and then replay
those calculated fixed offsets in a different connection attempt.

If you are talking about sshd, it is relinked random at boot.

Your cookie is in crt0, so it is in the main program.  You use the cookie
it in libc. This means you are creating a GOT entry.  Do you understand
the consequences?  It is not pretty.

The next thing going on is that libc.so is randomized at boot, so if the
attacker already cannot login they cannot see the inside-libc aslr location
where the execve stub is.  They must find precisely that execve stub entry
point, because of pinsyscalls.  How do they find that location?  If they
find that location by already being on the system previously, and reading
libc.so, then they can also look at libc.so's to predict how the GOT entry
will reach the cookie, and generate stack code to load it.

Another major thing going on is that almost nothing in libc can be used,
because of retguard protection on every function means you can only return
into the stack of functions.  You cannot jump into the middle.  This means
the attacker must use *only* the execve stub, and there are no other code
blocks available to construct / calculate values on the fly, unless extremely
lucky finding polymorphic code blocks which again need to be find inside
random-relinked .so (main, libc, libcrypto, etc).

I think your draft proposal isn't very realistic, in particular with the GOT
problem being introduced due to the cookie being in crt0.