2

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?

4

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
    # ⋮
  • I tried username ALL=(root) NOPASSWD: /usr/local...., then switched to user's shell and tried sudo /usr/local/script 1.1.1.1 but sudo asked for password here. What am I doing wrong? – Putnik Sep 22 '17 at 13:12
  • @Putnik with the example I gave, you have to pad all the numbers 001.001.001.001 – derobert Sep 22 '17 at 13:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.