I'm running the following code from within php
$ipAddress=$_SERVER['REMOTE_ADDR'];
$mac = `arp -an |grep $ipAddress | awk '{print $4}'`;
$c = "sudo iptables -t mangle -I internet 1 -m mac --mac-source $mac -j RETURN";
shell_exec($c);
after it, output of
#iptables -L -v -t mangle
pkts bytes target prot opt in out source destination
215 18676 all -- * * 0.0.0.0/0 0.0.0.0/0 MAC D0:17:C2:48:1E:4F
26 1717 RETURN udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53
0 0 RETURN tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:53
340 26189 MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MARK set 0x63
note that there is no RETURN in the target
If I run the same command from bash shell as sudo, the output is
$ sudo iptables -t mangle -I internet -m mac --mac-source D0:17:C2:48:1E:4F -j RETURN
pkts bytes target prot opt in out source destination
0 0 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0 MAC D0:17:C2:48:1E:4F
0 0 RETURN udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53
0 0 RETURN tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:53
0 0 MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MARK set 0x63
Observe that there is a RETURN in the target
I have modified sudoers with visudo to enable php to run the said command as root
I also tried system(), exec and using backtick operator in php. But, all is the same.
I could not understand why this happens and a remedy to it.
The string assigned to $mac
ends with a newline characters, thus breaking the iptables
command. Removing the newline, for example by using explode
instead of awk
, should fix this:
$ipArp = `arp -an | grep $ipAddress`;
$mac = explode(' ', $ipArp)[3];
I'd like to add that this kind of script scares me a little. Blindly passing values to a shell command can have very bad consequences. I don't think this particular script is exploitable, but giving sudo permissions to PHP is not a good idea from a security point of view.