Hi,
Making /proc/kallsyms readable only for root makes it harder
for attackers to write generic kernel exploits by removing
one source of knowledge where things are in the kernel.
Signed-off-by: Marcus Meissner <[email protected]>
---
kernel/kallsyms.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 6f6d091..a8db257 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -546,7 +546,7 @@ static const struct file_operations kallsyms_operations = {
static int __init kallsyms_init(void)
{
- proc_create("kallsyms", 0444, NULL, &kallsyms_operations);
+ proc_create("kallsyms", 0400, NULL, &kallsyms_operations);
return 0;
}
device_initcall(kallsyms_init);
--
1.7.1
On 11/04/2010 11:09 AM, Marcus Meissner wrote:
> Making /proc/kallsyms readable only for root makes it harder
> for attackers to write generic kernel exploits by removing
> one source of knowledge where things are in the kernel.
>
> Signed-off-by: Marcus Meissner <[email protected]>
I can't recall needing /proc/kallsyms when I wasn't root, so unless
there's a compelling use case.
Acked-by: Tejun Heo <[email protected]>
Thanks.
--
tejun
* Marcus Meissner <[email protected]> wrote:
> Hi,
>
> Making /proc/kallsyms readable only for root makes it harder for attackers to
> write generic kernel exploits by removing one source of knowledge where things are
> in the kernel.
Cc:-ed Linus - i think he argued in favor of such a patch in the past.
I generally agree with such patches (i have written some myself), but there's a few
questions with this one, which make this limited change ineffective and which make
it harder to implement a fuller patch that makes it truly harder to figure out the
precise kernel build:
- The real security obstruction effect is very small from this measure alone: the
overwhelming majority of our users are running distro kernels, so the Symbol.map
file (and hence 99% of /proc/kallsyms content) is well-known - unless we also
restrict 'uname -r' from nonprivileged users-ace. Hiding that might make sense -
but the two should be in one patch really.
- ( It will break a few tools that can be run as a plain user out of box - perf
for example. "chmod a+r /proc/kallsyms" during bootup will work that around so
it's not the end of the world. )
- For self-built kernels it might make sense - but there's "chmod a-r
/proc/kallsyms" during bootup one can do already.
- There's the side-question of module symbols - those are dynamically allocated
hence arguably per system. But module symbols make up only 1% on a typical
booted up full distro box.
So what does a distribution like Suse expect from this change alone? Those have
public packages in rpms which can be downloaded by anyone, so it makes little sense
to hide it - unless _all_ version information is hidden.
So i'd like to see a _full_ version info sandboxing patch that thinks through all
the angles and restricts uname -r kernel version info as well, and makes dmesg
unaccessible to users - and closes a few other information holes as well that give
away the exact kernel version - _that_ together will make it hard to blindly attack
a very specific kernel version.
But without actually declaring and achieving that sandboxing goal this security
measure is just a feel-good thing really - and makes it harder to make more
difficult steps down the road, like closing 'uname -r' ...
I fully expect Linus to overrule me on this, but hey, i had to try it and lay out my
arguments :-)
Thanks,
Ingo
On Thu, Nov 04, 2010 at 12:46:48PM +0100, Ingo Molnar wrote:
>
> * Marcus Meissner <[email protected]> wrote:
>
> > Hi,
> >
> > Making /proc/kallsyms readable only for root makes it harder for attackers to
> > write generic kernel exploits by removing one source of knowledge where things are
> > in the kernel.
>
> Cc:-ed Linus - i think he argued in favor of such a patch in the past.
>
> I generally agree with such patches (i have written some myself), but there's a few
> questions with this one, which make this limited change ineffective and which make
> it harder to implement a fuller patch that makes it truly harder to figure out the
> precise kernel build:
>
> - The real security obstruction effect is very small from this measure alone: the
> overwhelming majority of our users are running distro kernels, so the Symbol.map
> file (and hence 99% of /proc/kallsyms content) is well-known - unless we also
> restrict 'uname -r' from nonprivileged users-ace. Hiding that might make sense -
> but the two should be in one patch really.
Of course. System.map and others also need to turn to mode 400.
> - ( It will break a few tools that can be run as a plain user out of box - perf
> for example. "chmod a+r /proc/kallsyms" during bootup will work that around so
> it's not the end of the world. )
I was wondering about how much tools there are... I was also thinking of oprofile too.
> - For self-built kernels it might make sense - but there's "chmod a-r
> /proc/kallsyms" during bootup one can do already.
>
> - There's the side-question of module symbols - those are dynamically allocated
> hence arguably per system. But module symbols make up only 1% on a typical
> booted up full distro box.
>
> So what does a distribution like Suse expect from this change alone? Those have
> public packages in rpms which can be downloaded by anyone, so it makes little sense
> to hide it - unless _all_ version information is hidden.
It is the first patch, mostly an acceptance test balloon.
There are several other files handing information out, but kallsyms has
it all very nice and ready.
(timer_list, /proc/*/stat*, sl?binfo )
> So i'd like to see a _full_ version info sandboxing patch that thinks through all
> the angles and restricts uname -r kernel version info as well, and makes dmesg
> unaccessible to users - and closes a few other information holes as well that give
> away the exact kernel version - _that_ together will make it hard to blindly attack
> a very specific kernel version.
I am personally thinking of a "small steps" philosophy, one step after the other.
> But without actually declaring and achieving that sandboxing goal this security
> measure is just a feel-good thing really - and makes it harder to make more
> difficult steps down the road, like closing 'uname -r' ...
>
> I fully expect Linus to overrule me on this, but hey, i had to try it and lay out my
> arguments :-)
The goal we (SUSE Security and the oss-security list) had in mind is:
- Do not leak kernel addresses from kernel space to user space to make
writing kernel exploits harder.
Even if attackers get to have lists of addresses in their exploits it will have made
the world a bit better.
Ciao, Marcus
* Marcus Meissner <[email protected]> wrote:
> On Thu, Nov 04, 2010 at 12:46:48PM +0100, Ingo Molnar wrote:
> >
> > * Marcus Meissner <[email protected]> wrote:
> >
> > > Hi,
> > >
> > > Making /proc/kallsyms readable only for root makes it harder for attackers to
> > > write generic kernel exploits by removing one source of knowledge where things are
> > > in the kernel.
> >
> > Cc:-ed Linus - i think he argued in favor of such a patch in the past.
> >
> > I generally agree with such patches (i have written some myself), but there's a few
> > questions with this one, which make this limited change ineffective and which make
> > it harder to implement a fuller patch that makes it truly harder to figure out the
> > precise kernel build:
> >
> > - The real security obstruction effect is very small from this measure alone: the
> > overwhelming majority of our users are running distro kernels, so the Symbol.map
> > file (and hence 99% of /proc/kallsyms content) is well-known - unless we also
> > restrict 'uname -r' from nonprivileged users-ace. Hiding that might make sense -
> > but the two should be in one patch really.
>
> Of course. System.map and others also need to turn to mode 400.
That is not what I meant, at all.
It's not the System.map _on the system_.
It's the SuSE or Fedora kernel rpm package with a System.map in it, which
package the attacker can download from a hundred mirrors on the internet,
based on 'uname -r' output.
You cannot obfuscate the System.map of a distro kernel without obfuscating all
identification info. (Note that even the pure size of the System.map might tell a
kernel rpm version from another ...)
Ingo
* Ingo Molnar <[email protected]> wrote:
> * Marcus Meissner <[email protected]> wrote:
>
> > On Thu, Nov 04, 2010 at 12:46:48PM +0100, Ingo Molnar wrote:
> > >
> > > * Marcus Meissner <[email protected]> wrote:
> > >
> > > > Hi,
> > > >
> > > > Making /proc/kallsyms readable only for root makes it harder for attackers to
> > > > write generic kernel exploits by removing one source of knowledge where things are
> > > > in the kernel.
> > >
> > > Cc:-ed Linus - i think he argued in favor of such a patch in the past.
> > >
> > > I generally agree with such patches (i have written some myself), but there's a few
> > > questions with this one, which make this limited change ineffective and which make
> > > it harder to implement a fuller patch that makes it truly harder to figure out the
> > > precise kernel build:
> > >
> > > - The real security obstruction effect is very small from this measure alone: the
> > > overwhelming majority of our users are running distro kernels, so the Symbol.map
> > > file (and hence 99% of /proc/kallsyms content) is well-known - unless we also
> > > restrict 'uname -r' from nonprivileged users-ace. Hiding that might make sense -
> > > but the two should be in one patch really.
> >
> > Of course. System.map and others also need to turn to mode 400.
>
> That is not what I meant, at all.
>
> It's not the System.map _on the system_.
>
> It's the SuSE or Fedora kernel rpm package with a System.map in it, which package
> the attacker can download from a hundred mirrors on the internet, based on 'uname
> -r' output.
For example, on a Fedora testbox i have this version info:
$ uname -r
2.6.35.6-48.fc14.x86_64
Any attacker can download that rpm from:
http://download.fedora.redhat.com/pub/fedora/linux/updates/14/x86_64/kernel-2.6.35.6-48.fc14.x86_64.rpm
And can extract the System.map from it, using rpm2cpio and cpio -i -d. That will
include all the symbol addresses - without the attacker having any access to the
System.map or /proc/kallsyms on this particular box.
I.e. on distro kernel installations (which comprise the _vast_ majority of our
userbase) your patch brings little security benefits.
What i suggested in later parts of my mail might provide more security: to sandbox
kernel version information from unprivileged user-space - if we decide that we want
to sandbox kernel version information ...
That is a big if, because it takes a considerable amount of work. Would be worth
trying it - but feel-good non-solutions that do not bring much improvement to the
majority of users IMHO hinder such efforts.
Thanks,
Ingo
On Thu, Nov 04, 2010 at 03:11:04PM +0100, Ingo Molnar wrote:
>
> * Ingo Molnar <[email protected]> wrote:
>
> > * Marcus Meissner <[email protected]> wrote:
> >
> > > On Thu, Nov 04, 2010 at 12:46:48PM +0100, Ingo Molnar wrote:
> > > >
> > > > * Marcus Meissner <[email protected]> wrote:
> > > >
> > > > > Hi,
> > > > >
> > > > > Making /proc/kallsyms readable only for root makes it harder for attackers to
> > > > > write generic kernel exploits by removing one source of knowledge where things are
> > > > > in the kernel.
> > > >
> > > > Cc:-ed Linus - i think he argued in favor of such a patch in the past.
> > > >
> > > > I generally agree with such patches (i have written some myself), but there's a few
> > > > questions with this one, which make this limited change ineffective and which make
> > > > it harder to implement a fuller patch that makes it truly harder to figure out the
> > > > precise kernel build:
> > > >
> > > > - The real security obstruction effect is very small from this measure alone: the
> > > > overwhelming majority of our users are running distro kernels, so the Symbol.map
> > > > file (and hence 99% of /proc/kallsyms content) is well-known - unless we also
> > > > restrict 'uname -r' from nonprivileged users-ace. Hiding that might make sense -
> > > > but the two should be in one patch really.
> > >
> > > Of course. System.map and others also need to turn to mode 400.
> >
> > That is not what I meant, at all.
> >
> > It's not the System.map _on the system_.
> >
> > It's the SuSE or Fedora kernel rpm package with a System.map in it, which package
> > the attacker can download from a hundred mirrors on the internet, based on 'uname
> > -r' output.
>
> For example, on a Fedora testbox i have this version info:
>
> $ uname -r
> 2.6.35.6-48.fc14.x86_64
>
> Any attacker can download that rpm from:
>
> http://download.fedora.redhat.com/pub/fedora/linux/updates/14/x86_64/kernel-2.6.35.6-48.fc14.x86_64.rpm
>
> And can extract the System.map from it, using rpm2cpio and cpio -i -d. That will
> include all the symbol addresses - without the attacker having any access to the
> System.map or /proc/kallsyms on this particular box.
>
> I.e. on distro kernel installations (which comprise the _vast_ majority of our
> userbase) your patch brings little security benefits.
>
> What i suggested in later parts of my mail might provide more security: to sandbox
> kernel version information from unprivileged user-space - if we decide that we want
> to sandbox kernel version information ...
>
> That is a big if, because it takes a considerable amount of work. Would be worth
> trying it - but feel-good non-solutions that do not bring much improvement to the
> majority of users IMHO hinder such efforts.
Hiding the OS version is really quite hard I think.
I mean the kernel could hide it from uname, but lsb_release,
/etc/redhat-release, /etc/SuSE-release etc still exist and then you
can still use the fixed address list table inside your exploit. But an
exploits needs to have such a list, making it harder to write.
If we avoid exploits being able to just do open("/boot/System.map") it would
make it a useful step harder for exploit writers.
(This will end up a arms race between us and the exploit toolkit writers of course,
but hopefully not a longer one than fixing all actual problems ;)
I also briefly thought about kernel ASLR, but my knowledge of the kernel
loading is too limited whether this is even possible or at all useful.
Ciao, Marcus
Hello,
On 11/04/2010 03:33 PM, Marcus Meissner wrote:
> I mean the kernel could hide it from uname, but lsb_release,
> /etc/redhat-release, /etc/SuSE-release etc still exist and then you
> can still use the fixed address list table inside your exploit. But an
> exploits needs to have such a list, making it harder to write.
I do believe that making things more difficult to exploit helps. Many
people seem to think it only gives false sense of security tho.
> I also briefly thought about kernel ASLR, but my knowledge of the kernel
> loading is too limited whether this is even possible or at all useful.
We already have relocatable kernel for kdump and IIRC it doesn't add
runtime overhead, so putting the kernel at random address shouldn't be
too difficult. Not sure how useful that would be tho.
Thanks.
--
tejun
On 11/04/2010 10:38 AM, Tejun Heo wrote:
> Hello,
>
> On 11/04/2010 03:33 PM, Marcus Meissner wrote:
>> I mean the kernel could hide it from uname, but lsb_release,
>> /etc/redhat-release, /etc/SuSE-release etc still exist and then you
>> can still use the fixed address list table inside your exploit. But an
>> exploits needs to have such a list, making it harder to write.
>
> I do believe that making things more difficult to exploit helps. Many
> people seem to think it only gives false sense of security tho.
>
>> I also briefly thought about kernel ASLR, but my knowledge of the kernel
>> loading is too limited whether this is even possible or at all useful.
>
> We already have relocatable kernel for kdump and IIRC it doesn't add
> runtime overhead, so putting the kernel at random address shouldn't be
> too difficult. Not sure how useful that would be tho.
>
It's very coarse-grained relocation, which is why it works.
-hpa
P.S. It's not just for kdump anymore.
Hello,
On 11/04/2010 03:43 PM, H. Peter Anvin wrote:
>> We already have relocatable kernel for kdump and IIRC it doesn't add
>> runtime overhead, so putting the kernel at random address shouldn't be
>> too difficult. Not sure how useful that would be tho.
>
> It's very coarse-grained relocation, which is why it works.
Yeah, I recall reading the fairly simple relocator somewhere in the
x86 tree. Would it be impossible/difficult to improve it?
> P.S. It's not just for kdump anymore.
Ah, didn't know that either.
Thanks.
--
tejun
* Marcus Meissner <[email protected]> wrote:
> > For example, on a Fedora testbox i have this version info:
> >
> > $ uname -r
> > 2.6.35.6-48.fc14.x86_64
> >
> > Any attacker can download that rpm from:
> >
> > http://download.fedora.redhat.com/pub/fedora/linux/updates/14/x86_64/kernel-2.6.35.6-48.fc14.x86_64.rpm
> >
> > And can extract the System.map from it, using rpm2cpio and cpio -i -d. That will
> > include all the symbol addresses - without the attacker having any access to the
> > System.map or /proc/kallsyms on this particular box.
> >
> > I.e. on distro kernel installations (which comprise the _vast_ majority of our
> > userbase) your patch brings little security benefits.
> >
> > What i suggested in later parts of my mail might provide more security: to
> > sandbox kernel version information from unprivileged user-space - if we decide
> > that we want to sandbox kernel version information ...
> >
> > That is a big if, because it takes a considerable amount of work. Would be worth
> > trying it - but feel-good non-solutions that do not bring much improvement to
> > the majority of users IMHO hinder such efforts.
>
> Hiding the OS version is really quite hard I think.
Yes. Hard but it would be useful - especially if we start adding things like known
exploit honeypots. Forcing attackers to probe the kernel by actually running a
kernel exploit, and risking an alarm would be a very powerful security feature.
Removing version info will upset some tools/libraries that rely on kernel version
information for quirks though.
> I mean the kernel could hide it from uname, but lsb_release, /etc/redhat-release,
> /etc/SuSE-release etc still exist and then you can still use the fixed address
> list table inside your exploit. But an exploits needs to have such a list, making
> it harder to write.
>
> If we avoid exploits being able to just do open("/boot/System.map") it would make
> it a useful step harder for exploit writers.
Dunno. It's a very low 'barrier'.
> (This will end up a arms race between us and the exploit toolkit writers of
> course, but hopefully not a longer one than fixing all actual problems ;)
That's not really an arms race. It's more like a 'throwing a feather in the path of
a tornado' kind of defense. Sure, it has some effect.
> I also briefly thought about kernel ASLR, but my knowledge of the kernel loading
> is too limited whether this is even possible or at all useful.
Now ASLR for kernel addresses would be _very_ useful. We could still 'expose' useful
debug and instrumentation info like /proc/kallsyms, but the kernel internal offset
would be a per bootup secret.
_That_ is a real statistical defensive security measure which would help everyone
and everywhere. Not hiding public info on that system and still leaving the link to
the public info (the version) available.
(Isn't such a feature available in one of the security patches? Porting that to
distros and moving it upstream would add some real defense.)
Thanks,
Ingo
On Thu, Nov 04, 2010 at 08:08:04PM +0100, Ingo Molnar wrote:
>
> * Marcus Meissner <[email protected]> wrote:
>
> > > For example, on a Fedora testbox i have this version info:
> > >
> > > $ uname -r
> > > 2.6.35.6-48.fc14.x86_64
> > >
> > > Any attacker can download that rpm from:
> > >
> > > http://download.fedora.redhat.com/pub/fedora/linux/updates/14/x86_64/kernel-2.6.35.6-48.fc14.x86_64.rpm
> > >
> > > And can extract the System.map from it, using rpm2cpio and cpio -i -d. That will
> > > include all the symbol addresses - without the attacker having any access to the
> > > System.map or /proc/kallsyms on this particular box.
> > >
> > > I.e. on distro kernel installations (which comprise the _vast_ majority of our
> > > userbase) your patch brings little security benefits.
> > >
> > > What i suggested in later parts of my mail might provide more security: to
> > > sandbox kernel version information from unprivileged user-space - if we decide
> > > that we want to sandbox kernel version information ...
> > >
> > > That is a big if, because it takes a considerable amount of work. Would be worth
> > > trying it - but feel-good non-solutions that do not bring much improvement to
> > > the majority of users IMHO hinder such efforts.
> >
> > Hiding the OS version is really quite hard I think.
>
> Yes. Hard but it would be useful - especially if we start adding things like known
> exploit honeypots. Forcing attackers to probe the kernel by actually running a
> kernel exploit, and risking an alarm would be a very powerful security feature.
>
> Removing version info will upset some tools/libraries that rely on kernel version
> information for quirks though.
Quite honnestly, it's the worst idea I've ever read to protect the kernel.
Kernel version is needed at many places, when building some code which relies
on presence of syscall X or Y depending on a version, etc... If our kernel is
so buggy that we can only rely on its version to be kept secret, then we have
already failed.
The kernel version should not be a secret, and anyway there are many ways to
guess it. And judging by past exploits, some of them work on a wide variety
of kernels so that's often pointless. It's just like when admins used to hide
their product names from HTTP response headers, this did not stop exploits at
all because there were always ways to guess the information.
Also, keep in mind that the most info you'll hide from unprivileged users,
the more you'll need root access for anything, which is a lot worse. On
systems that are secured that way, there are sudoers for everyone to do
anything (even ping). This becomes unmanageable and that opens even more
flaws in the whole system. We'll be proud of saying that those are not
kernel issues anymore but management issues but it's a bit easy to point
the finger at the poor guy who tries to keep his system usable despite
our efforts not to do so. And BTW, yes I *do* have access to such a system
where sudo is required for many things and some flaws already give me root
access.
When you secure an environment too much, users build a sub-environment inside
it with lower controls. It's common to see one user provide a complete tool
suite to other users because nothing was installed for fear of opening a hole.
But when you provide all the tools to everyone with you own account, it's just
as if you were root. So that's just pushing the problem somewhere else.
Focusing on ways to make the kernel more reliable when some information is
known is more efficient than trying to hide that information and relying on
this fact.
Willy
* Willy Tarreau <[email protected]> wrote:
> On Thu, Nov 04, 2010 at 08:08:04PM +0100, Ingo Molnar wrote:
> >
> > * Marcus Meissner <[email protected]> wrote:
> >
> > > > For example, on a Fedora testbox i have this version info:
> > > >
> > > > $ uname -r
> > > > 2.6.35.6-48.fc14.x86_64
> > > >
> > > > Any attacker can download that rpm from:
> > > >
> > > > http://download.fedora.redhat.com/pub/fedora/linux/updates/14/x86_64/kernel-2.6.35.6-48.fc14.x86_64.rpm
> > > >
> > > > And can extract the System.map from it, using rpm2cpio and cpio -i -d. That will
> > > > include all the symbol addresses - without the attacker having any access to the
> > > > System.map or /proc/kallsyms on this particular box.
> > > >
> > > > I.e. on distro kernel installations (which comprise the _vast_ majority of our
> > > > userbase) your patch brings little security benefits.
> > > >
> > > > What i suggested in later parts of my mail might provide more security: to
> > > > sandbox kernel version information from unprivileged user-space - if we decide
> > > > that we want to sandbox kernel version information ...
> > > >
> > > > That is a big if, because it takes a considerable amount of work. Would be worth
> > > > trying it - but feel-good non-solutions that do not bring much improvement to
> > > > the majority of users IMHO hinder such efforts.
> > >
> > > Hiding the OS version is really quite hard I think.
> >
> > Yes. Hard but it would be useful - especially if we start adding things like known
> > exploit honeypots. Forcing attackers to probe the kernel by actually running a
> > kernel exploit, and risking an alarm would be a very powerful security feature.
> >
> > Removing version info will upset some tools/libraries that rely on kernel
> > version information for quirks though.
>
> Quite honnestly, it's the worst idea I've ever read to protect the kernel. Kernel
> version is needed at many places, when building some code which relies on presence
> of syscall X or Y depending on a version, etc... [...]
Actually that's not true, since we have a kernel ABI, and since there's many
backports of newer kernel features into older kernels that it's generally not
needed nor meaningful to know the kernel version for syscalls.
Returning -ENOSYS is the general standard we use to communicate syscall
capabilities.
In fact using kernel version to switch around library functionality is a bug i'd
argue.
> [...] If our kernel is so buggy that we can only rely on its version to be kept
> secret, then we have already failed.
That mischaracterises my suggestion rather heavily - which makes me suspect that you
misunderstood it. Here's the relevant section of what i suggested here:
> > Hard but it would be useful - especially if we start adding things like known
> > exploit honeypots. Forcing attackers to probe the kernel by actually running a
> > kernel exploit, and risking an alarm would be a very powerful security feature.
An 'exploit honeypot' would be some small amount of 'detection' code for the
exploitable pattern of parameters (most attacks come via ioctls so we can add
detection for known holes without any performance hit), and the kernel would warn
the sysadmin that an exploit attempt has occured.
The point is to make it riskier to run exploits - not to 'hide version because we
are so buggy'. Unprivileged attackers wont be able to know whether a kernel is
unpatched and wont know whether trying an actual exploit triggers a silent alarm or
not.
I.e. i think the only true break-through in kernel security will be to add credible
and substantial 'strike back' functionality - to increase the risks of detection
(which necessiates the removal of the information whether a kernel is patched or
not).
As i said it's hard - but it would be a rather break-through security feature for
Linux. Not an 'arms race' thing where we just put obstruction in the road of
attackers - but some real, unavoidable risk not detectable by attackers - running on
most stock distro kernels. (so there would be a real economy of scale)
The kerneloops client could also collect exploit attempt stats.
Thanks,
Ingo
On Thu, Nov 04, 2010 at 10:51:57PM +0100, Ingo Molnar wrote:
> > Quite honnestly, it's the worst idea I've ever read to protect the kernel. Kernel
> > version is needed at many places, when building some code which relies on presence
> > of syscall X or Y depending on a version, etc... [...]
>
> Actually that's not true, since we have a kernel ABI, and since there's many
> backports of newer kernel features into older kernels that it's generally not
> needed nor meaningful to know the kernel version for syscalls.
>
> Returning -ENOSYS is the general standard we use to communicate syscall
> capabilities.
>
> In fact using kernel version to switch around library functionality is a bug i'd
> argue.
I'm sorry Ingo, but I still don't agree. We've had several versions of epoll,
several (some even buggy) versions of splice() which cannot even be detected
without checking the kernel release. And those are just two that immediately
come to my mind. If we've been providing a version for the last 19 years, it
surely had some valid uses.
> > [...] If our kernel is so buggy that we can only rely on its version to be kept
> > secret, then we have already failed.
>
> That mischaracterises my suggestion rather heavily - which makes me suspect that you
> misunderstood it. Here's the relevant section of what i suggested here:
>
> > > Hard but it would be useful - especially if we start adding things like known
> > > exploit honeypots. Forcing attackers to probe the kernel by actually running a
> > > kernel exploit, and risking an alarm would be a very powerful security feature.
I have read it, but this does not require hiding the kernel version. You can
still keep your honey pots if you want (provided that they don't slow down
normal syscall path) and log suspect attempts. But if you're hiding the version,
those tricks will be used by valid programs too.
> An 'exploit honeypot' would be some small amount of 'detection' code for the
> exploitable pattern of parameters (most attacks come via ioctls so we can add
> detection for known holes without any performance hit), and the kernel would warn
> the sysadmin that an exploit attempt has occured.
If we pollute the ioctl code with all the CVEs we have accumulated over the
years, I bet we'd get a performance hit and will probably introduce new bugs
due to the harder to maintain code.
> The point is to make it riskier to run exploits - not to 'hide version because we
> are so buggy'. Unprivileged attackers wont be able to know whether a kernel is
> unpatched and wont know whether trying an actual exploit triggers a silent alarm or
> not.
In my opinion, hiding the distro-specific part of the version should not cause
too much harm, but still I find this useless.
You see, I've used the vmsplice exploit at one place. Do you know how I did ?
$ cat /etc/redhat-release
Then I opened the box and installed the DVD showing the same version on a
spare PC to experiment with it. Once I got the exploit to reliably work without
crashing the kernel nor leaving traces, I dared launching it on the target
machine and it worked. Uname -r was not involved there. I simply relied on
the fact that updating a distro is a pain at many places and that it's very
rare to find an updated one because of that, so they remain with the shipped
kernel for months if not years, and sometimes even because some product
vendors say "my product supports Red Hat kernel 2.6.18-128xxx" so they don't
want to risk losing the support because they don't understand anything to
versioning.
So if we make fixes easier to install, we'd probably have less issues with
unfixed code than if we try to pretend they're not vulnerable by hiding the
version.
> I.e. i think the only true break-through in kernel security will be to add credible
> and substantial 'strike back' functionality - to increase the risks of detection
> (which necessiates the removal of the information whether a kernel is patched or
> not).
>
> As i said it's hard - but it would be a rather break-through security feature for
> Linux.
It requires hiding so many things for providing so little protection that I
really don't believe in it at all. Simply checking the system uptime the
last most date of /boot generally tells you precise info about the last
udpate.
> Not an 'arms race' thing where we just put obstruction in the road of
> attackers - but some real, unavoidable risk not detectable by attackers - running on
> most stock distro kernels. (so there would be a real economy of scale)
>
> The kerneloops client could also collect exploit attempt stats.
Well, in my opinion, either the attacker is remote and you can already get
many info, or he's local and has time to precisely qualify the environment
in order not to leave the slightest trace. The rule is simple : if you don't
trust your local users, remain up to date. One day lag once and you lose.
Regards,
Willy
On Thu, Nov 04, 2010 at 11:35:26PM +0100, Willy Tarreau wrote:
> > The point is to make it riskier to run exploits - not to 'hide version because we
> > are so buggy'. Unprivileged attackers wont be able to know whether a kernel is
> > unpatched and wont know whether trying an actual exploit triggers a silent alarm or
> > not.
>
> In my opinion, hiding the distro-specific part of the version should not cause
> too much harm, but still I find this useless.
BTW, if you want to hide the kernel version for the 99% distro kernels,
there's a very simple way to do that : just don't bump EXTRAVERSION nor
the build date in official builds. Keep it the same for all the product's
life, and provide the real name in a /proc entry that is only readable by
root by default. This will solve your issue with the exact kernel version
revealing pointers/bugs without hurting compatibility with user space
tools.
That will not hide the hints I was talking about though (uptime, dir mod
time, ...) but it will provide you with a version unrelated to the bug
level.
Regards,
Willy
On Thu, Nov 4, 2010 at 6:11 PM, Tejun Heo <[email protected]> wrote:
> On 11/04/2010 11:09 AM, Marcus Meissner wrote:
>> Making /proc/kallsyms readable only for root makes it harder
>> for attackers to write generic kernel exploits by removing
>> one source of knowledge where things are in the kernel.
>>
>> Signed-off-by: Marcus Meissner <[email protected]>
>
> I can't recall needing /proc/kallsyms when I wasn't root, so unless
> there's a compelling use case.
>
> Acked-by: Tejun Heo <[email protected]>
Looks good to me too.
Acked-by: Eugene Teo <[email protected]>
Eugene
On Thu, 4 Nov 2010, Marcus Meissner wrote:
>
> Hi,
>
> Making /proc/kallsyms readable only for root makes it harder
> for attackers to write generic kernel exploits by removing
> one source of knowledge where things are in the kernel.
>
> Signed-off-by: Marcus Meissner <[email protected]>
> ---
> kernel/kallsyms.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
> index 6f6d091..a8db257 100644
> --- a/kernel/kallsyms.c
> +++ b/kernel/kallsyms.c
> @@ -546,7 +546,7 @@ static const struct file_operations kallsyms_operations = {
>
> static int __init kallsyms_init(void)
> {
> - proc_create("kallsyms", 0444, NULL, &kallsyms_operations);
> + proc_create("kallsyms", 0400, NULL, &kallsyms_operations);
> return 0;
> }
> device_initcall(kallsyms_init);
>
This doesn't harden things much, but a little is better than nothing.
This makes sense to me and looks OK.
Reviewed-by: Jesper Juhl <[email protected]>
--
Jesper Juhl <[email protected]> http://www.chaosbits.net/
Plain text mails only, please http://www.expita.com/nomime.html
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
On 11/04/10 05:29, Marcus Meissner wrote:
> On Thu, Nov 04, 2010 at 12:46:48PM +0100, Ingo Molnar wrote:
>>
>> * Marcus Meissner <[email protected]> wrote:
>>
>>> Hi,
>>>
>>> Making /proc/kallsyms readable only for root makes it harder for attackers to
>>> write generic kernel exploits by removing one source of knowledge where things are
>>> in the kernel.
< snip >
>> So what does a distribution like Suse expect from this change alone? Those have
>> public packages in rpms which can be downloaded by anyone, so it makes little sense
>> to hide it - unless _all_ version information is hidden.
>
> It is the first patch, mostly an acceptance test balloon.
>
> There are several other files handing information out, but kallsyms has
> it all very nice and ready.
>
> (timer_list, /proc/*/stat*, sl?binfo )
>
>> So i'd like to see a _full_ version info sandboxing patch that thinks through all
>> the angles and restricts uname -r kernel version info as well, and makes dmesg
>> unaccessible to users - and closes a few other information holes as well that give
>> away the exact kernel version - _that_ together will make it hard to blindly attack
>> a very specific kernel version.
>
> I am personally thinking of a "small steps" philosophy, one step after the other.
< snip >
The idea of trying to hide the kernel version is absurd. The number of different
places that can provide a precise fingerprint of a kernel version, or a small range of
possible kernel versions is immense. Closing all of those places makes use and
administration of a system more difficult, and encourages frequent use of su.
Dumb examples of version clues (beyond the obvious simple ones):
$ gcc -v
Target: x86_64-redhat-linux
gcc version 4.4.4 20100630 (Red Hat 4.4.4-10) (GCC)
$ rpm -qi gcc
Release : 10.fc13 Build Date: Wed Jun 30 02:54:10 2010
$ rpm -qi kernel
Version : 2.6.33.3 Vendor: Fedora Project
Release : 85.fc13 Build Date: Thu May 6 11:35:36 2010
$ ls -l /lib64
$ ls -l /boot
$ lsmod
-Frank
* Willy Tarreau <[email protected]> wrote:
> On Thu, Nov 04, 2010 at 10:51:57PM +0100, Ingo Molnar wrote:
> > > Quite honnestly, it's the worst idea I've ever read to protect the kernel. Kernel
> > > version is needed at many places, when building some code which relies on presence
> > > of syscall X or Y depending on a version, etc... [...]
> >
> > Actually that's not true, since we have a kernel ABI, and since there's many
> > backports of newer kernel features into older kernels that it's generally not
> > needed nor meaningful to know the kernel version for syscalls.
> >
> > Returning -ENOSYS is the general standard we use to communicate syscall
> > capabilities.
> >
> > In fact using kernel version to switch around library functionality is a bug i'd
> > argue.
>
> I'm sorry Ingo, but I still don't agree. We've had several versions of epoll,
> several (some even buggy) versions of splice() which cannot even be detected
> without checking the kernel release. And those are just two that immediately come
> to my mind. If we've been providing a version for the last 19 years, it surely had
> some valid uses.
I'm sorry Willy, but you are mostly wrong - and there's no need to speculate here
really. Just try the patch below :-)
If your claim that 'kernel version is needed at many places' is true then why am i
seeing this on a pretty general distro box bootup:
[root@aldebaran ~]# uname -a
Linux aldebaran 2.6.99-tip-01574-g6ba54c9-dirty #1 SMP Sun Nov 7 10:24:38 CET 2010 x86_64 x86_64 x86_64 GNU/Linux
?
Yes, some user-space might be unhappy if we set the version _back_ to say 2.4.0, but
we could (as the patch below) fuzz up the version information from unprivileged
attackers easily.
_Future_ ABI breakages that necessiate a version check are clearly frowned upon, so
this patch could even be considered a debugging feature: it makes it harder to
create ABI incompatibilities (at least for unprivileged user-space).
So you can think of version fuzzing also as the ultimate ABI check.
( This is a real defensive measure - here's a reason why attackers try stealth
remote fingerprinting of a target system first: they really want to avoid
detection and knowing the exact OS and version of a target tells them which
attacks can be tried with a higher chance of success. Same goes for local attacks
as well.
And once we have _that_, version fuzzing, removing kallsyms is one of the many
measures we need to use to hide the true version of the kernel from unprivileged
user-space. )
Thanks,
Ingo
Index: linux/Makefile
===================================================================
--- linux.orig/Makefile
+++ linux/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
-SUBLEVEL = 37
-EXTRAVERSION = -rc1
+SUBLEVEL = 99
+EXTRAVERSION =
NAME = Flesh-Eating Bats with Fangs
# *DOCUMENTATION*
* Willy Tarreau <[email protected]> wrote:
> > Not an 'arms race' thing where we just put obstruction in the road of attackers
> > - but some real, unavoidable risk not detectable by attackers - running on most
> > stock distro kernels. (so there would be a real economy of scale)
> >
> > The kerneloops client could also collect exploit attempt stats.
>
> Well, in my opinion, either the attacker is remote and you can already get many
> info, or he's local and has time to precisely qualify the environment in order not
> to leave the slightest trace. [...]
Your view of how attackers operate is rather simplistic. Knowing the precise
environment (via remote or local measures) is a big tactical advantage to them.
See the very patch we are discussing. People are submitting patches to hide certain
pieces of information exactly because that information is an advantage to attackers.
And my point is that "if you want to hide information do it effectively - or if it's
too hard dont do it at all".
Thanks,
Ingo
* Willy Tarreau <[email protected]> wrote:
> > An 'exploit honeypot' would be some small amount of 'detection' code for the
> > exploitable pattern of parameters (most attacks come via ioctls so we can add
> > detection for known holes without any performance hit), and the kernel would
> > warn the sysadmin that an exploit attempt has occured.
>
> If we pollute the ioctl code with all the CVEs we have accumulated over the years,
> I bet we'd get a performance hit and will probably introduce new bugs due to the
> harder to maintain code.
That's just wrong, because it's usually not the same ioctl hit with dozens of CVEs,
but lots of CVEs are spread out amongst lots of ioctls. You need to come up with
something more concrete than "I bet" to support that claim ;-)
> > The point is to make it riskier to run exploits - not to 'hide version because
> > we are so buggy'. Unprivileged attackers wont be able to know whether a kernel
> > is unpatched and wont know whether trying an actual exploit triggers a silent
> > alarm or not.
>
> In my opinion, hiding the distro-specific part of the version should not cause too
> much harm, but still I find this useless.
>
>
> You see, I've used the vmsplice exploit at one place. Do you know how I did ? $
> cat /etc/redhat-release
>
> Then I opened the box and installed the DVD showing the same version on a spare PC
> to experiment with it. Once I got the exploit to reliably work without crashing
> the kernel nor leaving traces, I dared launching it on the target machine and it
> worked. Uname -r was not involved there. [...]
Sigh, you _still_ have not understood my point and you clearly dont seem to know how
honeypots work.
An 'exploit honeypot' kernel feature, on a patched kernel, would at that point warn
the admin that local user XXX tried to run an exploit.
The point is that the attacker cannot know whether it's safe to run the exploit on
the box (will result in a compromise), or is not safe to run the exploit (the
honeypot code will warn the admin).
Uname -r fuzzing is not needed because the attacker 'needs to run it' to compromise
a vulnerable system (as you seem to believe). It's done because if the attacker runs
it on a _not vulnerable machine_, it keeps him from running the exploit.
In short, it removes the 'is it safe to try this exploit' information from the
system - and if there's also a honeypot there, it introduces a real (and if done
well enough, undetectable) risk of detection for the attacker.
Thanks,
Ingo
* Ingo Molnar <[email protected]> wrote:
> If your claim that 'kernel version is needed at many places' is true then why am i
> seeing this on a pretty general distro box bootup:
>
> [root@aldebaran ~]# uname -a
> Linux aldebaran 2.6.99-tip-01574-g6ba54c9-dirty #1 SMP Sun Nov 7 10:24:38 CET 2010 x86_64 x86_64 x86_64 GNU/Linux
>
> ?
>
> Yes, some user-space might be unhappy if we set the version _back_ to say 2.4.0,
> but we could (as the patch below) fuzz up the version information from
> unprivileged attackers easily.
Btw., with an 'exploit honeypot' and 'version fuzzing' the uname output would look
like this to an unprivileged user:
$ uname -a
Linux aldebaran 2.6.99 x86_64 x86_64 x86_64 GNU/Linux
[ we wouldnt want to include the date or the SHA1 of the kernel, obviously. ]
And it would look like this to root:
# uname -a
Linux aldebaran 2.6.37-tip-01574-g6ba54c9-dirty #1 SMP Sun Nov 7 10:24:38 CET 2010 x86_64 x86_64 x86_64 GNU/Linux
Ingo
Hi Ingo,
On Sun, Nov 07, 2010 at 09:50:16AM +0100, Ingo Molnar wrote:
>
> * Willy Tarreau <[email protected]> wrote:
>
> > On Thu, Nov 04, 2010 at 10:51:57PM +0100, Ingo Molnar wrote:
> > > > Quite honnestly, it's the worst idea I've ever read to protect the kernel. Kernel
> > > > version is needed at many places, when building some code which relies on presence
> > > > of syscall X or Y depending on a version, etc... [...]
> > >
> > > Actually that's not true, since we have a kernel ABI, and since there's many
> > > backports of newer kernel features into older kernels that it's generally not
> > > needed nor meaningful to know the kernel version for syscalls.
> > >
> > > Returning -ENOSYS is the general standard we use to communicate syscall
> > > capabilities.
> > >
> > > In fact using kernel version to switch around library functionality is a bug i'd
> > > argue.
> >
> > I'm sorry Ingo, but I still don't agree. We've had several versions of epoll,
> > several (some even buggy) versions of splice() which cannot even be detected
> > without checking the kernel release. And those are just two that immediately come
> > to my mind. If we've been providing a version for the last 19 years, it surely had
> > some valid uses.
>
> I'm sorry Willy, but you are mostly wrong - and there's no need to speculate here
> really. Just try the patch below :-)
>
> If your claim that 'kernel version is needed at many places' is true then why am i
> seeing this on a pretty general distro box bootup:
>
> [root@aldebaran ~]# uname -a
> Linux aldebaran 2.6.99-tip-01574-g6ba54c9-dirty #1 SMP Sun Nov 7 10:24:38 CET 2010 x86_64 x86_64 x86_64 GNU/Linux
I don't understand the point you're trying to make with this patch. Obviously
we can pretend to be any version, and by doing that, you also pretend not to
have some bugs that would have been fixed later after the *real* version.
What I'm saying is that history has shown that we have known bugs that are
not detectable by any other way than the kernel version. Take the splice()
data corruption bug for instance. I believe it was fixed in 2.6.26 or 2.6.27
and backported late in the 2.6.25.X stable branch. Due to this, without
knowing the kernel version, the user can't know whether it's safe to use
splice() or not. I'm particularly aware of this one because I got quite a
bunch of questions from users on this subject. But certainly there are a
bunch of other ones.
> Yes, some user-space might be unhappy if we set the version _back_ to say 2.4.0, but
> we could (as the patch below) fuzz up the version information from unprivileged
> attackers easily.
I think you understood my concerns about breaking compatibility with userspace
by announcing a wrong version. That's not what I'm saying, but rather that
user-space couldn't rely on the version anymore to avoid known bugs.
> _Future_ ABI breakages that necessiate a version check are clearly frowned upon, so
> this patch could even be considered a debugging feature: it makes it harder to
> create ABI incompatibilities (at least for unprivileged user-space).
Stating this will not change the behaviour WRT bugs unfortunately.
> So you can think of version fuzzing also as the ultimate ABI check.
>
>
> ( This is a real defensive measure - here's a reason why attackers try stealth
> remote fingerprinting of a target system first: they really want to avoid
> detection and knowing the exact OS and version of a target tells them which
> attacks can be tried with a higher chance of success. Same goes for local attacks
> as well.
>
> And once we have _that_, version fuzzing, removing kallsyms is one of the many
> measures we need to use to hide the true version of the kernel from unprivileged
> user-space. )
I think you didn't understand me. I was explaining that doing this will not
prevent them from guessing the precise kernel version, because if you're on
a mainstream distro, just check the uptime. If last reboot matches the next
day of a kernel release, most likely it's this version. Same for /boot
modification date. And conversely, when you find an uptime of 800 days, you
know for sure that your freshly discovered bug is still present, no need of
uname for that. And I gave you examples of that which have worked.
That's why I'm claiming that version fuzzing brings nothing *really* useful.
It just makes admin think they're secure but that's false.
Also as I said, if you want your distro to hide the bug fix level, simply
rebuild the kernel with a fixed EXTRAVERSION string, or ask the kernel
maintainers there not to update the EXTRAVERSION anymore and you'll have
your version fuzzing for free without changing any kernel code. But I'm
still certain it will not bring any value.
Willy
* Willy Tarreau <[email protected]> wrote:
> Hi Ingo,
>
> On Sun, Nov 07, 2010 at 09:50:16AM +0100, Ingo Molnar wrote:
> >
> > * Willy Tarreau <[email protected]> wrote:
> >
> > > On Thu, Nov 04, 2010 at 10:51:57PM +0100, Ingo Molnar wrote:
> > > > > Quite honnestly, it's the worst idea I've ever read to protect the kernel. Kernel
> > > > > version is needed at many places, when building some code which relies on presence
> > > > > of syscall X or Y depending on a version, etc... [...]
> > > >
> > > > Actually that's not true, since we have a kernel ABI, and since there's many
> > > > backports of newer kernel features into older kernels that it's generally not
> > > > needed nor meaningful to know the kernel version for syscalls.
> > > >
> > > > Returning -ENOSYS is the general standard we use to communicate syscall
> > > > capabilities.
> > > >
> > > > In fact using kernel version to switch around library functionality is a bug i'd
> > > > argue.
> > >
> > > I'm sorry Ingo, but I still don't agree. We've had several versions of epoll,
> > > several (some even buggy) versions of splice() which cannot even be detected
> > > without checking the kernel release. And those are just two that immediately come
> > > to my mind. If we've been providing a version for the last 19 years, it surely had
> > > some valid uses.
> >
> > I'm sorry Willy, but you are mostly wrong - and there's no need to speculate here
> > really. Just try the patch below :-)
> >
> > If your claim that 'kernel version is needed at many places' is true then why am i
> > seeing this on a pretty general distro box bootup:
> >
> > [root@aldebaran ~]# uname -a
> > Linux aldebaran 2.6.99-tip-01574-g6ba54c9-dirty #1 SMP Sun Nov 7 10:24:38 CET 2010 x86_64 x86_64 x86_64 GNU/Linux
>
> I don't understand the point you're trying to make with this patch. [...]
It was a simple experiement to support my rather simple argument which you disputed.
> [...] Obviously we can pretend to be any version, [...]
Ok, it's a pretty cavalier style of arguing that you now essentially turn around
your earlier claim that the 'kernel version is needed at many places' and say what
i've been saying, prefixed with 'obviously' ;-)
Yes, it's obvious that the kernel version is not needed for many functional purposes
on a modern distro - and that was my exact point.
I cannot think of a single valid case where the proper user-space solution to some
ABI compatibility detail is a kernel version check. I'd even argue that we want to
keep unprivileged user-space from being able to implement such crappy version checks
...
Thanks,
Ingo
On Sun, Nov 07, 2010 at 12:27:09PM +0100, Ingo Molnar wrote:
> > I don't understand the point you're trying to make with this patch. [...]
>
> It was a simple experiement to support my rather simple argument which you disputed.
OK
> > [...] Obviously we can pretend to be any version, [...]
>
> Ok, it's a pretty cavalier style of arguing that you now essentially turn around
> your earlier claim that the 'kernel version is needed at many places' and say what
> i've been saying, prefixed with 'obviously' ;-)
Huh ?
> Yes, it's obvious that the kernel version is not needed for many functional purposes
> on a modern distro - and that was my exact point.
>
> I cannot think of a single valid case where the proper user-space solution to some
> ABI compatibility detail is a kernel version check.
Ingo, I believe you did not read a single line of my previous mail, because I
precisely gave you counter-examples of that. The first use is simply the user
running "uname -a" to see if *he* can safely enable feature X or Y which is
known to be badly broken in some old versions.
> I'd even argue that we want to
> keep unprivileged user-space from being able to implement such crappy version checks
> ...
I'd say that *YOU* want that despite the fact that on mainstream distros, it
buys nothing since it's easy to guess the real version anyway as I showed you.
Don't forget that you proposed this in order to hide symbols from a small set
of well-known distro kernels. And the most important in my opinion is that it
does not bring anything to those who are currently victim of exploits : those
who don't upgrade, because their uptime alone is enough to *know* that the
vuln you want to exploit is still there.
At some places, your proposal would probably end up with uname being
chmoded +s so that users stop asking the admin for trivial things. That
really makes no sense.
Willy
* Willy Tarreau <[email protected]> wrote:
> [...] I was explaining that doing this will not prevent them from guessing the
> precise kernel version, [...]
Well, which is exactly what i have said to Marcus early on in this discussion:
|
| What i suggested in later parts of my mail might provide more security: to sandbox
| kernel version information from unprivileged user-space - if we decide that we
| want to sandbox kernel version information ...
|
| That is a big if, because it takes a considerable amount of work. Would be worth
| trying it - but feel-good non-solutions that do not bring much improvement to the
| majority of users IMHO hinder such efforts.
|
The 'considerable amount of work' refers not to the utsname version fuzzing patch
(it's a 10-liner patch, literally), but to controlling the channels of version
information you mentioned (uptime, the /boot timestamp), and some other channels you
did not mention: dmesg, various /sys and /proc entries that leak version
information, etc.
All must be closed down for unprivileged user-space, for this to be effective,
obviously.
( Note that there will also be some channels of information that cannot
realistically be closed down (such as the presence of sys_perf_event_open()
indicates a v2.6.32+ kernel - or a backported, patched kernel) - but what matters
mostly is to fuzz the _precise_ version information, to inject uncertainty into
the equation of attackers. Combined with honeypot silent alarm functionality it
turns the equation around and creates an outright risk of detection. )
Thanks,
Ingo
* Willy Tarreau <[email protected]> wrote:
> On Sun, Nov 07, 2010 at 12:27:09PM +0100, Ingo Molnar wrote:
> > > I don't understand the point you're trying to make with this patch. [...]
> >
> > It was a simple experiement to support my rather simple argument which you disputed.
>
> OK
>
> > > [...] Obviously we can pretend to be any version, [...]
> >
> > Ok, it's a pretty cavalier style of arguing that you now essentially turn around
> > your earlier claim that the 'kernel version is needed at many places' and say what
> > i've been saying, prefixed with 'obviously' ;-)
>
> Huh ?
>
> > Yes, it's obvious that the kernel version is not needed for many functional purposes
> > on a modern distro - and that was my exact point.
> >
> > I cannot think of a single valid case where the proper user-space solution to some
> > ABI compatibility detail is a kernel version check.
>
> Ingo, I believe you did not read a single line of my previous mail, because I
> precisely gave you counter-examples of that. [...]
I did read it and saw no valid counter-examples. You mentioned this one:
> Take the splice() data corruption bug for instance. I believe it was fixed in
> 2.6.26 or 2.6.27 and backported late in the 2.6.25.X stable branch. Due to this,
> without knowing the kernel version, the user can't know whether it's safe to use
> splice() or not. I'm particularly aware of this one because I got quite a bunch
> of questions from users on this subject. But certainly there are a bunch of other
> ones.
That example is entirely bogus. The correct answer to a buggy, data-corrupting
kernel is a fixed kernel. No ifs and when. No version checks in user-space. If
user-space ever works around a bug in that fashion it's entirely broken and
_deserves_ to be further broken via version fuzzing.
Do you know of a single such actual vmsplice() version check example in user-space,
or have you just made it up?
Thanks,
Ingo
On Sun, Nov 07, 2010 at 12:42:37PM +0100, Ingo Molnar wrote:
>
> * Willy Tarreau <[email protected]> wrote:
>
> > [...] I was explaining that doing this will not prevent them from guessing the
> > precise kernel version, [...]
>
> Well, which is exactly what i have said to Marcus early on in this discussion:
>
> |
> | What i suggested in later parts of my mail might provide more security: to sandbox
> | kernel version information from unprivileged user-space - if we decide that we
> | want to sandbox kernel version information ...
> |
> | That is a big if, because it takes a considerable amount of work. Would be worth
> | trying it - but feel-good non-solutions that do not bring much improvement to the
> | majority of users IMHO hinder such efforts.
> |
>
> The 'considerable amount of work' refers not to the utsname version fuzzing patch
> (it's a 10-liner patch, literally), but to controlling the channels of version
> information you mentioned (uptime, the /boot timestamp), and some other channels you
> did not mention: dmesg, various /sys and /proc entries that leak version
> information, etc.
I did not mention dmesg because it's already sometimes hidden from users (eg,
when iptables logs there).
> All must be closed down for unprivileged user-space, for this to be effective,
> obviously.
This would only be effective against finding a precise version. There's
no need for that, what you want is to hide kernel pointers, and your issue
is that in distro kernels, same kernels have the same pointers. It would be
much more efficient to work on a method to randomize all pointers than to
try to hide a kernel version hoping a user is not able to guess what it is.
Even if you'd hide the uptime, there are many ways to find it. In my opinion,
it's a race in the wrong direction, and which has several negative side
effects on the normal user.
Better attack the problem than its symptoms.
Willy
On Sun, Nov 07, 2010 at 12:47:56PM +0100, Ingo Molnar wrote:
> I did read it and saw no valid counter-examples. You mentioned this one:
>
> > Take the splice() data corruption bug for instance. I believe it was fixed in
> > 2.6.26 or 2.6.27 and backported late in the 2.6.25.X stable branch. Due to this,
> > without knowing the kernel version, the user can't know whether it's safe to use
> > splice() or not. I'm particularly aware of this one because I got quite a bunch
> > of questions from users on this subject. But certainly there are a bunch of other
> > ones.
>
> That example is entirely bogus. The correct answer to a buggy, data-corrupting
> kernel is a fixed kernel. No ifs and when. No version checks in user-space. If
> user-space ever works around a bug in that fashion it's entirely broken and
> _deserves_ to be further broken via version fuzzing.
It's not working around a bug, it's that using splice() instead of
recv()+send() brings an important speed up in some environments, and that
it is suggested to make use of it when possible, except on buggy kernels.
Some user-space code simply have a tunable to enable it or not.
> Do you know of a single such actual vmsplice() version check example in user-space,
> or have you just made it up?
I was not speaking about vmsplice() but about splice(). And yes it's a real
world example. Haproxy makes use of it when the option is specified. And it
will never enable it automatically due to that nasty data corruption bug
that cannot be detected. Only the user can run "uname -a" and compare with
his distro's fixes (or mainline kernel fixes) and know what to do. Once again
it's just *one* example. A version is beforeall an indication of features and
bugs status.
It's precisely because you're making a special case of the security bug that
you want to hide bugs from user-space by cheating on version.
Willy
* Willy Tarreau <[email protected]> wrote:
> [...]
>
> It's precisely because you're making a special case of the security bug that you
> want to hide bugs from user-space by cheating on version.
You claimed this for the second time and i'm denying it for the second time.
The goal of fuzzing the version inforation is _not_ to 'hide bugs from user-space by
cheating on version'. The goal is to introduce uncertainty to attackers, so that a
honeypot silent alarm can warn the admin.
Why are you putting words in my mouth?
Thanks,
Ingo
On Sun, Nov 07, 2010 at 01:12:35PM +0100, Ingo Molnar wrote:
>
> * Willy Tarreau <[email protected]> wrote:
>
> > [...]
> >
> > It's precisely because you're making a special case of the security bug that you
> > want to hide bugs from user-space by cheating on version.
>
> You claimed this for the second time and i'm denying it for the second time.
>
> The goal of fuzzing the version inforation is _not_ to 'hide bugs from user-space by
> cheating on version'. The goal is to introduce uncertainty to attackers, so that a
> honeypot silent alarm can warn the admin.
My interpretation of this mechanism is what I explained above. "Introducing
uncertainty" means hiding a version so that the attacker doesn't precisely
know which one it is and has to send a few probes to guess it. That's not
much different than trying to fire the exploit itself. When you run a
null-deref kernel exploit, better be sure of what you're doing, otherwise
the admin will shortly be aware of it too.
You could as well consider that launching some commands is suspicious
(eg: uname). You'll obviously get a lot of false-positive alarms from
all autoconf scripts run in local, but this gives an idea. Anyway, when
local users have their time (eg: students), it's still easy to guess the
version.
> Why are you putting words in my mouth?
I'm not putting anything in your mouth Ingo :-)
Willy
* Willy Tarreau <[email protected]> wrote:
> > Why are you putting words in my mouth?
>
> I'm not putting anything in your mouth Ingo :-)
To quote you:
" you're making a special case of the security bug that you want to hide bugs from
user-space by cheating on version. "
No, i did not say that i want to hide bugs from user-space by cheating on the
version. Why are you claiming that i said that? Why are you putting words in my
mouth?
Thanks,
Ingo
* Willy Tarreau <[email protected]> wrote:
> On Sun, Nov 07, 2010 at 01:12:35PM +0100, Ingo Molnar wrote:
> >
> > * Willy Tarreau <[email protected]> wrote:
> >
> > > [...]
> > >
> > > It's precisely because you're making a special case of the security bug that you
> > > want to hide bugs from user-space by cheating on version.
> >
> > You claimed this for the second time and i'm denying it for the second time.
> >
> > The goal of fuzzing the version inforation is _not_ to 'hide bugs from user-space by
> > cheating on version'. The goal is to introduce uncertainty to attackers, so that a
> > honeypot silent alarm can warn the admin.
>
> My interpretation of this mechanism is what I explained above. [...]
( Well, if it's "your interpretation" only then stop claiming that i said it. )
> [...] "Introducing uncertainty" means hiding a version so that the attacker
> doesn't precisely know which one it is and has to send a few probes to guess it.
No. The 'exploit honeypot' mechanism i outlined is really simple, and it means what
i explained already:
- attacker breaks into unprivileged user-space
- attacker runs exploit
- exploit attempt gets detected by the 'exploit honeypot' kernel code and a
(silent) warning goes to the admin (via a syslog message for example)
- attacker only sees that the attack did not succeed
This makes it _unsafe_ (for many types of attackers) to run an exploit locally.
> That's not much different than trying to fire the exploit itself. [...]
Erm, the difference is possible _detection_ via a silent alarm.
There's a huge difference between 'attempting an exploit and being caught' and 'not
even trying the exploit because based on the kernel version the attacker knows it
wont work'.
Thanks,
Ingo
* Willy Tarreau <[email protected]> wrote:
> > All must be closed down for unprivileged user-space, for this to be effective,
> > obviously.
>
> This would only be effective against finding a precise version. [...]
I'm glad that you agree with my point.
> [...] There's no need for that, what you want is to hide kernel pointers, [...]
That's a new claim from you - and when put like that it's wrong too: if the goal is
to introduce risk of detection to attackers (which i suggested to be an efficient
security measure), then hiding/fuzzing version information is an essential/needed
piece of such a measure, not something for which there is 'no need'.
Hiding the address of kernel data/code structures is another piece of such a larger
goal. Btw., as i argued it to Marcus already, hiding /proc/kallsyms will not hide
these addresses on the vast majority of Linux systems, and that the patch would only
cure the symptom, not the cause:
|
| But without actually declaring and achieving that sandboxing goal this security
| measure is just a feel-good thing really [...]
|
Anyway, i wasnt particularly successful in conveying my past arguments to you so i'd
rather leave the discussion at this point. You made your points and i made my points
as well.
Thanks,
Ingo
On Sun, Nov 07, 2010 at 01:25:33PM +0100, Ingo Molnar wrote:
>
> * Willy Tarreau <[email protected]> wrote:
>
> > > Why are you putting words in my mouth?
> >
> > I'm not putting anything in your mouth Ingo :-)
>
> To quote you:
>
> " you're making a special case of the security bug that you want to hide bugs from
> user-space by cheating on version. "
>
> No, i did not say that i want to hide bugs from user-space by cheating on the
> version. Why are you claiming that i said that? Why are you putting words in my
> mouth?
I'm not claiming that "you said that", it's my interpretation of what
you're trying to achieve with what you're defending. I'm free to interprete
as I want. Probably it's a very synthetical analysis, but it's my analysis.
Willy
On Sun, Nov 07, 2010 at 01:32:32PM +0100, Ingo Molnar wrote:
> No. The 'exploit honeypot' mechanism i outlined is really simple, and it means what
> i explained already:
>
> - attacker breaks into unprivileged user-space
>
> - attacker runs exploit
>
> - exploit attempt gets detected by the 'exploit honeypot' kernel code and a
> (silent) warning goes to the admin (via a syslog message for example)
>
> - attacker only sees that the attack did not succeed
>
> This makes it _unsafe_ (for many types of attackers) to run an exploit locally.
It's already unsafe and has always been. When running local kernel exploits,
it's common to find lots of segfault traces in dmesg. It's common to hang the
machine (the vmsplice exploit had a 50% failure rate from my tests).
> > That's not much different than trying to fire the exploit itself. [...]
>
> Erm, the difference is possible _detection_ via a silent alarm.
>
> There's a huge difference between 'attempting an exploit and being caught' and 'not
> even trying the exploit because based on the kernel version the attacker knows it
> wont work'.
And there's an even bigger difference between leaving traces of a failed
exploit attempt and successfully getting the exploit to work because the
system is not updated in time. That's been my point since the beginning,
most kernel exploits are run very early when released to the public. So
that's when a simple "uptime" will tell you it's safe to run your exploit.
And if you want to hide the uptime, let's simply check the creation date
of /dev/shm, or that a file you left in /tmp has not been removed by the
admin's scripts which clean that up at boot, etc...
In my opinion this is not efficient at all. Also, I've already been involved
in post-mortem diags on compromised machines. If the intruder is not a known
local user, he does not care at all being caught. Leaving rootkits everywhere
is generally not a problem for them, some don't even take care of clearing
the logs, because they bounced from already compromised systems.
Willy
On Sun, Nov 07, 2010 at 01:37:46PM +0100, Ingo Molnar wrote:
> > [...] There's no need for that, what you want is to hide kernel pointers, [...]
>
> That's a new claim from you - and when put like that it's wrong too:
It's where the discussion started and it's still in the subject of the thread !
You noted that with distro kernels, hiding kallsyms is useless since uname -r
reveals what kernel to download to get them anyway. Which is true !
Reason why it would be more efficient to find how we could randomize those
pointers at runtime.
(...)
> Anyway, i wasnt particularly successful in conveying my past arguments to you so i'd
> rather leave the discussion at this point. You made your points and i made my points
> as well.
That's also what I was about to say. Let's agree we disagree and have a
nice sunday afternoon. We can bring the discussion back around a beer if
you happen to pass by Paris :-)
Cheers,
Willy
> This makes it _unsafe_ (for many types of attackers) to run an exploit locally.
They don't care.
Firstly it 's trivial to identify the true kernel version from all sorts
of other methods and secondly almost all exploiting is done by robots
running from box to box and which are completely disposable.
They simply *don't* care and if they do the rpm -q, tcp finger prints and
a few other tricks such as clock timing a couple of syscalls will answer
the question reliably anyway.
Marcus Meissner <[email protected]> writes:
>
> I also briefly thought about kernel ASLR, but my knowledge of the kernel
> loading is too limited whether this is even possible or at all useful.
Kernel ASLR sounds like a good idea, although there are some traps.
On 32bit the available range is not too great, only a few hundred MB
max. Probably less on a larger systems, there will conflicts with a
large mem_map. On 64bit x86 it's nearly 2GB and somewhat easier
(although a large mem_map may still be a problem)
You still want to not stray too much from a 2MB alignment
to make sure most of the main kernel is handled by a single 2MB TLB
entry.
It would not be too hard to do today using kexec and loading the kernel
twice. Right now the kexec command doesn't allow specifying
the address, but the kernel interface supports it, so it could
be just implemented in the user tool.
Doing it with a single boot sequence would be a bit more work.
Right now the relocation entries are not put into the bzImage
and that would be needed.
That would not cover modules, but it shouldn't be too difficult
to do it for those either.
-Andi
--
[email protected] -- Speaking for myself only.
We already do virtual relocation on 32 bits, and replicating that on 64 bits wouldn't be hard. However, the linkage script strongly assumes congruency mod 2/4 MiB, and that is probably nontrivial to change. However, that still gives about 9 bits of entrophy to play with. The question is if that is enough, or if we'd have to do more clever hacks.
"Andi Kleen" <[email protected]> wrote:
>Marcus Meissner <[email protected]> writes:
>>
>> I also briefly thought about kernel ASLR, but my knowledge of the
>kernel
>> loading is too limited whether this is even possible or at all
>useful.
>
>Kernel ASLR sounds like a good idea, although there are some traps.
>
>On 32bit the available range is not too great, only a few hundred MB
>max. Probably less on a larger systems, there will conflicts with a
>large mem_map. On 64bit x86 it's nearly 2GB and somewhat easier
>(although a large mem_map may still be a problem)
>
>You still want to not stray too much from a 2MB alignment
>to make sure most of the main kernel is handled by a single 2MB TLB
>entry.
>
>It would not be too hard to do today using kexec and loading the kernel
>twice. Right now the kexec command doesn't allow specifying
>the address, but the kernel interface supports it, so it could
>be just implemented in the user tool.
>
>Doing it with a single boot sequence would be a bit more work.
>Right now the relocation entries are not put into the bzImage
>and that would be needed.
>
>That would not cover modules, but it shouldn't be too difficult
>to do it for those either.
>
>-Andi
>
>--
>[email protected] -- Speaking for myself only.
--
Sent from my mobile phone. Please pardon any lack of formatting.
* Alan Cox <[email protected]> wrote:
> > This makes it _unsafe_ (for many types of attackers) to run an exploit locally.
>
> They don't care.
Sure, script kiddies and botnet builders wont care - i.e. attacks where the
individual target is low value, or where either the attacker or the attacked is
stupid.
But it's different when a skilled attacker meets a skilled defense: all the
exploits/attacks against high-value targets i've seen showed a great deal of care
taken to avoid detection.
Future trends are also clear: eventually, as more and more of our lives are lived on
the network, home boxes are becoming more and more valuable. So i think
concentrating on the psychology of the skilled attacker would not be unwise. YMMV.
Thanks,
Ingo
* H. Peter Anvin <[email protected]> wrote:
> We already do virtual relocation on 32 bits, and replicating that on 64 bits
> wouldn't be hard. However, the linkage script strongly assumes congruency mod 2/4
> MiB, and that is probably nontrivial to change. However, that still gives about 9
> bits of entrophy to play with. The question is if that is enough, or if we'd have
> to do more clever hacks.
Even 1 bit of entropy would bring a visible improvement: a failed exploit attempt to
the wrong address can crash the kernel with a 50% chance. 9 bits would be very nice.
If an exploit can be brute-forced without crashing the kernel then only some
significantly large bitness would help. So while 9 bits would be rather low for a
user-space ASLR scheme [many user-space bugs can be brute-forced without crashing
the system and raising alarms], it's very attractive for kernel ASLR.
Ingo
On Thu, 4 Nov 2010, Frank Rowand wrote:
> On 11/04/10 05:29, Marcus Meissner wrote:
> > On Thu, Nov 04, 2010 at 12:46:48PM +0100, Ingo Molnar wrote:
> >>
> >> * Marcus Meissner <[email protected]> wrote:
> >>
> >>> Hi,
> >>>
> >>> Making /proc/kallsyms readable only for root makes it harder for attackers to
> >>> write generic kernel exploits by removing one source of knowledge where things are
> >>> in the kernel.
>
> < snip >
>
> >> So what does a distribution like Suse expect from this change alone? Those have
> >> public packages in rpms which can be downloaded by anyone, so it makes little sense
> >> to hide it - unless _all_ version information is hidden.
> >
> > It is the first patch, mostly an acceptance test balloon.
> >
> > There are several other files handing information out, but kallsyms has
> > it all very nice and ready.
> >
> > (timer_list, /proc/*/stat*, sl?binfo )
> >
> >> So i'd like to see a _full_ version info sandboxing patch that thinks through all
> >> the angles and restricts uname -r kernel version info as well, and makes dmesg
> >> unaccessible to users - and closes a few other information holes as well that give
> >> away the exact kernel version - _that_ together will make it hard to blindly attack
> >> a very specific kernel version.
> >
> > I am personally thinking of a "small steps" philosophy, one step after the other.
>
> < snip >
>
> The idea of trying to hide the kernel version is absurd. The number of different
> places that can provide a precise fingerprint of a kernel version, or a small range of
> possible kernel versions is immense. Closing all of those places makes use and
> administration of a system more difficult, and encourages frequent use of su.
>
I agree. Hiding the kernel version is silly. But that's not what the
original patch was about. The original patch was about "Making
/proc/kallsyms readable only for root ..." and that (IMVHO) makes sense
for a number of reasons.
1. For those people running (popular) distro kernels, hiding the
information on /proc/kallsyms doesn't achieve much, true, an attacker can
get the information easily online. But it still makes it slightly more
involved for exploits to gain access to information about the addresses of
kernel functions - at the very least they now have to hard-code lists of
addresses for the kernels they target - not much pain, but the more pain
we can inflict upon these people without hurting legitimate users, the
better.
2. For people running niche-distros that attackers cannot be bothered to
target explicitly, but where they previously relied on obtaining these
addresses from /proc/kallsyms we have a real gain - the attackers can no
longer get the info they need.
3. For people running custom compiled kernels (and I personally know of a
few large businesses that do so and several individuals, and I'll bet real
money that there are more than you suspect "out there"), attacks relying
on /proc/kallsyms for info are completely defeated.
4. Once we get (and I'm sure that's only a matter of time) randomization
of the addresses that kernel functions are loaded at, even popular distros
where the kernel version and config are known to attackers will gain a
valuable defence by ths patch. Attackers will then no longer be able to
just download the info from the distro repositories and hard-code
addresses since they will be randomized, but if they have access to
/proc/kallsyms they won't need to since they can then just look up the
addresses there - this patch closes that info path to them which is good.
--
Jesper Juhl <[email protected]> http://www.chaosbits.net/
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please.
On 11/10/2010 12:53 AM, Ingo Molnar wrote:
>
> * H. Peter Anvin <[email protected]> wrote:
>
>> We already do virtual relocation on 32 bits, and replicating that on 64 bits
>> wouldn't be hard. However, the linkage script strongly assumes congruency mod 2/4
>> MiB, and that is probably nontrivial to change. However, that still gives about 9
>> bits of entrophy to play with. The question is if that is enough, or if we'd have
>> to do more clever hacks.
>
> Even 1 bit of entropy would bring a visible improvement: a failed exploit attempt to
> the wrong address can crash the kernel with a 50% chance. 9 bits would be very nice.
>
> If an exploit can be brute-forced without crashing the kernel then only some
> significantly large bitness would help. So while 9 bits would be rather low for a
> user-space ASLR scheme [many user-space bugs can be brute-forced without crashing
> the system and raising alarms], it's very attractive for kernel ASLR.
>
Now, *relative* symbol addresses will typically not have any randomness
at all, which may limit the usefulness, of course.
-hpa
--
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel. I don't speak on their behalf.
* H. Peter Anvin <[email protected]> wrote:
> Now, *relative* symbol addresses will typically not have any randomness at all,
> which may limit the usefulness, of course.
Yeah - but it happens quite often that the scope of the vulnerability only allows
absolute addresses. In fact it's a pretty common case: basically most derefs into
attacker-controlled data pointers are like that.
Thanks,
Ingo