0

I have a webserver running CentOS 6.2 and the latest Apache from repositories. Todey I encountered a problem when running an executable program via CGI on Apache. The program is supposed to connect to some site, download something and then returns it to user (normal port-80 request, nothing fishy).

The problem is, that the CGI programs returns Permission denied on socket_open command.

Other simpler CGI programs that do not require network connectivity work fine and this program works just as well when invoked from command line, so I suspected some permissions issue and since setting a setuid on the executable didn't resolve a problem, I came to a conclusion that it is something that SELinux has control over.

I have never really worked with SELinux, but getsebool -a | grep httpd returns

allow_httpd_anon_write --> off
allow_httpd_mod_auth_ntlm_winbind --> off
allow_httpd_mod_auth_pam --> off
allow_httpd_sys_script_anon_write --> off
httpd_builtin_scripting --> on
httpd_can_check_spam --> off
httpd_can_network_connect --> off
httpd_can_network_connect_cobbler --> off
httpd_can_network_connect_db --> off
httpd_can_network_memcache --> off
httpd_can_network_relay --> off
httpd_can_sendmail --> off
httpd_dbus_avahi --> on
httpd_enable_cgi --> on
httpd_enable_ftp_server --> off
httpd_enable_homedirs --> off
httpd_execmem --> off
httpd_read_user_content --> off
httpd_setrlimit --> off
httpd_ssi_exec --> off
httpd_tmp_exec --> off
httpd_tty_comm --> on
httpd_unified --> on
httpd_use_cifs --> off
httpd_use_gpg --> off
httpd_use_nfs --> off

I suspect that httpd_can_network_connect --> off is the problematic one here, but this is a permision for the httpd, not the actual executable. Are SELinux permissions inherited from parent process? How would I set it to be enabled for the script only and not for the whole httpd? Or is there a whole different problem and not a SELinux related one?

Thank you for help.

Edit: I tried setenforce 0 and the script is working then, so it is a SELinux thing.

Edit 2: ausearch -ts recent -m avc returns

time->Thu May  3 23:52:29 2012
type=SYSCALL msg=audit(1336081949.221:18563): arch=c000003e syscall=42 success=no exit=-13 a0=8 a1=7fff21161cb0 a2=10 a3=7fff21161a30 items=0 ppid=6813 pid=6814 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm=".stutsk" exe="/var/www/html/stutsk-cgi/.stutsk" subj=system_u:system_r:httpd_sys_script_t:s0 key=(null)
type=AVC msg=audit(1336081949.221:18563): avc:  denied  { name_connect } for  pid=6814 comm=".stutsk" dest=80 scontext=system_u:system_r:httpd_sys_script_t:s0 tcontext=system_u:object_r:http_port_t:s0 tclass=tcp_socket
  • 1
    As a starting point: a) Prove you have a SELinux problem by setting SELinux to permissive (`echo 0 >/selinux/enforce`) and retest. b) Check your audit log for denied errors (auditd needs to be running) c) use `audit2allow -a -w` (from the `policycoreutils-python` package) to generate the necessary rules based on your audit log. – cyberx86 May 03 '12 at 01:25
  • 1
    If your running the cgi script from a cgi-bin directory then I am pretty certain that the script does a domain transition of its own into httpd_cgi_script_t (I believe). Can you re-run the script and produce the output of "ausearch -ts recent -m avc" – Matthew Ife May 03 '12 at 20:53
  • This is probably true. See my edit. –  May 03 '12 at 21:53

2 Answers2

0

Are SELinux permissions inherited from parent process?

Yes, unless a rule causes a transition to a new domain.

How would I set it to be enabled for the script only and not for the whole httpd?

You'd need to create a new domain that allows network access, and write a rule that causes a domain transition when the script interpreter is invoked. Note that this will cause any script invoked by this interpreter when invoked by httpd to follow this transition; it is much less trivial to cause a script-specific domain transition.

Ignacio Vazquez-Abrams
  • 45,939
  • 6
  • 79
  • 84
0

Personally, would have reservations of permitting CGI processing being able to fetch stuff from the network (just makes me feel uncomfortable) but you can enable this with the following policy:

policy_module(localhttpd_script_t, 1.0.0)

gen_require(`
        type httpd_sys_script_t;
        type http_port_t;
')

gen_tunable(`httpd_script_can_http_connect', `false')

tunable_policy(`httpd_script_can_http_connect', `
        allow httpd_sys_script_t self:tcp_socket rw_socket_perms;
        corenet_tcp_connect_http_port(httpd_sys_script_t)
        corenet_tcp_sendrecv_http_port(httpd_sys_script_t)
')

You'll need to install the policycoreutils-python stuff if its not done already.

To make this, run

make -f /usr/share/selinux/devel/Makefile load

This will compile and install the module. I compiled on Fedora 15, but I dont think theres any special policy thats unique to that system.

To turn this on (temporarily) run the command setsebool httpd_script_can_http_connect 1 and to make permanent setsebool -P httpd_script_can_http_connect 1 .

Matthew Ife
  • 23,357
  • 3
  • 55
  • 72
  • I don't think that CGI that has access to the network is something special. It needs to connect to the database server, for example. Anyway, thank you for your answer! –  May 04 '12 at 20:00