Download as odt, pdf, or txt
Download as odt, pdf, or txt
You are on page 1of 4

AppArmor protection for your Apache (including

mod_php, mod_python and others)


December 13, 2006 at 19:51 · Filed under Linux
The biggest weak of Apache httpd web server is lack of security when using it in multiuser enviroment.
All httpd processes run under the same UID and GID which means that user JOE can create simple
php script which when run via httpd will be able to open and read other users web files (which means
that other users database passwords hidden somewhere in web configuration files are not protected).
There are some ways to protect your files:
• FastCGI (mainly for PHP; allows to run php scripts under different privileges)
• CGI (running PHP and other scripts through suexec)
• nonstandard apache MPMs like peruser, metuxmpm (allow to run parts of httpd with different
UID/GID; unfortunately very alpha quality)
The primary problem with all above is that performance drops dramaticly.
That’s where AppArmor comes to a rescue.
AppArmor is kind of SuSE response to SELinux. SELinux is preety good
when it comes to creating fine grained policy rules but
tends to be quite complicated when it comes to writting policies for programs.
The AppArmor on the other hand is much simpler but also quite limited. AppArmor can be used to
restrict file and capabilities(7)
access only. That’s enough for us - we want exactly that - limit access to parts of filesystem.
The primary reason why we choose AppArmor over SELinux here is the ,,change hat” functionality.
It allows to define subpolicies for a program and the program is able to switch between subpolicies.
apache-mod_apparmor allows to switch subpolicy on per virtual host, directory and location basis!

How to do that?

