CGI scripts and SELinux

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, and httpd_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

  1. Edit the /etc/httpd/conf/httpd.conffile and replace the ‘ScriptAlias‘ option with the following line:
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
  1. In the same file, where the configuration of your website (or virtual host) is located, add the following lines:
<Directory "/var/www/cgi-bin">
    AllowOverride None
    Options None
    Require all granted
  1. Check the configuration file:
# apachectl configtest
Syntax OK
  1. Restart the httpd service:
# systemctl restart httpd
  1. Create your text Script
print "Content-type: text/html\n\n";
print "Testing the Perl Secipt GCI  Script <br \>";
print "..... by Ram N Sangwan";Assign the Permissions
# chmod +x /var/www/cgi-bin/
  1. By default /var/www/cgi-bin directory has context
# ls -laZ /var/www/cgi-bin/
# ls -laZ /var/www/cgi-bin/
  1. Try you will receive an error with a message saying you don’t have permission to access the file on the server.
  2. 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/
  1. 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

  1. Create the following simple Python-based CGI script in a regular user’s home directory:
$ mkdir ~/cgi-bin
$ vi ~/cgi-bin/
#!/usr/bin/env python 

import sys, time 
import subprocess 
import cgi, cgitb 
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 = 
  if output == '' and pd.poll() != None: 
  if output != '': 
  1. With this CGI script now available, first launch a simple CGI-capable web server:
$ python -m CGIHTTPServer 6020
  1. In a different session, connect to the web server and call the CGI script:
$ curl http://localhost:6020/cgi-bin/ 
PING localhost ( 56(84) bytes of data 
64 bytes from localhost ( 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 
  1. Now, launch the same CGI-capable web server, but with NNP enabled:
$ setpriv --no-new-privs python -m CGIHTTPServer 6020
  1. Again, connect to the web server and call the CGI script:
$ curl http://localhost:6020/cgi-bin/
ping: icmp open socket: Permission denied 
  1. 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="" dev=md9 ino=56842 
  tclass=file permissive=0 

September 23, 2019

0 responses on "CGI scripts and SELinux"

Leave a Message

WhatsApp chat