Thursday, November 20, 2014

Small customizations to SELinux policy

Jason Tibberts III asked me a great question:

> So I have this AVC:
> avc: denied { name_connect } for pid=9045 comm="httpd" dest=9680 scontext=user_u:system_r:httpd_t:s0 tcontext=system_u:object_r:port_t:s0 tclass=tcp_socket
> which comes from a PHP script trying to open a socket. This is no big
> deal. I believe that setting httpd_can_network_connect should fix it.
> However, I was wondering if it's possible to restrict the destination
> port to 9680, or restrict the destination host at all?
> - J<

SELinux by default ships with httpd outgoing networking turned off. This is a good thing. In the past apache has had vulnerabilities that have allowed people to use a web server to forward traffic through a vulnerable server.

This has led to apache worms. Google Apache Worms gives 1,790,000 hits.
Apache mail bots that allow web server to become mail forwarders.
Any other attack plain where you can get the apache server to connect to other machines.

Since most apache web server only serve content, there is no reason to allow the server to connect to other machines by default.

We have setup several booleans in apache to allow it to connect

httpd_can_network_connect --> Allows apache to connect to any port
httpd_can_network_connect_db --> Allows apache to connect to database ports
httpd_can_network_relay --> Allows apache to connect to "apache" ports
httpd_can_sendmail --> Allows Apache to connect to the mail port

But as Jason points out this is not very fine grained. A better solution if you want to get your hands a little dirty with policy would be to write a policy module and define the port(s) you want to connect to.

You could build a simple policy module, and define the port type, and allow httpd_t to connect to the port.

# cat > myphp.te << _EOF

type httpd_t;

type php_port_t;

allow httpd_t php_port_t:tcp_socket name_connect;

Compile the and load the policy module
# make -f /usr/share/selinux/devel/Makefile
# semodule -i myphp.pp

Define the port numbers that are included in the port type.
# semanage port -a -t php_port_t -p tcp 9680

Now apache should be able to connect to port 9680 and only this port.

No comments: