Important Contexts
- The
httpd_sys_script_exec_t
type should be used for CGI scripts, allowing the web server to execute the scripts. - The
httpd_sys_script_rw_t, httpd_sys_script_ra_t
, andhttpd_sys_script_t
types are used for files that are only handled by the CGI scripts. These can be read/write, append-only, or read-only.
Sequence 1. Enabling a CGI Script in SELinux
- Edit the
/etc/httpd/conf/httpd.conf
file and replace the ‘ScriptAlias
‘ option with the following line:
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
- In the same file, where the configuration of your website (or virtual host) is located, add the following lines:
AllowOverride None
Options None
Require all granted
- Check the configuration file:
# apachectl configtest
Syntax OK
- Restart the httpd service:
# systemctl restart httpd
- Create your text Script
/var/www/cgi-bin/test.pl.
#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "Testing the Perl Secipt GCI Script
";
print "..... by Ram N Sangwan";Assign the Permissions
# chmod +x /var/www/cgi-bin/test.pl
- By default
/var/www/cgi-bin
directory has context
“httpd_sys_script_exec_t”. # ls -laZ /var/www/cgi-bin/
# ls -laZ /var/www/cgi-bin/test.pl
- Try
http://server.example.com/cgi-bin/test.pl
you will receive an error with a message saying you don’t have permission to access the file on the server. - Lets make it work
# semanage fcontext -a -t httpd_sys_script_exec_t “/var/www/cgi-bin(/.*)?"
# restorecon -R /var/www/cgi-bin/
# ls -laZ /var/www/cgi-bin/
# ls -laZ /var/www/cgi-bin/test.pl
- Just in case you require
# getsebool -a | grep httpd_enable_cgi
httpd_enable_cgi --> on
# setsebool httpd_enable_cgi off
# getsebool -a | grep httpd_enable_cgi
httpd_enable_cgi --> off
Sequence 2. Working with Python based CGI Script
[the_ad id="2469"]
- Create the following simple Python-based CGI script in a regular user's home directory:
$ mkdir ~/cgi-bin
$ vi ~/cgi-bin/test.py
#!/usr/bin/env python
import sys, time
import subprocess
import cgi, cgitb
cgitb.enable()
print 'Content-Type: text/html;charset=utf-8\n'
PIPE = subprocess.PIPE
STDOUT = subprocess.STDOUT
pd = subprocess.Popen(['ping','-c','1','localhost'], stdout=PIPE, stderr=STDOUT)
while True:
output = pd.stdout.read(1)
if output == '' and pd.poll() != None:
break
if output != '':
sys.stdout.write(output)
sys.stdout.flush()
- With this CGI script now available, first launch a simple CGI-capable web server:
$ python -m CGIHTTPServer 6020
- In a different session, connect to the web server and call the test.py CGI script:
$ curl http://localhost:6020/cgi-bin/test.py PING localhost (127.0.0.1) 56(84) bytes of data 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.002 ms -- localhost ping statistics -- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.002/0.002/0.002/0.000 ms
- Now, launch the same CGI-capable web server, but with NNP enabled:
$ setpriv --no-new-privs python -m CGIHTTPServer 6020
- Again, connect to the web server and call the test.py CGI script:
$ curl http://localhost:6020/cgi-bin/test.py ping: icmp open socket: Permission denied
- Because Linux's NNP is enabled, the ping command is not able to obtain the higher privileges needed to open the socket.
Sometimes, the SELinux policy doesn't even allow an application to be executed without transitioning. In that case, an execute_no_trans denial will show up:
type=AVC msg=audit(1150125191.592:740): avc: denied { execute_no_trans } for pid=2793 comm="pipe" name="PostFix.mail.SpamAssassin.spamfilter.sh" dev=md9 ino=56842 scontext=system_u:system_r:postfix_pipe_t:s0 tcontext=system_u:object_r:ql_spamassassin_client_exec_t:s0 tclass=file permissive=0