Throwing the kitchen sink at web application vulnerabilities
I started chasing a goal of mine to find an XSS vulnerability in the wild by putting together a Python notebook that could maybe assist me on the journey. You can read a little about it here:
As I learnt more on the topic, I realized there isn’t a simple, strict methodology to finding an XSS vulnerability and my notebook felt too rigid and linear to be useful. I also ran in to the OWASP Testing Guide and I feel like I’ve found the perfect road map to become a pretty competent bug bounty-er, if such a name exists.
For all these reasons, I needed something more modular where I can pick and choose functionality based off my current understanding of a website and adapt quickly to new findings. Or as per my original plan, to simply make a tool I can use to throw a kitchen sink at in desperation of finding a weakness somewhere.
This project will be something I iterate over as I’m doing CTF challenges, learning about particular vulnerabilities and adapting it to match and cover the OWASP Testing Guide. You can find the GitHub here: https://github.com/Jacob-CL/The-Kitchen-Sink.git
As of April 2024, Ive ‘codified’ as much of 4.1.* as I can from the OWASP Testing Guide which covers ‘Information Gathering’. Meaning that the tool can now do many things, starting with static source code analysis. Here it’ll scour a page searching for keywords from a series of specific text files. Keywords that might giveaway evidence of databases, HTML comments, HTML meta tags, HTML input tags, JavaScript tags, and evidence of front-end filtering.
An example command to do a page source static analysis:
python TKS.py -u [URL] -static
A snippet of an example output:
Next, it can enumerate a root domain / directory walk with the command by appending potentially revealing paths to the original URL provided:
python TKS.py -u [URL] -dw
It’ll return the response code of each, where a valid URL is a response code less than 400:
The kitchen sink tool can also banner grab, it will send both normal and malformed requests to the provided URL in the hope to fingerprint the web server or application. Normal GET request:
Malformed GET request in case something like the web server is obfuscated in the normal response code: (Not the case here but you get the point)
It’ll port scan a URL with either a list of common ports or if you really want to throw the kitchen sink, the first 1024. Here is an example using this command for a common port scan:
python tks.py -u [IP ADDRESS] -ps
And the resulting output:
Finally, you wouldn’t be throwing the kitchen sink if you didn’t do all of this, all at once with a simple ‘ — throw’ argument appended to your command. Doing so will do all of the above all at once, although at the moment, it breaks a lot because some of my functions expect IP addresses whilst other prefer not etc. This kind of error handling is definitely on my to do list!
For CTF specific web applications —
You’re often given a web application’s relevant files to build it yourself with Docker — to quickly find useful points of interest I’ve built a ‘grep’ like functionality where it’ll recursively iterate through each folder and file looking for a series of strings defined in ‘CTFPatterns.txt’.
The command needed to grep through a directory looking for CTF relevant strings is:
python TKS.py -g [DIRECTORY]
To demonstrate this, I’ve used the ‘SpookTastic’ challenge from HackTheBox’s Halloween CTF event and here are the results:
Here you can easily and quickly see that the app.py file might have some kind of blacklisting logic in it alongside mentions of a MongoDB. Most interestingly, bot.html has a ‘| safe’ string suggesting unvalidated and unfiltered HTML input is trusted and allowed.
As it turns out, the web app takes any input thanks to the ‘| safe’ filter (meaning it’ll trust any string) but it’s passed to a blacklist function that will deny the input if it contains a string with ‘script’. So essentially, solving the challenge is to use an XSS payload that doesn’t include the word ‘script’.
I’ve also now added the functionality to dynamically look for interactable input (as defined by Selenium) count it, and submit to see the response I get back.
If I use the SpookTastic challenge as my guinea pig again, the vulnerable input field doesn’t appear and become ‘interactable’ until you scroll to the very bottom. Therefore I had to make it so the script scrolls to the bottom of the page, and then try to submit the input. Not a bad habit at all in the quest for completeness.
I also found simply pressing the ENTER key after copying the payload (with Selenium in the Firefox browser) doesn’t actually trigger the alert textbox either, it seems to just refresh the page unless. For that, I had to add logic to try look for a button to press in the parent form or just press the ENTER key.
Happily, the code was able to open a browser, scroll to the bottom (making the input interactable), enter the string, and then find the button to press to get the alert to pop:
Ultimately, I want to follow the OWASP Testing Guide and write my own tooling to adapt to what I learn, to point me in the right direction as to where I should be looking rather than auto solve challenges like above. The ‘Information Gathering’ methods codified and outlined above cover almost all that’s needed in 4.1.* and be might be all the help I need in finding a vulnerability. The plan is to keep the tool flexible and adaptable to as many situations as possible. Stay tuned for more.