2010-11-12 13:38:48

by Dan Rosenberg

[permalink] [raw]
Subject: [CRYPTO] obfuscating kernel pointers

Hi Crypto people,

I'm planning on submitting a patch that introduces a new %p format
specifier that obfuscates kernel pointers depending on privileges. This
change is for security reasons - many networking protocols expose
pointers to socket structures in their /proc interfaces, which are
attractive targets when exploiting other issues.

It's been suggested that I initialize a secret value at boot, and use
that as the key to a crypto hash function. I should use a function that
is relatively fast (ideally), produces a unique output based on its
input of a pointer, and produces consistent output when given the same
input. It should be difficult to infer the input given only the output.

I have two questions:

1. What is a proper, safe way of initializing a random value at boot?
Are there any existing examples that do this?

2. Can you recommend a crypto algorithm that would be well suited for
this pointer obfuscation?

Thanks,
Dan


2010-11-12 17:30:23

by Neil Horman

[permalink] [raw]
Subject: Re: [CRYPTO] obfuscating kernel pointers

On Fri, Nov 12, 2010 at 08:32:01AM -0500, Dan Rosenberg wrote:
> Hi Crypto people,
>
> I'm planning on submitting a patch that introduces a new %p format
> specifier that obfuscates kernel pointers depending on privileges. This
> change is for security reasons - many networking protocols expose
> pointers to socket structures in their /proc interfaces, which are
> attractive targets when exploiting other issues.
>
> It's been suggested that I initialize a secret value at boot, and use
> that as the key to a crypto hash function. I should use a function that
> is relatively fast (ideally), produces a unique output based on its
> input of a pointer, and produces consistent output when given the same
> input. It should be difficult to infer the input given only the output.
>
> I have two questions:
>
> 1. What is a proper, safe way of initializing a random value at boot?
> Are there any existing examples that do this?
>
Just use get_random_bytes, or initalize an instance of cprng with
get_random_bytes.

> 2. Can you recommend a crypto algorithm that would be well suited for
> this pointer obfuscation?
>

Depends on your goal, if you just wnat to hide the pointers, why not just print
NULL instead of the value? If you want to maintain some level of uniqueness,
just pull sizeof (void *) random bytes from whatever method above and add it to
the pointer in question, and hope for the best.

Honestly, though, I'm having trouble seeing the value of this. What interface in proc
are you seeing that exposes pointers from kernel space in any meaningful way?
and if those cases exist, isn't selinux the solution to preventing exposure of
these values to processes without sufficient privlidges?
Neil

> Thanks,
> Dan
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>

2010-11-12 17:39:44

by Dan Rosenberg

[permalink] [raw]
Subject: Re: [CRYPTO] obfuscating kernel pointers

Thanks for your response.

> >
> Just use get_random_bytes, or initalize an instance of cprng with
> get_random_bytes.
>

Will do.

>
> Depends on your goal, if you just wnat to hide the pointers, why not just print
> NULL instead of the value? If you want to maintain some level of uniqueness,
> just pull sizeof (void *) random bytes from whatever method above and add it to
> the pointer in question, and hope for the best.
>

Unfortunately, neither of these sound like an option. It's been
requested from the networking folks that any replacement value for the
socket addresses be a consistent unique identifier for object tracking
purposes. The current plan is to expose the real address to privileged
readers, and expose a consistent obfuscated address that's only useful
for tracking to unprivileged readers.

> Honestly, though, I'm having trouble seeing the value of this. What interface in proc
> are you seeing that exposes pointers from kernel space in any meaningful way?
> and if those cases exist, isn't selinux the solution to preventing exposure of
> these values to processes without sufficient privlidges?
> Neil
>

Lots of packet families expose them...see, for
example, /proc/net/{tcp,udp,raw,unix}. Since socket structures have
function pointers, they are an appealing target in the event of a kernel
memory write vulnerability. The goal here is to make exploitation of
such issues more difficult, including for distros that don't use
SELinux.

Thanks,
Dan

2010-11-12 18:56:57

by Neil Horman

