I work for a company, which offers penetration tests as one of our core services. And like any company, we are constantly looking for new people to hire, either for fixed positions, or for internships. As you can imagine, requirements for internships are more lenient, but we do require people to have a basic grasp of penetration testing. People should know what “XSS” means and not think we mistyped CSS.

So as part of the hiring process, we do a quick hacking challenge with people. If you’ve ever done a Hack the Box challenge, then you know how that works. You get some web application and a theme like “XSS” or “Open Redirect” and you have to find and exploit the vulnerability. It’s all pretty standard. Some people will breeze through it in a few minutes, which tells us they have a really solid understanding of penetration testing; while others need a little longer or pursue a path that is ultimately unsuccessful.

In either case, what we really care about is your thought process! In person, we’d ask you to narrate what you’re doing. Something like

So at first, I’m just going to inject <script>alert(1)</script> as the most basic payload I can think of, just to see how the system will react. I’m not expecting that to actually work, because that would be a bit too easy. So right now, I see that I get alert(1) returned. So that tells me that script tags are filtered out. Next, I’ll try <b>test</b> to see if maybe the script tag specifically is excluded. And no, I get test returned. So that tells me that even “benign” tags like <b> are filtered out. Next I’ll try <foobar>test</foobar> to see if all tags, even non-existant ones are filtered. If not, that might indicate that there is some sort of whitelist. Okay, that returns test as well. […]

That’s how things are supposed to look like. Even if you may not find the vulnerability, showing how you approach an application can give valuable insight into your skill as a pentester. We can judge pretty well if you would have found the vulnerability sooner or later, if your approach is promising enough.


…not all our candidates are like this. Some approach the issue, by opening up some XSS payload list, and then blindly copying and pasting into whatever input field they see, until some alert box pops up (or not). What does that tell me about your approach? What does that tell me about your understanding of the application? You’re basically a script, running through some wordlist and sending data to a server; you’re giving the term “script kiddie” a whole new meaning by becoming the script.

However, we don’t want to hire /bin/bash, we want to hire a person, who understands what they are doing. And what upsets me the most is that this is how some people approach training tools like Hack the Box: They just blindly copy payloads until something pops up and they say “Wooo, hackerman!”. What do you learn from this? Nothing. You learn fuck all from it.

You see, I used to be active on Information Security, and I’d regularly see questions like “Can someone help me with this box?”. The question would look something like this:

Hi I’ve been trying this hack the box challenge (https://…) and I really don’t know what I’m supposed to do. Can you tell me how to solve it?

What is the point to it? Even if I or anyone else told you what the solution was, what would you gain from it? You can mark it as solved, but you didn’t solve it - someone else solved it for you.

A Better Path

You’re not a script, kiddie! Instead of blindly copy/pasting in payloads or running some “autopwn” script, you should try for yourself and see how far you get. Write down what you tried, why you tried it, what you had hoped would happen, and what you can tell from the result. And if it worked, explain why it worked. Throw away “automatic” tools like sqlmap, because you don’t learn anything from using those.

And if you get stuck, now is the time to ask questions. Show what you tried, what worked, what didn’t, why you believe this is the right approach and specifically, what you think is holding you back.

I’ve been trying this HTB challenge (https://…) and judging by the title, it’s supposed to be a SQL Injection challenge. After poking around a little, I found out the the following URL is injectable: .../profile/<payload>. So I imagine, that the underlying query will be something like SELECT * from profile where id = <input>. So I tried injecting 27+OR+1=1, but it just shows me the profile with ID 27. That at least confirms that I can inject something, because it still interprets “OR 1=1”. When I run 27+OR+1=2, I get an error that the profile was not found.

To try and get some interesting data, I tried a UNION SELECT, like follows: 27+UNION+SELECT+Password+from+Users but it just prints the profile for user 27. What am I missing here?

Can you imagine what’s missing here? Well, you aren’t seeing the code in the background, so it’a bit of a mean question. Let me show you the query that is run:

SELECT Username, ProfileDesc, AvatarPath FROM Users WHERE ID = <input> LIMIT 1

And the right payload to inject would be:

133333333337 UNION SELECT Username, Password, AvatarPath from Users LIMIT 0, 1 -- 

What does that do? The user ID is a non-existant user ID. It allows us to ensure that the original SELECT does not return any data at all. The UNION SELECT basically “replaces” the original select completely. We keep the username to see who it belongs to. We replace the profile description with the password, so that instead of a “bio”, we get the password (or the hash) and for AvatarPath, we keep the same as before, because there really isn’t much else to do. The LIMIT is where it gets tricky. We can only get one user at a time, so the LIMIT 1 from before was working as intended (and the reason that our hypothetical question asker still got shown the profile for user 27, even if OR 1=1 was injected later). However, we want to iterate through the result set, so we use the LIMIT X, Y syntax. This means that we skip the first X elements and then limit to Y elements. In order to get data for other users, we increase X to iterate all users through the database, until we get an error, that no profile was found. In this case, we skipped more entries than the result set contained. Even if you replace 133333333337 with 27, you can just change it to skip the first entry and you get the same thing.

In this case, you actually learn from the experience. Even if someone may have to give you a nudge towards the final answer, you still learn a lot by trying. Your next step should be to play around with UNION SELECTS to really grok them. So here’s a little challenge:

Say you only have one column, into which you can inject data. How can you get data from multiple columns into that one result column?

In Short

Stop relying on “payload lists”!

Stop relying on “autopwn” scripts!

Understand what you are doing and don’t blindly follow someone else’s tutorial. If you don’t understand why something works, ask! There are countless places to ask professionals and most of them will be delighted to explain the details of something to anyone who is interested.

Understand the theory how and exploit works and learn to exploit it on your own!

Git gud!