First you need to patch you kernel with apparmor patches (these are very small and non-intrusive);
most of AppArmor lives in separate directory in kernel tree: security/apparmor so it’s not conflicting
even with grsecurity patches. You will also need to download and build apparmor-parser, apparmor-profiles
and apparmor-utils packages. All these available on AppArmor Home Page.
AppArmor keeps policy files in /etc/apparmor.d/. These are simple text files, for example
/etc/apparmor.d/usr.sbin.httpd.prefork policy:
# vim:syntax=apparmor
# Last Modified: Tue Dec 12 02:37:27 2006
#include <tunables/global>
/usr/sbin/httpd.prefork flags=(complain) {
#include <abstractions/base>
#include <abstractions/nameservice>
/usr/sbin/httpd.prefork mr,
capability setuid,
capability setgid,
capability kill,
capability dac_override,
capability dac_read_search,
/etc/httpd/apache.conf r,
/etc/httpd/conf.d r,
/etc/httpd/conf.d/* r,
/etc/httpd/ssl/* r,
/usr/lib{,64}/apache/*.so mr,
/etc/httpd/webapps.d r,
/etc/gai.conf r,
/etc/httpd/magic r,
/etc/mime.types r,
/usr/share/file/magic* r,
/etc/openssl/** r,
/var/log/httpd/** w,
/var/log/archive/httpd/* w,
/etc/php4/** r,
/usr/lib{,64}/php4/*.so mr,
/etc/php/** r,
/usr/lib{,64}/php/*.so mr,
/var/run/httpd.pid rw,
/var/run/httpd/** rw,
/proc/[0-9]*/attr/current rw,
/etc/snmp/** r,
/usr/share/snmp/** r,
/usr/share/perl5/** r,
/usr/lib{,64}/perl5/** r,
/usr/lib{,64}/perl5/**.so* mr,
/usr/X11R6/lib{,64}/lib*.so* mr,
^HANDLING_UNTRUSTED_INPUT flags=(complain) {
/home/services/httpd/** r,
/var/log/httpd/** w,
/var/log/archive/httpd/* w,
/home/users/**/.htaccess r,
}
^HAT_no_access flags=(complain) {
/home/services/httpd/** r,
/var/log/httpd/** w,
/var/log/archive/httpd/* w,
}
#include <abstractions/httpd-users>
}
r – read, w – write, ix – inherited policy on execution, * – simple globbing, **– glob that also matches slash
character (there is more of these of course – see man apparmor.d(5) for details).
HANDLING_UNTRUSTED_INPUT and HAT_no_access are HATs configuration (HAT is previously
mentioned subpolicy). By default mod_apparmor runs in HANDLING_UNTRUSTED_INPUT hat. That hat
can be changed from configuration file for example:
AADefaultHatName HAT_no_access
<VirtualHost vhost.domain.org>
AADefaultHatName HAT_domain_org
[...]
</VirtualHost>
<VirtualHost vhost.other-domain.com>
AADefaultHatName HAT_other_domain_com
[...]
</VirtualHost>
will cause that mod_apparmor sets appropriate hat on per virtual host basis (as mentioned earlier we can use
AADefaultHatName in Location and Directory directives, too).
Now we need to sets policies for these new vhost hats, but first we will put common rules into single
abstraction/httpd-hat file that later will be used in HAT policies:
#include <abstractions/base>
capability setuid,
capability setgid,
/proc/[0-9]*/mounts r,
/proc/filesystems r,
/home/services/httpd/** r,
/var/log/httpd/** w,
/var/log/archive/httpd/* w,
/usr/lib{,64}/perl5/** r,
/usr/lib{,64}/perl5/**.so* mr,
/etc/mysql/mysql-client.conf r,
/etc/services r,
/etc/protocols r,
/etc/nsswitch.conf r,
/etc/hosts r,
/etc/host.conf r,
/etc/resolv.conf r,
/etc/mtab r,
/etc/fstab r,
/etc/xml/* r,
/etc/fonts/** r,
/usr/share/** r,
/var/cache/fontconfig/* r,
/var/run/php r,
/var/run/php/** rw,
/var/run/nscd/socket rw,
/tmp r,
/tmp/** rwl,
/bin/* ixr,
/usr/bin/* ixr,
/usr/lib{,64}/lib*.so* mr,
/usr/X11R6/lib{,64}/lib*.so* mr,
/usr/lib{,64}/ImageMagick-** r,
/usr/lib{,64}/ImageMagick-**.so* mr,
and finally HAT policies in abstractions/httpd-users:
^HAT_domain_org {
#include <abstractions/httpd-hat>
/home/users/web-pages/domain_org rw,
/home/users/web-pages/domain_org/** rw,
/home/users/web-pages/domain_org/cgi-bin/** ixrw,
}
^HAT_other_domain_com {
#include <abstractions/httpd-hat>
/home/users/web-pages/other_domain_com rw,
/home/users/web-pages/other_domain_com/** rw,
/home/users/web-pages/other_domain_com/cgi-bin/** ixrw,
}
That’s all. We load policy using rcapparmor init script (/etc/rc.d/init.d/apparmor in PLD/Linux). We can put
profile into complain mode (everything is logged but no restriction is in effect) or in enforce mode (apparmor
will enforce profile and log rejects). Example /var/log/audit/audit.log:
type=UNKNOWN[1500] msg=audit(1166014976.862:130983): REJECTING r access
to /var/cache/fontconfig/2ee5dd3f6641dbe23533346fa3fce51a-x86-64.cache-2
(convert(13663) pro
file /usr/sbin/httpd.prefork active HAT_domain_org)
type=UNKNOWN[1500] msg=audit(1166015781.907:130984): REJECTING r access
to /etc/fonts/conf.avail/20-fix-globaladvance.conf (convert(17219) profile /usr/sbin/httpd.p
refork active HAT_domain_org)
type=UNKNOWN[1500] msg=audit(1166015781.907:130985): REJECTING r access
to /etc/fonts/conf.avail/20-lohit-gujarati.conf (convert(17219) profile /usr/sbin/httpd.pref
ork active HAT_domain_org)
[...]
type=UNKNOWN[1500] msg=audit(1166016116.536:131037): REJECTING r access
to /var/cache/fontconfig/2ee5dd3f6641dbe23533346fa3fce51a-x86-64.cache-2
(convert(17596) pro
file /usr/sbin/httpd.prefork active HAT_other_domain_com)
type=UNKNOWN[1500] msg=audit(1166016139.393:131038): REJECTING r access
to /var/tmp (httpd.prefork(7442) profile /usr/sbin/httpd.prefork active
HAT_other_domain_com)
type=UNKNOWN[1500] msg=audit(1166016139.405:131039): REJECTING r access
to /var/tmp (httpd.prefork(7442) profile /usr/sbin/httpd.prefork active
HAT_other_domain_com)
type=UNKNOWN[1500] msg=audit(1166016139.429:131040): REJECTING r access
to /var/tmp (httpd.prefork(7442) profile /usr/sbin/httpd.prefork active
HAT_other_domain_com)
This log file is very usefull when creating policy (of course apparmor provides some tools that will create
policy for you by parsing log file but I was doing everything manually with vim in one hand and tail in
second).
Note that .htaccess checking is done at HANDLING_UNTRUSTED_INPUT level, before vhost HAT is
applied.
ps. you will probably need to pass capability.disable=1 selinux=off when booting kernel. Otherwise apparmor
won’t even load.

You might also like