Jail the remote (SSH) terminal path too, not just local
Deploy Ladill Hosting / deploy (push) Successful in 33s
Deploy Ladill Hosting / deploy (push) Successful in 33s
Accounts whose node has an ssh_private_key take the remote branch, which still launched an unjailed 'runuser' shell — leaving the breach open. Route it through the same jailkit launcher (no sudo; provider connects as root). Now every terminal session is chrooted to the customer's own home. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
2a1228b40e
commit
18d1e735d8
@@ -143,7 +143,10 @@ class RunHostingTerminalWorkerCommand extends Command
|
||||
throw new \RuntimeException('Unable to establish an SSH connection for the browser terminal.');
|
||||
}
|
||||
|
||||
$remoteCommand = "runuser -u {$account->username} -- bash -lc ".escapeshellarg($launchCommand);
|
||||
// SECURITY: jail the remote shell too. provider->connect() logs in as
|
||||
// root, so the launcher runs without sudo and chroots the customer into
|
||||
// the node's jail (only their own home visible) — never an unjailed shell.
|
||||
$remoteCommand = $this->buildJailedLaunchCommand($account, $relativePath, false);
|
||||
|
||||
return new RemoteSshShellSession($ssh, $remoteCommand, $cols, $rows);
|
||||
}
|
||||
@@ -156,17 +159,21 @@ class RunHostingTerminalWorkerCommand extends Command
|
||||
* /etc, secrets). Invoked via sudo -n, scoped in /etc/sudoers.d/ladill-jailsh
|
||||
* because the terminal worker runs as www-data.
|
||||
*/
|
||||
private function buildJailedLaunchCommand(HostingAccount $account, string $relativePath): string
|
||||
private function buildJailedLaunchCommand(HostingAccount $account, string $relativePath, bool $sudo = true): string
|
||||
{
|
||||
$launcher = (string) config('hosting.terminal_jail_launcher', '/usr/local/sbin/ladill-jailsh');
|
||||
$rel = $relativePath !== '' ? $relativePath : '/public_html';
|
||||
|
||||
return implode(' ', [
|
||||
'sudo', '-n',
|
||||
escapeshellarg($launcher),
|
||||
escapeshellarg($account->username),
|
||||
escapeshellarg($rel),
|
||||
]);
|
||||
$parts = [];
|
||||
if ($sudo) {
|
||||
$parts[] = 'sudo';
|
||||
$parts[] = '-n';
|
||||
}
|
||||
$parts[] = escapeshellarg($launcher);
|
||||
$parts[] = escapeshellarg($account->username);
|
||||
$parts[] = escapeshellarg($rel);
|
||||
|
||||
return implode(' ', $parts);
|
||||
}
|
||||
|
||||
private function buildUserShellBootstrap(HostingAccount $account, string $relativePath, int $cols, int $rows): string
|
||||
|
||||
Reference in New Issue
Block a user