Bobby // Tg-hack2020 CTF:
We observe couple of things:- /login - Cool login site
- /password - Cool password change area
- /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:
- 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).
- There’s probably no injection in other params as they are part of prepared templated sqli syntax (“?” indicates that).
- 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.
Cool.
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:
"21db9a2aef143c4e8e3863fce29d0b35d7dbdcec18f3e8d13abdf12e78e2e3e9d713e2b4c9ab682c
6ba1a472284b37f3257a05b7ffce2542c98e4199127b0822"
6ba1a472284b37f3257a05b7ffce2542c98e4199127b0822"
Now let’s try to connect with this one and viola we got the
flag mi hijo:
TG20{bobby_knows_his_sql}
Miscs:
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 sqlmap.py
I have also tried to automate my bf searches for the username with sqlmap.py 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 sqlmap.py -u https://bobby.tghack.no/password -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 sqlmap.py 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:
Post a Comment