Description
The Local Authority portal hides its credentials inside ancillary JavaScript. Browse the secondary login file to enumerate referenced assets and recover the cleartext username/password pair.
Setup
View the page source; it references a POST to login.php even though that file isn't linked anywhere.
Manually browse to /login.php to load the script includes, then inspect secure.js for hard-coded credentials.
Return to the original page and sign in with the recovered username/password to reach admin.php.
Solution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1Enumerate hidden assets
ObservationThe main page's form action points at login.php, though nothing links to that file. Navigate to it directly and its own script includes load, revealing further assets such as secure.js.Open login.php directly (e.g., http://saturn.picoctf.net:<PORT_FROM_INSTANCE>/login.php). The browser now lists secure.js among the sources.What didn't work first
Tried: Right-clicking the main page and selecting 'View Page Source' to look for hidden files.
View Source shows the raw HTML of the main page, which does reveal the login.php form action while loading none of that page's own script includes. Navigate the browser to login.php so it makes a fresh request and parses those script tags, which pulls in secure.js.
Tried: Checking the Network tab in DevTools on the main page to find secure.js.
The Network tab only records requests made while it is open on the current page, and secure.js is loaded solely by login.php, so it never appears until you go there. Open DevTools first, then navigate, and watch the tab fill in.
Learn more
Asset enumeration is the process of discovering resources on a web server that aren't explicitly linked from the main page. Common techniques include reading the page source for referenced URLs, checking
robots.txtandsitemap.xml, and using directory brute-forcing tools like gobuster or dirsearch to probe for common filenames.Here, the form action attribute in the main page's HTML points to
login.php, which is enough of a breadcrumb. Manually navigating to that URL loads it in the browser, which in turn causes the browser to request all scripts and stylesheets referenced bylogin.php- includingsecure.js. This is a reliable way to discover secondary resources: follow every link, form action, and script reference you find.In real web application testing, this reconnaissance phase is critical. Tools like Burp Suite's Spider, OWASP ZAP's crawler, or
wget --mirrorcan automate the discovery of linked resources across an entire site.Step 2Read secure.js
Observationlogin.php loads a file called secure.js. Between that name and the challenge's theme of client-side credential storage, it is the obvious place to find a hardcoded username and password.secure.js contains a validation function that checksusername === 'admin'andpassword === 'strongPassword098765'(or declares them as constants). Use these credentials on the main login form.What didn't work first
Tried: Looking for credentials in the Console tab by typing 'password' or 'username' to search for variables.
The Console shows logged output and evaluates expressions; it will not list declared variables unless you already know their names. Open the Sources tab, or the Network tab's response preview, and read secure.js in full. With the names in hand, the Console can confirm their values.
Tried: Trying common passwords like 'admin', 'password', or '123456' on the login form before checking the JS file.
Guessing credentials is unreliable and slow - there are thousands of common passwords. The challenge explicitly stores the password in a JavaScript file served to the browser. Reading secure.js gives you the exact string in seconds without any guessing.
Learn more
Storing credentials in client-side JavaScript is a severe security vulnerability. The entire purpose of authentication is to distinguish authorized users from unauthorized ones - but if the password is in the JavaScript file that every visitor's browser downloads, any visitor can read it. This type of vulnerability is so common that browsers' built-in developer tools are sufficient to exploit it: no specialized tools required.
A "secure" filename for a JavaScript file containing cleartext credentials is ironic, but this naming pattern (trying to obscure the purpose through the filename) is a form of security through obscurity - it provides no actual protection. The real fix is to perform authentication server-side: the server compares submitted credentials against a hashed value in a database, and the client never sees the reference value.
This pattern also illustrates why Single Page Applications (SPAs) that implement authentication logic in JavaScript are inherently limited: you can gate the UI, but you can never gate the data if the same JavaScript file is accessible to all users.
Step 3Retrieve the flag
Observationsecure.js exposes the exact plaintext credentials the server-side check uses. Submit them on the portal's login form, which posts to login.php, and the login succeeds, redirecting to admin.php where the flag is displayed.Successful authentication redirects to admin.php, which prints the picoCTF flag in plain text. Once you're inside, probe sibling routes -/admin.php,/debug.php,/users.php,/settings.php- to see what other surfaces the same auth check unlocked. Real-world admin panels almost always expose more than the one page you're sent to.What didn't work first
Tried: Pasting the credentials straight out of the JavaScript with their surrounding quotes, as
'admin'and'strongPassword098765'.The quotes in secure.js are string delimiters, not part of the values, so submitting them sends four extra characters and the comparison fails. Type the contents only: admin and strongPassword098765.
Learn more
Once you have the credentials from
secure.js, logging in is straightforward. The server-side authentication check validates the submitted credentials and, if they match, grants access to the admin page. Even though the validation happens server-side, the credentials were exposed client-side - making the server-side check irrelevant from a security standpoint.This challenge models a real attack pattern: credential harvesting from client-side code. Security researchers regularly find API keys, database passwords, and auth tokens embedded in JavaScript bundles shipped to browsers. Tools like truffleHog and gitleaks scan codebases for such accidental exposures, and browser extensions like DotGit look for exposed
.gitdirectories that might reveal source code and embedded secrets. The post Web challenges: real-world bug patterns collects the rest of this family - hidden form fields, JS-side auth checks, exposed admin routes.
Interactive tools
- Strings ExtractorPull printable text from any binary, library, or image. ASCII and UTF-16 detection, configurable minimum length, flag-like highlight, no command line needed.
Flag
Reveal flag
picoCTF{j5_15_7r4n5p4r3n7_b0c...}
Because the credentials live in front-end JavaScript, simply browsing to the referenced file is enough.