How to run setuid task properly

iptablespermissionssetuid

Assuming there is a php website and I want to block an ip at the firewall level based on the site code execution. The site is run under non-root user.

I was going to pass IP from the site code to a script (writeable to root only) like

#!/bin/bash
function validate_ip()
{ ... code here ...}
if validate_ip $1; then 
    /usr/sbin/iptables -I INPUT -s $1 -j DROP
    echo 'blocked'; 
else 
    echo 'bad IP $1'; 
fi

using suid bit. I want to add additional IP validation to avoid XSS and other bad things (consider it paranoia if you like), so do not want to allow the site to call iptables directly.

The script does not work can't initialize iptables table 'filter': Permission denied (you must be root) because bash drops suid bit

There is workaround: allow iptables in sudo but I don't think it's secure. I have no time/possibility to develop/buy a binary which will do the task. One suggested binary wrapper around script but I hesitate, perhaps there is a better way?

So, the question is: how can I allow non-root app to block ip in iptables firewall in a secure way?

Best Answer

Instead of making your bash script suid root, run your bash script through sudo. As a side benefit, this also lets you easily lock down who can run your script as root and also the arguments passed. You could, for example, only allow:

phpuser ALL=(root) NOPASSWD: /usr/local/sbin/your-script [0-9][0-9][0-9].[0-9][0-9][0-9].[0-9][0-9][0-9].[0-9][0-9][0-9]

then make sure your PHP script always formats each IP address octet as three digits.

If it's too hard to have PHP call sudo (which it shouldn't be!) you can have the script do it itself, with something like:

#!/bin/sh

[ "$(id -u)" -eq 0 ] || exec sudo -- "$0" "$@"
# rest of script here

(I'm not entirely sure iptables will be happy with the leading 0s, if not you can strip them off).

PS: Please quote your variables in your shell script:

if validate_ip "$1"; then 
    /usr/sbin/iptables -I INPUT -s "$1" -j DROP
    # ⋮
Related Question