๐ Micro CMS v2
A detailed write-up of the Web challenge 'Micro CMS v2' from Hacker101 CTF
๐ Challenge Overview
Category Details Additional Info ๐ Event Hacker101 CTF Event Link ๐ฐ Category Web ๐ ๐ Points 9 Out of 9 total โญ Difficulty ๐ก Medium Personal Rating: 4/10 ๐ค Author Unknown Profile ๐ฎ Solves (At the time of flag submission) Unknown solve rate ๐ Date 04-03-2025 Hacker101 CTF ๐ฆพ Solved By mH4ck3r0n3 Team:
๐ฏ Challenge Files & Infrastructure
Provided Files
1Files: None
๐ Initial Analysis
First Steps
Initially, the website appears as follows:
This is version 2 of the challenge Micro-CMS v1. By clicking on the
Micro-CMS Changelogpage, we are shown what has been changed fromversion 1:It seems that an authentication system has been introduced for creating and editing pages. In fact, when I try to click on
Edit this pageorCreate a new page, I am redirected to/login:It can therefore be assumed that there is an
SQL Injectionvulnerability that allows us to access account notes already present in thedb. In fact, when trying to submit a'in theusernamefield, I get anInternal Server Error:This suggests that the query sanitization is not properly handled, and the parameters are directly passed into the query. To understand what type of
SQL Injectionis involved, the first thing to analyze is whether unique errors are returned for theusernameor just for thepassword. So, I submitusername=admin&password=adminto see what is returned:It seems that, as we can see, it returns
Unknown user, which is a unique error for theusername(to avoid Error Based SQL Injection, generic errors should always be used, such asusername or password ...to prevent revealing useful information). This means we could try anError Based Blind SQL Injectionto enumerate theusernameand later thepasswordto access the page. There will probably also be a way to perform aTime Based Blind SQL Injection. These two types of injections use linear brute force to enumerate and dump the database. Anoraclequery is used, which functions as a real oracle that we can ask questions. Let’s take theError Basedas an example. In this case, we ask the oracle, “Is the first letter of the username perhaps ‘a’?” The oracle responds “yes,” so we ask our next question: “Is the second letter of the username ‘a’?” and so on, until we can compose the entire username. We will use the unique error messageUnknown userfor this technique. For each request, we will check if the response contains that error until we successfully guess the entire username, eventually getting a different error, likewrong password. The same technique is applied forTime Based, but instead of using visible errors, it uses the response time. The query payload is built in such a way that it inserts a delay, likeSLEEP(5);. This way, each time we guess a letter,SLEEP(5);will execute, and we will know itโs the correct letter by calculating the response time. If it’s approximately5 seconds, we can move on to guessing the next letter. Letโs move on to the exploitation phase.
๐ฌ Vulnerability Analysis
Potential Vulnerabilities
- Error Based Blind SQL Injection
- IDOR
๐ฏ Solution Path
Exploitation Steps
Initial setup
Building an oracle for a
Blind SQL Injectioncan be quite a hassle since you have to try and retry until you find the correct payload. Therefore, I used SqlMap since there are no rules prohibiting the use of automated tools. The first thing I did was launch SqlMap:
1sqlmap "https://b23aa3c6ccd56e4c43848255ee6bbf51.ctf.hacker101.com/login" --dump -data "username=&password=" --risk 3 --level 5 --threads 8Specifying the
usernameandpasswordfields, SqlMap also identified aTime Based Injectionand built the following oracle from the output:Once this was done, sqlmap started dumping the database. I stopped its execution with
CTRL+Csince sqlmap uses a session saving system, creating files so that it resumes from where it left off in the next run. Here is the resulting log:
1cat /home/mh4ck3r0n3/.local/share/sqlmap/output/b23aa3c6ccd56e4c43848255ee6bbf51.ctf.hacker101.com/logLet’s move on to the next phase.
Exploitation
As we can see from the log, a
dbcalledlevel2and a tablepageswithin it were found. However, I still wanted to investigate further by dumping all thedbby specifying the flag--dbs:
1sqlmap "https://b23aa3c6ccd56e4c43848255ee6bbf51.ctf.hacker101.com/login" -data "username=&password=" --risk 3 --level 5 --threads 8 --dbsNothing interesting, the only database that doesn’t seem to be default is
level2. From the previous output, I also found another table,admins, giving a total of two tables inlevel2, namelyadminsandpages. I assume thatadminscontains the users andpagescontains the created pages. So, I performed the dump of the tables one by one:
1sqlmap "https://b23aa3c6ccd56e4c43848255ee6bbf51.ctf.hacker101.com/login" --dump -data "username=&password=" --risk 3 --level 5 --threads 8 -T adminsAs we can see, inside the
adminstable, there was only one user withusername=donald&password=jannet. After trying to log in with this user, I obtained the first flag.Subsequently, since we are only told that authentication has been added, I assume that the vulnerabilities from the previous challenge are still present. So, I ran the same script for enumerating the pages that I had written for the previous challenge ( enum_pages.py):
It seems that there is another page which is not visible, namely page number
3. To avoid wasting time, I performed the dump of thepagestable, specifying--where="id=3", so that it wouldn’t dump the first two pages:
1sqlmap "https://b23aa3c6ccd56e4c43848255ee6bbf51.ctf.hacker101.com/login" --dump -data "username=&password=" --risk 3 --level 5 --threads 8 -T pages --where="id=3"With this, I was able to obtain the second flag, which was apparently hidden in page
3in the database (screenshot in theFlag Capturesection). Reading through the write-ups at the end of the resolution, it was also possible to access usingusername=' UNION SELECT '123' AS password FROM admins WHERE '1' = '1&password=123.I caught the last flag almost by accident… always thinking about a possible
IDOR, I noticed that by changing the page path from/page/1to/page/edit/1(just like in the previous challenge), I was redirected to/login. But then I thought, what if I accessed it using aPOSTinstead of aGET? Since in the previous challenge, thePOSTmethod was used to modify thetitleandbodyof the page. So, I made the request withcurl:
1curl -X POST https://b23aa3c6ccd56e4c43848255ee6bbf51.ctf.hacker101.com/page/edit/1By doing so, I obtained the third and final flag.
Flag capture
๐ ๏ธ Exploitation Process
Approach
The automatic exploit for the second flag uses the method found in the write-up I read after solving the challenge, although I also mentioned my own method, and it seems to work. For the remaining two flags, I made a
POSTrequest to/page/edit/1for the third flag, and accessed with the credentials extracted from the blind error-based injection for the first, extracting it from the response text using a regex.
๐ฉ Flag Capture
Flag 1Flag 2Flag 3
Proof of Execution
๐ง Tools Used
Tool Purpose Python Exploit SQLMap SQL Injection Testing
๐ก Key Learnings
Time Optimization
- Move step by step with SQLMap, for example, first enumerate the
dbs, then once you have the information, move on to dumping a specific table that you’re interested in, and so on…- Directly use a
request.txtfile for sqlmap, as you can copy, for example, the/loginrequest and use it directly to set upsqlmap.
Skills Improved
- Binary Exploitation
- Reverse Engineering
- Web Exploitation
- Cryptography
- Forensics
- OSINT
- Miscellaneous
๐ References & Resources
Learning Resources
๐ Final Statistics
| Metric | Value | Notes |
|---|---|---|
| Time to Solve | 00:40 | From start to flag |
| Global Ranking (At the time of flag submission) | Challenge ranking | |
| Points Earned | 9 | Team contribution |
Created: 04-03-2025 โข Last Modified: 04-03-2025 *Author: mH4ck3r0n3 โข Team: *