Bagel
Gaining Access
Nmap scan:
$ nmap -p- --min-rate 5000 10.129.150.229
Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-19 23:21 EST
Nmap scan report for 10.129.150.229
Host is up (0.17s latency).
Not shown: 65327 closed tcp ports (conn-refused), 205 filtered tcp ports (no-response)
PORT STATE SERVICE
22/tcp open ssh
5000/tcp open upnp
8000/tcp open http-altAdded bagel.htb to the /etc/hosts file. Running a detailed scan shows that port 8000 ws a Werkzeug server. Nothing else was revealed.
$ sudo nmap -p 22,5000,8000 -sC -sV -O -T4 10.129.150.229
...
8000/tcp open http-alt Werkzeug/2.2.2 Python/3.10.9
|_http-server-header: Werkzeug/2.2.2 Python/3.10.9
|_http-title: Did not follow redirect to http://bagel.htb:8000/?page=index.htmlBagel Shop LFI
Port 8000 hosted a web application selling bagels.

The interesting parameter here was the URL, which was http://bagel.htb/?page=index.html. LFI works here and I can view the /etc/passwd file.
The users are phil and developer. There's an orders page with the previous orders made.
Not too sure what to make of the orders, but at least we have an LFI. gobuster revealed no other directories of interest. Since we have no other information of the file system in the machine, we can view the /proc/self/cmdline file to view the processes that are running.

Now we can download the source code and begin enumerating possible vulnerabilities.
Source Code Reviews
Here's the code for the application:
So there's a DLL file somewhere that is used to read orders from an orders.txt file. Websockets are used to connect to port 5000. We should find this DLL file, but I don't know where to look as of now. Instead, we can try writing a script to connect to this WebSocket and abuse it somehow as it does not seem to take any user input.
I tested this by changing ReadOrder to WriteOrder and creating this script here to connect:
When viewing the /orders page again, we see that I have successfully overwritten everything there.
The exploit has to do with how user input is not sanitised and the json.dumps function. Some type of deserialization exploit related to the DLL needs to be used here.
I decided to brute force the PIDs that were running on this machine, and I managed to find the DLL.
Now, I can download the DLL file and port it over to Windows for analysis with DnSpy. When opened, we find the code for 3 Order functions, 1 ReadFile function and the deserialize function I found.
TypeNameHandling = 4 means this:
Include the .NET type name when the type of the object being serialized is not the same as its declared type. Note that this doesn't include the root serialized object by default. To include the root object's type name in JSON you must specify a root type object with SerializeObject(Object, Type, JsonSerializerSettings) or Serialize(JsonWriter, Object, Type).
https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_TypeNameHandling.htm
I also found some credentials here:

From the 3 main functions, it seems that ReadOrder does check for LFI, so that's not exploitable. WriteOrder does not seem to do much, but RemoveOrder is suspiciously short and does nothing. For our JSON deserialisation exploit, perhaps we should use this as the main function for exploitataion. We know from the main function of the DLL that the code always deserializes the input we give it no matter what.
Deserialization
We know that this is a .NET related JSON deserialisation exploit based on the DLL. This resource was particularly helpful in creating the payload:
For our payload, we would first need to add the the 'RemoveOrder' function, then nest our payload within it. Since the TypeNameHandling = 4, the $type variable has to call the root object's type, in this case it would be bagel_server.file,bagel as per the DLL object names.
Afterwards, we can call the ReadFile function to read whatever file we want.
This was my code and output: (took a while of testing)

This works! Now, we can attempt to read the user flag and the private SSH key of the user phil.

Then we can SSH in as phil.

Privilege Escalation
Developer Shell
With the credentials we found within the DLL file, we can su to become the developer user.

Sudo Dotnet
As the developer user, we can run /usr/bin/dotnet as the root user.

Since we can run this, we can simply run dotnet fsi, which would open up an interactive interpreter we can use to make /bin/bash a SUID binary.
Then, either in the same shell or another, we can run /bin/bash -p to become root.

Rooted!