On the website ctfchallenge.com, the definition of this challenge is as follows
VulnTraining provide training services to their clients but they could do with some training themselves, security training that is!
CTF level: hard.
Number of flags: 11
Main website: www.vulntraining.co.uk
Screenshot:
Here, we add anything we find of value incrementally during our walk through.
- billing.vulntraining.co.uk found from subdomain discovery in step 2
- c867fc3a.vulntraining.co.uk found from subdomain discovery in step 2
- billing.vulntraining.co.uk/login -> found from subdomain discovery in step 2
- billing.vulntraining.co.uk/?api=test -> found from parameter discovery in step 14
- www.vulntraining.co.uk/
- www.vulntraining.co.uk/git/HEAD -> found from content discovery in step 5
- www.vulntraining.co.uk/.git/config -> found from content discovery in step 5
- www.vulntraining.co.uk/.git/index -> found from content discovery in step 5
- www.vulntraining.co.uk/framework -> found from content discovery in step 5
- www.vulntraining.co.uk/robots.txt -> found from content discovery in step 5
- www.vulntraining.co.uk/server/ -> found from content discovery in step 5
- www.vulntraining.co.uk/server/login -> was directed to it through a location header
- vulntraining.co.uk/php-my-s3cret-admin -> found from endpoint 7
- admin.vulntraining.co.uk/ -> found after subdomain discovery in step 12
- admin.vulntraining.co.uk/admin
- admin.vulntraining.co.uk/admin/users
- admin.vulntraining.co.uk/invoices
- admin.vulntraining.co.uk/admin
- Database creds:
vulntraining:#x7QE1Jg&cNO
- Billing account creds:
dominic.bryant:987654321
- We usually start by surfing the website but in the case of this website it is really simple, just the home page and not a single link other than it.
- So we do some subdomain discovery by
- Using dnsrecon:
dnsrecon -d vulntraining.co.uk -D ~/wordlists/subdomains.txt -t brt
but 0 records found - Searching on crt.sh we found
- Using dnsrecon:
- Had a quick look at each one of these subdomains. Found that
- We can start by entering any data in username and password fields to see how the website reacts with it and it showed the error message
Username is invalid
So we can enumerate usernames- Username enumeration using ffuf:
ffuf -w ~/wordlists/usernames.txt -X POST -d "username=FUZZ&password=werwe" -t 1 -p 0.1 -H "Cookie: ctfchallenge=$ctfchallenge_cookie" -H "Content-Type: application/x-www-form-urlencoded" -u http://billing.vulntraining.co.uk/login -mc all -fr "Username is invalid"
but no username in this list is valid so we have to find usernames in another way
- Username enumeration using ffuf:
- We try discovering any hidden endpoint in
www.vulntraining.co.uk
by bruteforcing it with ffuf:ffuf -w ~/wordlists/content.txt -t 1 -p 0.1 -H "Cookie: ctfchallenge=$ctfchallenge_cookie" -u http://www.vulntraining.co.uk/FUZZ -mc all -fc 404
and found.git
files and some endpoints- We start with the simplest
robots.txt
endpoint and we find that it has a disallowed directory that when accessed showed flag 2 Found Flag 2 - Then we try accessing this
/server
endpoint that shows302 status code
which is a relocation, but is showed a snapshot of the server status! Found Flag 4 - We go and visit the admin site of MySQL
http://vulntraining.co.uk/php-my-s3cret-admin
to see what it has and it has a PHPMyAdmin panel! - Tried entering a random username and password to see if we can bruteforce usernames, but it shows a general error message ->
Invalid username and password combination
- We start with the simplest
- Going back to the
.git
files we found, I accessed.git/config
file and found that it had a remote git repository!- We visited this remote repo and found that it is the framework used in the main website and it was private but they had open it to the public Found Flag 6
- Looking at the commits, it has a commit with a message
Removed database creds now we're making this project open source
! We found database credentialsvulntraining:#x7QE1Jg&cNO
!
- Going back to the PHPMyAdmin page we found earlier in step 5.3, we try found credentials and it works
- We access this
vulntraining
database and we findbilling_users
table that has a user with a probably hashed password! Found Flag 7 - This password seems to be hashed but not showing completely, so we can bruteforce with the username we got,
dominic.bryant
by ffuf:ffuf -w ~/wordlists/passwords.txt -X POST -d "username=dominic.bryant&password=FUZZ" -t 2 -p 0.1 -H "Cookie: ctfchallenge=$ctfchallenge_cookie" -H "Content-Type: application/x-www-form-urlencoded" -u http://billing.vulntraining.co.uk/login -mc all -fr "Password is invalid"
- Voila! We found the password which is
987654321
- We access this
- While reviewing the requests in Burp Proxy history (a step I do often every now and then during the pentesting process), I found that the main website
www.vulntraining.co.uk
has a flag in its response in the HTML<meta>
tag! Found Flag 5 - We now login in the
billing.vulntraining.co.uk/login
forum with the credentialsdominic.bryant:987654321
Found Flag 8- We find that every Id is a hyperlink to an invoice, so I tried different Ids like
billing.vulntraining.co.uk/10
but it showed a404 status code
- So maybe we can do content discovery using ffuf but found nothing other than the Ids of the 4 invoices and the
/login
and/logout
endpoints but only sat thetoken
cookie withdeleted
- Tried content discovery on
billing.vulntraining.co.uk/1/FUZZ
but nothing appeared
- We find that every Id is a hyperlink to an invoice, so I tried different Ids like
- I went back to surfing the original domain and found that it has
style.css
file underhttp://www.vulntraining.co.uk/css
so I went to look for the content of this file and found a hidden asset! - We try doing content discovery on
http://www.vulntraining.co.uk/server/
using ffuf but only the/login
endpoint appeared! - I went back for doing some subdomain discovery on
vulntraining.co.uk
because maybe I have missed something and as I hoped, we foundadmin.vulntraining.co.uk
subdomain - We try with this
admin.vulntraining.co.uk
subdomain and it is an API that shows a responseUnauthorized
! So we can do content discovery - We go back to
billing.vulntraining.co.uk
, it shows a comment in HTML sayingAPI Response Time 0
, so we know for sure that this is an api. But from step 9.1 we know that it has no endpoints other than that of/1
,/2
,/3
,/4
, so can we do parameter discovery? and found a parameter showing500 status code
which indicates an internal server error. This seems interesting- We see what kind of error it shows, so I tried setting this
api
get parameter totest
and it only showedAPI Error
message! - Tried multiple values for this
api
parameter likeapi=internal
,api=external
and such but nothing worked - Tried parameter bruteforcing on
http://admin.vulntraining.co.uk/admin/?FUZZ=test
but nothing happened - Tried content discovery on
http://admin.vulntraining.co.uk/admin/users/FUZZ
and it showed that any integer that follows/users/
such as/users/10001
would give a401 Status Code
response - Tried writing a URL in that api parameter and it shows the original pages of
billing.vulntraining.co.uk
whenapi=admin.vulntraining.co.uk
and showsAPI Error
whenapi=billing.vulntraining.co.uk
- This indicates that
billing.vulntraining.co.uk
communicates withadmin.vulntraining.co.uk
, so maybe we can see how this communication works by generating a burp collaborator link and see if its response shows. YAAAAYYY! we find a flag and a token (probably the admin token) Found Flag 9
- We see what kind of error it shows, so I tried setting this
- Tried this X-Token HTTP header to see if this authorizes the request to the api
http://admin.vulntraining.co.uk/
and it worked!- From step 13.1, we know that
admin.vulntraining.co.uk
has/admin/users/
endpoint so we must try it. Unfortunately, it shows that user does not have the permission - We can try
/admin/users/1
for example hoping that this api has Broken Function Level Authorization vulnerability, and it actually has! - We then do bruteforcing on this
/admin/users/{id}
endpoint to enumerate user ids using Burp Intruder and we found the admin user to haveid=5
andusername=jon.helmstead
! Found Flag 10 - We try accessing this
/admin
endpoint with the newapikey
we found and see what appears. We find a secret endpoint - We access this secret endpoint but it only redirected my to another endpoint with no value
- Tried changing this
id
parameter but it only showedMessage is deleted
whenid=1
andMessage not found
when I changed theid
to any other value
- From step 13.1, we know that
- Tried to login with
jon.helmstead
tohttp://billing.vulntraining.co.uk/login
but it says thatUsername is invalid
so this user is not onbilling
subdomain - Then I bruteforce the password of
jon.helmstead
username (with the large passwords file) in thehttp://www.vulntrainging.co.uk/server/login
, but found no password matching - I tried SQLi with this
id
parameter thinking that this message withid=1
might have a flagdeleted=1
, so I wrote in the query/admin/s3cr3t_m3ss4g3s/?id=1%20AND%20deleted%3d1
and it showed the same response as/admin/s3cr3t_m3ss4g3s/?id=1
so I think it is vulnerable to SQL injection- This may be because in the backend code, it checks whether the retrieved message from the database has the deleted column with 1, then it will show to the user
Message is deleted
message - This is a Blind SQLi! So how can we exploit this? I tried testing the message with
id=2
because I know its content, and then from Wappalyzer I found that the website uses PHP so most probably it will use MySQL as a DBMS - Tested the
substring
function with MySQL syntax and it worked properly - Tried retrieving the id of the second message to test the query inside the
substring
function, but for some reason it did not work. Maybe there's no table calledmessages
- I remembered that when I tried the
deleted
column it worked directly in the query without anyselect
, so this means that this request parameter is appended directly into the SQL query. This means if I tried a value ofid=2%20and%20substring(message,1,1)%3d'H'
it should return200 OK
and this is what really happened - Does this mean I can bruteforce the content of the message that has
id=1
? But we have a problem. We cannot know the length of the message so I started by assuming that this message is of length 10 characters and I configured my Burp Intruder to check on each character, if the character is true, the response will has a423 Locked
status and will return the messageMessage is deleted
- Configured Burp Intruder to flag each response that has
deleted
in its body, and this way, we can bruteforce each character the message consists of - But during the attack, I found that first that 4th and 6th character is not found which means that my character set
[a-z0-9]
is not sufficient. I have to add some special characters and try again - I added the special characters and found out that the 4th and 6th characters still don't appear because they are
space
s. - Continued the bruteforcing process until I interpolated a big part of the message which says
don t share this message with anyone! [^flag^9dd08...]
Found Flag 11
- This may be because in the backend code, it checks whether the retrieved message from the database has the deleted column with 1, then it will show to the user
- With this, we have successfully found all the flags!