[permalink] [raw]
Subject: Re: [CRYPTO] obfuscating kernel pointers

On Fri, Nov 12, 2010 at 12:39:41PM -0500, Dan Rosenberg wrote:
> Thanks for your response.
>
> > >
> > Just use get_random_bytes, or initalize an instance of cprng with
> > get_random_bytes.
> >
>
> Will do.
>
> >
> > Depends on your goal, if you just wnat to hide the pointers, why not just print
> > NULL instead of the value? If you want to maintain some level of uniqueness,
> > just pull sizeof (void *) random bytes from whatever method above and add it to
> > the pointer in question, and hope for the best.
> >
>
> Unfortunately, neither of these sound like an option. It's been
> requested from the networking folks that any replacement value for the
> socket addresses be a consistent unique identifier for object tracking
> purposes. The current plan is to expose the real address to privileged
> readers, and expose a consistent obfuscated address that's only useful
> for tracking to unprivileged readers.
>
adding a consistent random value to a your void * pointers sounds like a fine
solution to the problem, then. As long as you use the same random value for the
lifetime of the system, that will give you consistent values. And you have to
use the same random input consistently to have consistent output on multiple
concatinations of the same file anyway. This also has the advantage of not
having to do a crypto operation for every print/seq_sprintf/etc that contains a
%p.


> > Honestly, though, I'm having trouble seeing the value of this. What interface in proc
> > are you seeing that exposes pointers from kernel space in any meaningful way?
> > and if those cases exist, isn't selinux the solution to preventing exposure of
> > these values to processes without sufficient privlidges?
> > Neil
> >
>
> Lots of packet families expose them...see, for
> example, /proc/net/{tcp,udp,raw,unix}. Since socket structures have
> function pointers, they are an appealing target in the event of a kernel
> memory write vulnerability. The goal here is to make exploitation of
> such issues more difficult, including for distros that don't use
> SELinux.
>
huh, I guess they do spit out pointer values. At any rate, I'm still having a
hard time seeing the value here. If a distro doesn't enforce a security policy
sufficient to protect against information leaks from exposed files, I don't see
why the kernel should do that work for it. But regardless, I suppose thats a
debate to hav when you post a patch :)

> Thanks,
> Dan
>
>

2010-11-12 19:03:20

by Dan Rosenberg

[permalink] [raw]
Subject: Re: [CRYPTO] obfuscating kernel pointers


> >
> adding a consistent random value to a your void * pointers sounds like a fine
> solution to the problem, then. As long as you use the same random value for the
> lifetime of the system, that will give you consistent values. And you have to
> use the same random input consistently to have consistent output on multiple
> concatinations of the same file anyway. This also has the advantage of not
> having to do a crypto operation for every print/seq_sprintf/etc that contains a
> %p.
>

The problem with that is the ease with which one could infer that random
value makes the whole thing pretty pointless.

-Dan

2010-11-15 08:43:15

by Tomas Mraz

[permalink] [raw]
Subject: Re: [CRYPTO] obfuscating kernel pointers

On Fri, 2010-11-12 at 08:32 -0500, Dan Rosenberg wrote:
> Hi Crypto people,
>
> I'm planning on submitting a patch that introduces a new %p format
> specifier that obfuscates kernel pointers depending on privileges. This
> change is for security reasons - many networking protocols expose
> pointers to socket structures in their /proc interfaces, which are
> attractive targets when exploiting other issues.
>
> It's been suggested that I initialize a secret value at boot, and use
> that as the key to a crypto hash function. I should use a function that
> is relatively fast (ideally), produces a unique output based on its
> input of a pointer, and produces consistent output when given the same
> input. It should be difficult to infer the input given only the output.
>
> I have two questions:
>
> 1. What is a proper, safe way of initializing a random value at boot?
> Are there any existing examples that do this?
>
> 2. Can you recommend a crypto algorithm that would be well suited for
> this pointer obfuscation?
This would not be a 'hashing' algorithm but a simple block encryption
algorithm in the ECB mode with the random key initialized at boot. The
problem here is that the standard block ciphers have at least 64 bit
block length as smaller block length ciphers would not be secure for
general purpose uses. You would have to take an existing block cipher
algorithm and modify it to achieve the smaller block length.

