Pi-hole Remote Code Execution
natedotred.wordpress.com
natedotred.wordpress.com
While I agree this should be fixed. This is a pretty low issue
Although this requires you to authenticate at the web portal, so 'some' sort of trust is necessary to gain this level of access. I believe they even have some plan of letting authenticated users update the pi-hole code from the web interface by the wording on this issue: https://discourse.pi-hole.net/t/how-do-i-update-pi-hole/249.
A funny thought: you can create a script (that uses the default password) to inject a code to schedule an update to the pi-hole (and revert the changed permissions) which fixes the vulnerability and leaves no trace! These possibilities reminds me of a hacker series!
The existing code is analogous to building SQL queries using string concatenation and forgetting the mysqli_real_escape_string() call. Really the solution is to use a parameterized interface (e.g. by calling pcntl_fork() + pcntl_exec(), that accepts an array of arguments instead of a string command-line).
Pcntl doesn't seem to have a wrapper for the posix_spawn syscall.
The pcntl_exec function is the only one that has a reasonable interface, but is way too low level.
php should simply accept this as a valid function call:
exec(["sudo", "pihole", "-a", "addstaticdhcp", $mac, $ip, $hostname]);exec("sudo pihole -a addstaticdhcp ".$mac." ".$ip." ".$hostname);
and/or
exec("sudo pihole -a removestaticdhcp ".$mac);
So three places to audit:
1) Regexp's and related complex high-level functions;
2) Calls to exec()
3) Uses of sudo within an exec()
Instead php should have an interface that accepts:
exec(["sudo", "pihole", "-a", "addstaticdhcp", $mac, $ip, $hostname]);
without any shell trickery.If there's a sudo in this specific like doesn't matter, your reverse shell is going to run as a regular user and after that it only matters low locked down the sudoers configuration is.
You can even implement a "safe" exec function like so:
function safe_exec(array $args, array &$output = null, int &$return_var = 0) : string {
return exec(
implode(' ',
array_map('escapeshellarg', $args)
), $output, $return_var
);
}
// Example usage
$output = [];
$return_var = 0;
echo safe_exec(['ls', '/tmp'], $output, $return_var);
var_export($output);
echo "Exit code: $return_var\n";
[1] https://www.php.net/manual/en/function.escapeshellarg.phpWow, this is always a mistake and a huge one. exec() is dangerous, exec calling with sudo more so, and should never be used in conjunction with unprivileged user input like this. Granted a weak attempt was made to sanitize the user string, but so weak one might wonder if it is Underhanded Code at play here.
The big problem with this sort of issue is that it indicates that there almost certainly are massive security problems elsewhere in this code base since this one is low hanging fruit that never should have made it past even rudimentary code review by anyone with a bare minimum knowledge of security.
On to the response. First, doing something I don't want to do that someone else told me to do and not getting paid for it is slavery. Slavery is bad.
Second, I don't use their solution. I have my own custom DNS intercept system I wrote myself which is much better and also enjoys security by obscurity. With a single user it's hardly worth the time to mess with.
Third, I already donated to their project, above. I reviewed their code, agreed it was complete shit, and concurred with the consensus that they need a complete security audit. That is extremely valuable advice which is worth $3000. So I donated $3000 and all you've done is sit and whine and create anonymous coward accounts to troll people. Tsk.
If somebody prompts you to do something on the internet do you give it any concern? You must be swimming in free iPhone X's then. He suggested you donate time to an open source project which is about as equivalent to slavery as a cashier at Burger King trying to upsell you a large whopper menu.
You've donated absolutely nothing to the project by commenting here if you didn't provide the feedback directly via the projects public tools.
I actively contribute to many open source projects. Writing a shell script to generate dnsmasq hosts files isn't exactly rocket science. It doesn't matter if you don't use the project, lesser informed people do, by improving it you improve a large amount of people's security. Call it virtual herd immunity, it affects you too indirectly.
Mind you they trusted a regex that looks pretty sane (A preg_replace might of been better)
Probably difficult to exploit that way without first finding another bug to retrieve that token from a random origin.
Specifically, "simple requests" do not, covered here[1]. This case is POST, with a Content-Type of application/x-www-form-urlencoded. (The rule of thumb you can use is that these were all essentially possible to send prior to CORS even existing. To send a POST, you would construct a form tag with the inputs filled in with the desired values, set the target URL to the "victim" site, and have JS submit the form.)
[1]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simpl...
Say hi to J from me.