ProactiveSecurityRoadmap

Differences between revisions 1 and 52 (spanning 51 versions)
Revision 1 as of 2005-04-04 18:04:03
Size: 465
Editor: ca-studio-bsr1o-251
Comment:
Revision 52 as of 2006-05-15 17:39:10
Size: 14044
Editor: c-68-33-112-13
Comment: Refine my comments.
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
= People = ## page was renamed from ProactiveSecurityRoadmap
= Proactive Security Roadmap =
Line 3: Line 4:
 * MartinPitt
 * MatthiasKlose
== Status ==
Line 6: Line 6:
= Goal =   * Created: [[Date(2005-04-24T00:17:26Z)]] by MattZimmerman[[BR]]
  * Priority: LowPriority[[BR]]
  * People: MartinPittLead, AndrewMitchellSecond [[BR]]
  * Contributors: MattZimmerman[[BR]]
  * Interested: MartinPitt, MatthiasKlose, BrandonHale, AndrewMitchell[[BR]]
  * Status: ApprovedSpecification, BreezyGoal, DistroSpecification[[BR]]
  * Branch: [[BR]]
  * Malone Bug: [[BR]]
  * Packages: [[BR]]
  * Depends: [[BR]]
  * UduSessions: 2(0)[[BR]]
Line 8: Line 18:
Proactively improve security for Breezy == Introduction ==
Line 10: Line 20:
= Requirements = Establish a strategy for implementing proactive security features in Ubuntu.
Line 12: Line 22:
 * Run cron as non-root?
 * Run dhclient3 as non-root?
 * Eliminate inetd from base
 * Compile-time stack protection
== Rationale ==
Line 17: Line 24:
= Agenda = We want to reduce the risk of security holes in Ubuntu systems by reducing the number of potential attack vectors and find general solutions for preventing common classes of vulnerabilities. This confines the impact of actual vulnerabilities to a minimum.
Line 19: Line 26:
= Pre-Work = == Scope and Use Cases ==
Line 21: Line 28:
 * Research privilege requirements of cron, dhclient3
 * Search for implicit dependencies on inetd via netbase
 * Determine requirements for compile-time stack protection in gcc (4.x?)
 * We will patch the Ubuntu kernel to provide protection against common attacks and reduce the privileges of system daemons so that they run with least privileges.

 * Users may find that some programs need fixes as a result of these protections, and so we will provide a method to disable the kernel improvements at runtime.

 * If a community member supplies packages, we will have modified gcc and kernel packages with hardened patches available in universe.

== Implementation Plan ==

=== Data Preservation and Migration ===

Does not apply here.

=== Packages Affected ===

