Solution for executing root commands as unprivileged user – sudo 'ing script – easily opens possibility of security breach and unexpected behavior and results (this is also true for any other solution such as binary wrapper with setuid
);
It's clear that scripts added using visudo, like this
www-data ALL=(ALL) NOPASSWD: /usr/local/sbin/mycommand
- should be readable, writable and executable only by root – which is both owner and group (
chown root:root mycommand; chmod 700 mycommand
) - should have its parent directory ownership
root:root
with755
mode - should validate input – arguments and stdin – and reject and abort execution upon any invalid/unexpected data provided
- should use absolute instead of relative paths / aliases (?)
Defaults env_reset
in/etc/sudoers
should be set (?help needed here)
What else can be done to secure a sudo-powered script?
Best Answer
I'd amend your list of criteria for protecting a script a little. Given this - or a similar - entry in
/etc/sudoers
:we can state that the script:
PATH
before using any external commandslogger
)Additionally, in many cases there is no real need for a script to run as root - it can run setgid, or even setuid to some other account. In the general case consider these options to avoid granting full root access to the script.
For SELinux environments it may be possible to create a policy that prevents the script from doing anything unexpected. Capabilities such as CAP_NET_ADMIN are more finely grained than blanket root privileges and might also be worth considering.
In the specific case you've outlined, where you want to validate a single IPv4 address and pass it to
iptables
, you might be able to get away with validating the IP address as a series of non-specific octets. In this case 444.555.666.999 might be accepted as plausible, knowing thatiptables
itself will reject anything that isn't a real IP address. At one extreme you might decide that matching the RE/^[0-9.]+$/
is enough to be happy passing the value toiptables
. At the other, well there are plenty of answers on StackExchange and in other places that address the issue of validating an IP address. Some better than others.Special cases to consider are RFC1918 addresses, multicast addresses, and your own external IP address range. Oh, and the reserved block formerly known as Class E. Do you need IPv6 support?
What will happen if your script is called hundreds of times a minute? Do you need to prepare for this eventuality? Will your
iptables
chain overflow? If you think you're going to need hundreds of rules in your chain it will be [more efficient to use theipset
extension toiptables
rather than a linear list. Here's a good tutorial. In terms of protection, it allows you to build sets of thousands (if not tens of thousands) of similar rules that can run without significantly slowing the traffic flowing through your rulesets.Suddenly your apparently straightforward requirement is quite complex.