Use |mprotect()| to secure key data ? / was: Re: Proposal: always handle keys in separate process
Roland Mainz
roland.mainz at nrubsig.org
Tue Jan 19 09:00:58 AEDT 2016
On Thu, Jan 14, 2016 at 8:12 PM, Alexander Wuerstlein <arw at cs.fau.de> wrote:
> Hello,
>
> in light of the recent CVE-2016-0777, I came up with the following idea,
> that would have lessened its impact. Feel free to ignore or flame me,
> maybe its stupid or I missed something :)
>
> - private key material should only ever be handled in a separate process
> from the SSH client. ssh-agent (maybe slightly extended) seems the
> logical choice.
[snip]
While this *might* be a bit of an overkill (think about embedded
systems where the extra >= 500kb for a separate process actually hurt)
... what about using the existing facilities like |mprotect()| to
secure the key data, e.g. like this:
-- snip --
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#define MYMSG(str) { puts((str)) ; fflush(stdout); fflush(stderr); }
#define SECRET_BUFF_SIZE (8192) /* should be page size */
char *secret_buff = NULL;
void write_buff(const char *in_str)
{
mprotect(secret_buff, SECRET_BUFF_SIZE, PROT_WRITE);
strncpy(secret_buff, in_str, SECRET_BUFF_SIZE);
mprotect(secret_buff, SECRET_BUFF_SIZE, PROT_NONE);
}
void read_buff(void)
{
mprotect(secret_buff, SECRET_BUFF_SIZE, PROT_READ);
printf("|%s|\n", secret_buff);
mprotect(secret_buff, SECRET_BUFF_SIZE, PROT_NONE);
}
void thief_read_buff(void)
{
printf("|%s|\n", secret_buff);
}
int main(int ac, char *av[])
{
secret_buff = mmap(NULL, SECRET_BUFF_SIZE*2, PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0);
if ((secret_buff == (void *)-1) || (secret_buff == NULL))
{
perror("mmap() failed");
return EXIT_FAILURE;
}
MYMSG("# writing something into the secret buffer");
write_buff("hello, this string is secret: vem_iam_1983");
MYMSG("# authorised secret buffer reader...");
read_buff();
MYMSG("# ALERT ALERT thieves are trying to use the buffer...");
thief_read_buff();
return EXIT_SUCCESS;
}
-- snip --
This example goes nicely "boom" with a SIGSEGV in function
|thief_read_buff()| when it tries to access the data in |secret| which
have neither |PROT_READ| nor |PROT_WRITE| at that point:
-- snip --
$ gdb ./a.out
[snip]
Reading symbols from /home/test001/tmp/a.out...done.
(gdb) run
Starting program: /home/test001/tmp/a.out
# writing something into the secret buffer
# authorised secret buffer reader...
|hello, this string is secret: vem_iam_1983|
# ALERT ALERT thieves are trying to use the buffer...
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7ac3e44 in _IO_vfprintf_internal (s=<value optimized out>,
format=<value optimized out>, ap=<value optimized out>) at
vfprintf.c:1593
1593 vfprintf.c: No such file or directory.
in vfprintf.c
(gdb) where
#0 0x00007ffff7ac3e44 in _IO_vfprintf_internal (s=<value optimized
out>, format=<value optimized out>, ap=<value optimized out>) at
vfprintf.c:1593
#1 0x00007ffff7acb34a in __printf (format=<value optimized out>) at printf.c:35
#2 0x0000000000400853 in thief_read_buff () at secretbuffer.c:27
#3 0x000000000040093d in main (ac=1, av=0x7fffffffde08) at secretbuffer.c:46
-- snip --
Granted this way is not elegant but it prevents unintended data
leakage with a minimum of resource overhead (erm... yes, we still
fiddle at MMU level which is expensive from an OS point of view but
it's still a few hundred times more lightwheight than having a
separate process around).
The other idea from the <sys/mman.h> area would be to store secret
data in unlinked temporary files, e.g. we only keep the fd's around
and |mmap()| and |munmap()| them on demand to store/read data in
dedicated functions.
Note that this only works for memory (file mapped or |MAP_ANON|)
obtained via |mmap()|, so using the stack or global vars is not
recommended (POSIX and SUS do not allow it but some OSes support it
anyway...).
----
Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
More information about the openssh-unix-dev
mailing list