`Kernel`:
 * Port the [http://www.openwall.com/ OpenWall] patch that prevents exploitation of unsafe temporary file creation; it is really trivial; add a proc file to be able to enable/disable at runtime.
 * Provide a grsecurity kernel in universe, if a community member is interested to care about it; [http://people.ubuntu.com/~pitti/arch/martin.pitt@canonical.com--2005/linux-hardened--devel--2.6.10/ packaging] is available.
 * Extract and port some of grsecurity's `/proc` restrictions which can be enabled/disabled at runtime:
  * Users can only see their own processes; this will keep them from e.g. seeing confidential command line arguments of other processes, which is still a very common mistake.
  * Hide memory addresses from map files: make it harder to deploy successful exploitations of heap overflows.
 * Extract and port randomization patches from grsecurity:
  * PID: Prevent the prediction of PIDs for child processes to make it harder to exploit race conditions, and avoid information leaks.
  * TCP sequence numbers: Make it harder to hijack TCP connections.
  * TCP source ports: Drastically increase the average time for TCP reset attacks.

`prelink`:
 * Prelinked applications leave a huge `/var/log/prelink.log` which contains memory address; patch prelink to not dump addresses.

`gcc`:
 * If a community member is interested, we can provide SSP/Fortify/etc. gcc packages in universe, but we will not put them into main and use them as a default as long as upstream does not adopt a solution. Mainstream (gcc 4.1, the developement branch) integrated stack smashing protections. When gcc 4.1 will become the standard Ubuntu compiler, would be worth to activate this option for most packages compilation.

`dhcp3-client`:
 * Currently `dhclient` runs as root, which is much more than necessary.
 * Privilege requirements: normal users with CAP_NET_RAW and CAP_NET_BIND_SERVICE; needs a suid wrapper to call /etc/dhcp3/dhclient-script
 * `dhclient-script` must be security reviewed (proper quoting, etc.).
 * Status: Implemented in Breezy, patch sent to Debian.
 * OpenBSD has a modified (with privsep and the like) and well audited version of dhclient and dhcpd. Could be of use for a comparison.

`dhcp3-server`:
 * Currently `dhcpd` runs as root, which is much more than necessary.
 * Privilege requirements: normal user with CAP_NET_RAW and CAP_NET_BIND_SERVICE for initialization phase; these can be dropped after socket creation.
 * Status: Implemented in Breezy, patch sent to Debian.

`inetd`:
 * This package is currently installed by default as part of the base system; since it is a daemon running as root, but is not used much any more, it is desirable to throw it out to Supported.
 * MartinPitt compiled a list of all packages in main which use inetd on the InetdUsage page.

`unix_chkpwd`:
 * Change `/sbin/unix_chkpwd` from setuid root to setgid shadow by default.
 * Since this breaks NIS lookups (see [http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=155583 #155583]), the permissions need to be changed back to setuid root if the package `nis` is installed. There is no clean way to achieve that, though. After consulting Scott, the least evil hack seems to be:
  * `nis` postinst: If `unix_chkpwd` does not yet already have an override, do `dpkg-statoverride` to set the permissions to `root:root 4755`.
  * `nis` prerm: If the current permissions of `unix_chkpwd` is `root:root 4755` and there is a stat override for it, remove the override to restore permissions.

== Outstanding Issues ==

Desirable for the future:
 * Exponentially delay the respawning of repeatedly crashing applications to prevent brute force attacks (eventually finding the correct offset of memory locations for buffer overflow attacks).
  * There are some potential ways to do this that can be mainly non-intrusive, I will discuss this later.
 * Evaluate chroot hardening patches.
  * A lot of nice stuff in GrSecurity.
 * Memory protection: Jamie will research whether there are things exploitable in exec-shield which aren't in PaX.
 * Compile-time stack protection.
  * mudflap comes with gcc 4.0, but does not help in any way to improve proactive security
   * mudflap is a debugging tool, not a security tool. Stop treating it like the next ProPolice.
  * [http://www.research.ibm.com/trl/projects/security/ssp/ SSP] currently offers the [http://www.ida.liu.se/~johwi/research_publications/paper_ndss2003_john_wilander.pdf most effective protection], but does not (currently) work with 4.0 and is unlikely to be accepted upstream.
   * Upstream in 4.1, although some report it to be semi-broken.
  * There is another project called FORTIFY_SOURCE which has a better chance to be eventually accepted upstream.
  * We will not support any solution that is not at least considered upstream.
   * Fedora Core 5 uses both FORTIFY_SOURCE and mainline SSP in tandem.
  * As of now, mainstream gcc development branch (4.1) implemented this protection (not mudflap). See [http://gcc.gnu.org/gcc-4.1/changes.html Gcc 4.1 changes]
 * Runtime memory protection
  * Since there is no accepted upstream solution, we will not support that in main for now. However, if a community member wants to provide universe kernels, we would greatly appreciate that.
  * Some info is already compiled at http://ubuntu.com/wiki/UbuntuHardened.

 * Reduce the privileges of cron.
  * Parsing the crontabs as normal user and introducing a minimal setuid wrapper for actually executing the commands as the target user will not help to improve security; the remaining stuff (timer and signal handling) does not accept user input and thus is not very error prone. I do not really have a good idea about this. (Note: atd also runs with root privileges, it just hides them pretty well; I do not have an idea how to deroot this either, it's the same problem.)
 * Support SELinux out of the box; there is a [wiki:SELinux separate BoF] about this topic. It should be noticed that Secure Computing recently reaffirmed his patent right on SELinux "Type Enforcement" technology. They allow to use SELinux freely on anything but firewalls, vpn and authentification servers etc. See [http://www.securecomputing.com/pdf/Statement_of_Assurance.pdf SSC Statement of assurance] and [http://lwn.net/Articles/6267/ LWN article]. What's our position in regard to this patent ?
 * Evaluate RSBAC or GRsecurity as potentials SELinux alternatives for ACL. See. [http://gentoo-wiki.com/Access_Control_Comparison_Table Gentoo's ACL Comparison Table]

== Comments ==

ColinWatson: I think other-user-process hiding should be off by default; when turned on, it requires the system administrator to use extra privilege to inspect the state of the system, which is not necessarily an obvious security win.

JohnMoser: Colin, consider that most users don't need to know all that. A 'sudo ps -e' is harmless unless the user running ''sudo'' has his account compromised, in which case running ''sudo'' could run a trojan that runs ''sudo'' to get itself root and (for stealth) execute your command. Consider what I just said: accounts with ''sudo'' access are basically root accounts with the stupidity guard on, they won't protect you from malware.

FurryBall: I would like to comment on the SSP and userland protection part. In overall there are more effective and secure ways to achieve this - doing it by the kernelland governing the userland. Mentioning PAX and Exec_shield. I'd say do the task once and focus on doing it better there..

JohnMoser: Furry, PaX and Exec Shield do not do direct stack smash protection, they do general memory corruption trap-and-kill. Also in some cases you still get an executable stack, or you have low entropy on address space randomization and a 216 second brute force on apache. In these cases, you have 32 orders of magnitude more work to do to break the SSP canary. Sorry, but a format string bug will quickly defeat this; we're still 4 billion times better protected against vanilla buffer overflows on the stack.

JohnMoser: Furry, you should also consider that ProPolice/SSP will re-order local variables and place passed arguments into local variables when entering a function. This protects local variables and passed arguments (i.e. pointers) from short buffer overflows in ways the kernel could never hope to. The only damage a buffer overflow can do before we detect it is to other stack frames from the calling function chain.

JohnMoser: An interesting hack would possibly be to combine ProPolice/SSP — protection of everything in the current stack frame — with a very ugly kernel and compiler hack that makes every stack frame start on a new page, and sticks an unmapped page between each stack frame. This would create a situation where buffer overflows on the stack can reliably be prevented from altering program flow before being detected; RETP and SFP damage would be detected before use, passed arguments and local variables are not harmed, and the previous stack frame has a guard page that can't be faulted into. This is of course a major ABI change and total breakage; '''it's a cute idea, but not viable'''. Maybe OpenBSD will do it.


=== Input from JohnMoser ===
Considering hardened kernels, PaX/GrSecurity vs. Exec Shield is a major argument. Exec Shield provides a very nice level of protection; while PaX provides a stricter but more secure environment. Exec Shield has wide testing in Fedora Core and RHEL, and thus is an easier near-target. See PaXvExecShield for a dedicated wiki entry comparing the two.

Exec Shield could be implemented in the default Ubuntu kernel. This works quite well in Fedora/RHEL, and thus has a wide test base. Exec Shield is also controlled by the '''exec-shield''' kernel command line; '''exec-shield=0''' turns it off, mimicing IA-32 behavior; while '''exec-shield=2''' defaults it on unless a binary opts out, mimicing behavior on a true NX bit platform. Rather than support kernels with and without Exec Shield, using the boot option would be possible.

If I recall correctly, Fedora Core and RHEL both use a higher order address space layout randomization than stock mainline; but the code is in mainline Linux. We should perhaps look into patching the kernel to use high order entropy by default, more similar to PaX; but also to accept a kernel command line parameter such as '''stack-aslr=12''' and '''mmap-aslr=16''' to adjust this at boot time. Low entropy randomization is easily brute forced in respawning daemons, especially ones which fork() to handle connections: ''apache'' is an easy target.

One problem with Exec Shield is it does not implement PaX mprotect() restrictions to enforce true ''data-code separation''. PaX second-guesses the program and makes sure all memory is initialized with only one of '''PROT_WRITE''' and '''PROT_EXEC'''. This does not typically hinder program execution; however, there may be a few cases. We should look into implementing this as a managable policy to create ''passive data-code separation''.

PaX also has the ability to enforce data-code separation. In this mode, non-executable memory never gains '''PROT_EXEC'''; and executable memory may never be granted '''PROT_WRITE''' without dropping '''PROT_EXEC'''. This gives ''active data-code separation''. This can be disabled in PaX per executable binary or, with SELinux hooks, per process based on security context. This policy control is worth implementing, as it gives enterprise security administrators the ability to enforce fine-grained control over memory protection and keep track of what programs are most vulnerable in the event of a security alert. This leads to prioritizing security patch application.

GrSecurity has a good brute force deterrance scheme, which makes fork() enter a queue that gets one execution per 30 seconds when called if a PaX kill or segmentation fault is encountered in a child fork() process with the same executable image. This causes one fork() to occur every 30 seconds. As expected, this is a hugely visible denial-of-service attack; but hey, we're making broken code safe, it's not going to be pretty so don't try. Obviously this DoS can only occur if an already existing security hole is attacked, so clean programs are unaffected. '''It is possible to devise a less intrusive model that is almost as effective'''.

Proactive Security Roadmap

Status

Introduction

Establish a strategy for implementing proactive security features in Ubuntu.

Rationale

We want to reduce the risk of security holes in Ubuntu systems by reducing the number of potential attack vectors and find general solutions for preventing common classes of vulnerabilities. This confines the impact of actual vulnerabilities to a minimum.

Scope and Use Cases

  • We will patch the Ubuntu kernel to provide protection against common attacks and reduce the privileges of system daemons so that they run with least privileges.
  • Users may find that some programs need fixes as a result of these protections, and so we will provide a method to disable the kernel improvements at runtime.
  • If a community member supplies packages, we will have modified gcc and kernel packages with hardened patches available in universe.

Implementation Plan

Data Preservation and Migration

Does not apply here.

Packages Affected

Kernel:

  • Port the [http://www.openwall.com/ OpenWall] patch that prevents exploitation of unsafe temporary file creation; it is really trivial; add a proc file to be able to enable/disable at runtime.

  • Provide a grsecurity kernel in universe, if a community member is interested to care about it; [http://people.ubuntu.com/~pitti/arch/martin.pitt@canonical.com--2005/linux-hardened--devel--2.6.10/ packaging] is available.

  • Extract and port some of grsecurity's /proc restrictions which can be enabled/disabled at runtime:

    • Users can only see their own processes; this will keep them from e.g. seeing confidential command line arguments of other processes, which is still a very common mistake.
    • Hide memory addresses from map files: make it harder to deploy successful exploitations of heap overflows.
  • Extract and port randomization patches from grsecurity:
    • PID: Prevent the prediction of PIDs for child processes to make it harder to exploit race conditions, and avoid information leaks.
    • TCP sequence numbers: Make it harder to hijack TCP connections.
    • TCP source ports: Drastically increase the average time for TCP reset attacks.

prelink:

  • Prelinked applications leave a huge /var/log/prelink.log which contains memory address; patch prelink to not dump addresses.

gcc:

  • If a community member is interested, we can provide SSP/Fortify/etc. gcc packages in universe, but we will not put them into main and use them as a default as long as upstream does not adopt a solution. Mainstream (gcc 4.1, the developement branch) integrated stack smashing protections. When gcc 4.1 will become the standard Ubuntu compiler, would be worth to activate this option for most packages compilation.

dhcp3-client:

  • Currently dhclient runs as root, which is much more than necessary.

  • Privilege requirements: normal users with CAP_NET_RAW and CAP_NET_BIND_SERVICE; needs a suid wrapper to call /etc/dhcp3/dhclient-script
  • dhclient-script must be security reviewed (proper quoting, etc.).

  • Status: Implemented in Breezy, patch sent to Debian.
  • OpenBSD has a modified (with privsep and the like) and well audited version of dhclient and dhcpd. Could be of use for a comparison.

dhcp3-server:

  • Currently dhcpd runs as root, which is much more than necessary.

  • Privilege requirements: normal user with CAP_NET_RAW and CAP_NET_BIND_SERVICE for initialization phase; these can be dropped after socket creation.
  • Status: Implemented in Breezy, patch sent to Debian.

inetd:

  • This package is currently installed by default as part of the base system; since it is a daemon running as root, but is not used much any more, it is desirable to throw it out to Supported.
  • MartinPitt compiled a list of all packages in main which use inetd on the InetdUsage page.

unix_chkpwd:

  • Change /sbin/unix_chkpwd from setuid root to setgid shadow by default.

  • Since this breaks NIS lookups (see [http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=155583 #155583]), the permissions need to be changed back to setuid root if the package nis is installed. There is no clean way to achieve that, though. After consulting Scott, the least evil hack seems to be:

    • nis postinst: If unix_chkpwd does not yet already have an override, do dpkg-statoverride to set the permissions to root:root 4755.

    • nis prerm: If the current permissions of unix_chkpwd is root:root 4755 and there is a stat override for it, remove the override to restore permissions.

Outstanding Issues

Desirable for the future:

  • Exponentially delay the respawning of repeatedly crashing applications to prevent brute force attacks (eventually finding the correct offset of memory locations for buffer overflow attacks).
    • There are some potential ways to do this that can be mainly non-intrusive, I will discuss this later.
  • Evaluate chroot hardening patches.
  • Memory protection: Jamie will research whether there are things exploitable in exec-shield which aren't in PaX.
  • Compile-time stack protection.
  • Runtime memory protection
    • Since there is no accepted upstream solution, we will not support that in main for now. However, if a community member wants to provide universe kernels, we would greatly appreciate that.
    • Some info is already compiled at http://ubuntu.com/wiki/UbuntuHardened.

  • Reduce the privileges of cron.
    • Parsing the crontabs as normal user and introducing a minimal setuid wrapper for actually executing the commands as the target user will not help to improve security; the remaining stuff (timer and signal handling) does not accept user input and thus is not very error prone. I do not really have a good idea about this. (Note: atd also runs with root privileges, it just hides them pretty well; I do not have an idea how to deroot this either, it's the same problem.)
  • Support SELinux out of the box; there is a [wiki:SELinux separate BoF] about this topic. It should be noticed that Secure Computing recently reaffirmed his patent right on SELinux "Type Enforcement" technology. They allow to use SELinux freely on anything but firewalls, vpn and authentification servers etc. See [http://www.securecomputing.com/pdf/Statement_of_Assurance.pdf SSC Statement of assurance] and [http://lwn.net/Articles/6267/ LWN article]. What's our position in regard to this patent ?

  • Evaluate RSBAC or GRsecurity as potentials SELinux alternatives for ACL. See. [http://gentoo-wiki.com/Access_Control_Comparison_Table Gentoo's ACL Comparison Table]

Comments

ColinWatson: I think other-user-process hiding should be off by default; when turned on, it requires the system administrator to use extra privilege to inspect the state of the system, which is not necessarily an obvious security win.

JohnMoser: Colin, consider that most users don't need to know all that. A 'sudo ps -e' is harmless unless the user running sudo has his account compromised, in which case running sudo could run a trojan that runs sudo to get itself root and (for stealth) execute your command. Consider what I just said: accounts with sudo access are basically root accounts with the stupidity guard on, they won't protect you from malware.

FurryBall: I would like to comment on the SSP and userland protection part. In overall there are more effective and secure ways to achieve this - doing it by the kernelland governing the userland. Mentioning PAX and Exec_shield. I'd say do the task once and focus on doing it better there..

JohnMoser: Furry, PaX and Exec Shield do not do direct stack smash protection, they do general memory corruption trap-and-kill. Also in some cases you still get an executable stack, or you have low entropy on address space randomization and a 216 second brute force on apache. In these cases, you have 32 orders of magnitude more work to do to break the SSP canary. Sorry, but a format string bug will quickly defeat this; we're still 4 billion times better protected against vanilla buffer overflows on the stack.

JohnMoser: Furry, you should also consider that ProPolice/SSP will re-order local variables and place passed arguments into local variables when entering a function. This protects local variables and passed arguments (i.e. pointers) from short buffer overflows in ways the kernel could never hope to. The only damage a buffer overflow can do before we detect it is to other stack frames from the calling function chain.

JohnMoser: An interesting hack would possibly be to combine ProPolice/SSP — protection of everything in the current stack frame — with a very ugly kernel and compiler hack that makes every stack frame start on a new page, and sticks an unmapped page between each stack frame. This would create a situation where buffer overflows on the stack can reliably be prevented from altering program flow before being detected; RETP and SFP damage would be detected before use, passed arguments and local variables are not harmed, and the previous stack frame has a guard page that can't be faulted into. This is of course a major ABI change and total breakage; it's a cute idea, but not viable. Maybe OpenBSD will do it.

Input from JohnMoser

Considering hardened kernels, PaX/GrSecurity vs. Exec Shield is a major argument. Exec Shield provides a very nice level of protection; while PaX provides a stricter but more secure environment. Exec Shield has wide testing in Fedora Core and RHEL, and thus is an easier near-target. See PaXvExecShield for a dedicated wiki entry comparing the two.

Exec Shield could be implemented in the default Ubuntu kernel. This works quite well in Fedora/RHEL, and thus has a wide test base. Exec Shield is also controlled by the exec-shield kernel command line; exec-shield=0 turns it off, mimicing IA-32 behavior; while exec-shield=2 defaults it on unless a binary opts out, mimicing behavior on a true NX bit platform. Rather than support kernels with and without Exec Shield, using the boot option would be possible.

If I recall correctly, Fedora Core and RHEL both use a higher order address space layout randomization than stock mainline; but the code is in mainline Linux. We should perhaps look into patching the kernel to use high order entropy by default, more similar to PaX; but also to accept a kernel command line parameter such as stack-aslr=12 and mmap-aslr=16 to adjust this at boot time. Low entropy randomization is easily brute forced in respawning daemons, especially ones which fork() to handle connections: apache is an easy target.

One problem with Exec Shield is it does not implement PaX mprotect() restrictions to enforce true data-code separation. PaX second-guesses the program and makes sure all memory is initialized with only one of PROT_WRITE and PROT_EXEC. This does not typically hinder program execution; however, there may be a few cases. We should look into implementing this as a managable policy to create passive data-code separation.

PaX also has the ability to enforce data-code separation. In this mode, non-executable memory never gains PROT_EXEC; and executable memory may never be granted PROT_WRITE without dropping PROT_EXEC. This gives active data-code separation. This can be disabled in PaX per executable binary or, with SELinux hooks, per process based on security context. This policy control is worth implementing, as it gives enterprise security administrators the ability to enforce fine-grained control over memory protection and keep track of what programs are most vulnerable in the event of a security alert. This leads to prioritizing security patch application.

GrSecurity has a good brute force deterrance scheme, which makes fork() enter a queue that gets one execution per 30 seconds when called if a PaX kill or segmentation fault is encountered in a child fork() process with the same executable image. This causes one fork() to occur every 30 seconds. As expected, this is a hugely visible denial-of-service attack; but hey, we're making broken code safe, it's not going to be pretty so don't try. Obviously this DoS can only occur if an already existing security hole is attacked, so clean programs are unaffected. It is possible to devise a less intrusive model that is almost as effective.

UbuntuDownUnder/BOFs/ProactiveSecurityRoadmap (last edited 2008-08-06 16:18:54 by localhost)