Sunday, April 12, 2020

Bobby // Tg-hack2020 CTF:

We observe couple of things:

  1. /login - Cool login site
  2. /password - Cool password change area
  3. /style – defines website style
When one first sees the challenge name (“bobby” little tables 😉) and the site – let’s try sql-injection it’ won’t we?
After trying injecting anywhere – we finally sees some syntax sqli error when we go to /password and write new password value with incorrect things..

We can see for example, that if we place there ‘’’’ We will get:
unrecognized token: "''''''''''' WHERE user=? AND pass=?"
That’s really cool, it means couple of things:

  1. We’re probably in update / set sql command injection (it at least seems like that because we try update specific user password with these specific user/password details).
  2. There’s probably no injection in other params as they are part of prepared templated sqli syntax (“?” indicates that).
  3. Fields from some table (users tables probably or something?) is ‘user’ and ‘pass’.
Let’s first fix our query to somehow kinda validate injection.
I tried putting various comments styles / ending to remove the statement end: “--” or “#’ or “;”. But finally what seems to be working (seems to be as well kinda mysql style) was “/*”
 I tried to put this one: ‘ or ‘1’=’1’/* and got this:
sql: expected 0 arguments, got 2
Ok, this is really good because it means we kinda fixed the first syntax error we’ve made and influenced for a new one. So why we see now this error? Well, good question.
So, remember we commented out the rest of the statement, the statement is still being binded into 2 other args we give to it (remember these “?” we’ve seen before). Cool, let’s fix that:

I have put now ‘ or ?=?/* and also placed the same values for user/pass which I give as an input (so that this equality of ?=? will become true):
Password changed!
Oh yes!!! Did we made?
Well… not quite yet just a sec…

What is the username? Oops…
So I’ve tried: “admin”/”user”/”administrator”/cookie id kinda.
Ok so it’s a little harder than that.

Let’s try to explore our DB then, shall we?
Ok, let’s try get sqli version?
Putting any of: version() / @@version / version  - didn’t work unfortunately.. weird.. the server just returns back that these methods aren’t recognized.

Stack that up:

Let’s try now to stack some query and search for table names.
My next newish string was: “1' where "A"=(select "A" from TABLE_NAME) and ?=?/*” and we got:
no such table: TABLE_NAME
Cool, so it’s a good primitive to find table names (If we get password changed – then according to this table exists kinda). Let’s look for them. So let’s try some good old-fashioned information_schema.tables or even sys.tables: “”
no such table: information_schema.tables
damnnnn… so no schema… what can we do then? I’ve tried put “users” – oh well and it works 😊
Not suprising that much because – remember – we probably have it’s fields back from first stage.

La bobby table?

Ok, let’s try extract username first, change it’s password to ours and connect with the login in the previous menu, right? Right right, cool cool.

Other functions?

I’ve tried look for functions that available to me as well. No EVAL/LEFT/CHAR_LENGTH. To know which functions available we just try and see if we get some error back from them, but to inspect their usage, totally another thing.
How to inspect some functions functionallity? Remember our feedback is if we succeeded changing password or not.

So we can put something like:
a' where ‘ser’=(select SUBSTR(‘user’, 2) from users) and ?=?/*

And just wait to see if password get’s to change successfully or not.

INSTR to the rescue:

I’ve found that instr works quite as expected. This function search specific char/string in other string and returns the index in which this string starts in another one.

Because we know already that users table is a valid one and exists we will focus on it.
Let’s try now find char by char of that username we will change the password for:
password\' where 1=(select INSTR(user, "{KNOWN_SUBSTRING} + 
NEW_BRUTEFORCE_CHAR") from users where INSTR(user, "{KNOWN_SUBSTRING}")=1 
or "{KNOWN_SUBSTRING}"="") and ?=?/*

KNOWN_SUBSTRING will be the chars we already know.
What are we doing here? Every time we try to find the next char, we call this NEW_BRUTEFORCE_CHAR.

Every time we found it is the next char in the user-name – we add it up to KNOWN_SUBSTRING.
Remember that our way to know if this is kinda valid char is that we check response for “Password changed!” string – which means sql statements was made successfully.
We also need to consider that this level restarts every 8 minutes. So we need to restart our session as well. We also need to automate this of-course and not do this by hand cause username and number of chars to validate can be also long right?

Cool. Running that and observing the result was given to us as the username:
Now let’s try to connect with this one and viola we got the flag mi hijo:


Unicode SQLi charsets bruteforcing:

As there was the /style reference for css-style and a utf-8 support - i've thought probably in the begining that there's maybe other charsets we needed to bruteforce on. so when cool thing i kinda observed is how to generate charsets for other utf ranges. I've used data in /style area and downloaded all the .woff2 files which usually compressed with brotli. to open these i've used fonttools in python3. it worked perfectly towards generating charsets to try bruteforcing over. fortunately In the end it was kinda un-needed.

Finding SQL injections with

I have also tried to automate my bf searches for the username with which is a really cool tool. It can also be provided with cookie/headers and post params to try bf/inject sql statements over.
Unfortunately and probably because some tables we're kinda missing it didnt worked perfectly and need to be worked alot more probably to be perfectly working as it was probably using only specific techniques and maybe not the relevant for our cases over here.
Nonetheless, This was one of the main commands i have tried:
python -u -a --method POST -p new_pass --cookie "id=5e8ecd02xa3796b6e545debad2c51c4e13298ce70e756013a6505326ae55a364dfd38ece2ba9de568bd90a97a53805022790661fdfffd6f22bbd52aadf1b0c5965d548027x0f9090fa8d3d4547821fa5feac5d1db8f872667f68b94c6026ddb5ba9b407b88" --data "user=asdas&old_pass=asdsadasdsad&new_pass=dsadasdsa%27%28" --level 5

the -p selects the parameter that the will try inject upon.
the -a tries all / verious methods. level 5 seems to be (at least by the manual) searching for more deeper ways to exploit/inject data kinda.
the --data is our form kinda data in that format.

No comments:

Hitcon 2021' CTF - Vulpixelize

Vulpixelize Writeup In this challenge – we are given docker webserver with the following files: 1.       Dockerfile 2.       Simple Flask we...