--
Tomas Mraz
No matter how far down the wrong road you've gone, turn back.
Turkish proverb

2010-11-15 11:24:33

by Neil Horman

[permalink] [raw]
Subject: Re: [CRYPTO] obfuscating kernel pointers

On Mon, Nov 15, 2010 at 09:43:12AM +0100, Tomas Mraz wrote:
> On Fri, 2010-11-12 at 08:32 -0500, Dan Rosenberg wrote:
> > Hi Crypto people,
> >
> > I'm planning on submitting a patch that introduces a new %p format
> > specifier that obfuscates kernel pointers depending on privileges. This
> > change is for security reasons - many networking protocols expose
> > pointers to socket structures in their /proc interfaces, which are
> > attractive targets when exploiting other issues.
> >
> > It's been suggested that I initialize a secret value at boot, and use
> > that as the key to a crypto hash function. I should use a function that
> > is relatively fast (ideally), produces a unique output based on its
> > input of a pointer, and produces consistent output when given the same
> > input. It should be difficult to infer the input given only the output.
> >
> > I have two questions:
> >
> > 1. What is a proper, safe way of initializing a random value at boot?
> > Are there any existing examples that do this?
> >
> > 2. Can you recommend a crypto algorithm that would be well suited for
> > this pointer obfuscation?
> This would not be a 'hashing' algorithm but a simple block encryption
> algorithm in the ECB mode with the random key initialized at boot. The
> problem here is that the standard block ciphers have at least 64 bit
> block length as smaller block length ciphers would not be secure for
> general purpose uses. You would have to take an existing block cipher
> algorithm and modify it to achieve the smaller block length.
>
> --
> Tomas Mraz
> No matter how far down the wrong road you've gone, turn back.
> Turkish proverb
>
Something else occurs to me. If this is to be implemented as an internal
modification to the %p format token, you're going to have to be careful as to
when you're able to use it. Crypto algorithms can be built as individual
modules, and the api has them auto-load on demand when instances of them are
requested. How are you going to be certain that the hash that you choose is
available? For that matter, how are you going to know when its safe to ask for
the algorithm? If you do a printk(...%p\n") early during the boot, you'll be
calling request_moule->...->call_usermodehelper_exec before the workqueue or any
of its datastructures are initalized, and that will oops you.

Neil

> --
> To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>

2010-11-15 11:58:48

by Herbert Xu

[permalink] [raw]
Subject: Re: [CRYPTO] obfuscating kernel pointers

Tomas Mraz <[email protected]> wrote:
>
> This would not be a 'hashing' algorithm but a simple block encryption
> algorithm in the ECB mode with the random key initialized at boot. The
> problem here is that the standard block ciphers have at least 64 bit
> block length as smaller block length ciphers would not be secure for
> general purpose uses. You would have to take an existing block cipher
> algorithm and modify it to achieve the smaller block length.

If block sizes are a problem then we have stream ciphers too.

Cheers,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2010-11-15 12:06:41

by Tomas Mraz

[permalink] [raw]
Subject: Re: [CRYPTO] obfuscating kernel pointers

On Mon, 2010-11-15 at 19:58 +0800, Herbert Xu wrote:
> Tomas Mraz <[email protected]> wrote:
> >
> > This would not be a 'hashing' algorithm but a simple block encryption
> > algorithm in the ECB mode with the random key initialized at boot. The
> > problem here is that the standard block ciphers have at least 64 bit
> > block length as smaller block length ciphers would not be secure for
> > general purpose uses. You would have to take an existing block cipher
> > algorithm and modify it to achieve the smaller block length.
>
> If block sizes are a problem then we have stream ciphers too.
But you obviously cannot use a stream cipher as ECB cipher which is what
Dan needs here.
--
Tomas Mraz
No matter how far down the wrong road you've gone, turn back.
Turkish proverb