Skip to main content

Client-side-again picoCTF 2019 Solution

Recover a password hidden inside obfuscated client-side JavaScript running in the browser.

Published: April 2, 2026Updated: July 22, 2026

Description

Try to find the password again. Check the HTML source.

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1
    View the page source
    Observation
    I noticed the challenge description explicitly says 'Check the HTML source,' which suggested the password validation logic, including the correct password, is embedded in a client-side script tag that can be read directly by viewing the raw page source.
    Open the challenge URL and view source (Ctrl+U). Find the JavaScript that validates the password. The logic will be obfuscated - variables may have random names and strings may be split into pieces.
    What didn't work first

    Tried: Opening DevTools and looking at the Elements panel instead of View Source.

    The Elements panel shows the live DOM after JavaScript has already run, which can differ from the original source. Inline script tags may appear collapsed or reformatted. Ctrl+U (View Source) gives you the raw server-delivered HTML, which is what you want when hunting for the embedded validation script.

    Tried: Looking only at the visible page content for the password, rather than the JS.

    Client-side validation challenges embed the comparison logic inside a script tag, not in any visible element. The password will not appear in the page text - it is buried inside JavaScript string operations that only show up when you read the source.

    Learn more

    Client-side password validation is fundamentally insecure because the browser must have the complete validation logic (including the correct password) to check your input. Obfuscation only adds friction, not real security.

    Common obfuscation techniques include: splitting strings into parts and joining them, using character codes instead of string literals, renaming variables to meaningless names, and reversing strings.

  2. Step 2
    Deobfuscate the JavaScript
    Observation
    I noticed the validation script used a lookup function (such as _0x4b5b) with numeric indices and substring position checks rather than plain string comparisons, which suggested the password was assembled from encoded fragments that needed to be resolved individually in the browser console before they could be read.
    Paste the obfuscated JavaScript into an online beautifier (like beautifier.io) or use browser DevTools. Trace the string operations - look for concatenation, split, reverse, join, or charAt calls that reconstruct the password.
    What didn't work first

    Tried: Trying to read the obfuscated code top-to-bottom without evaluating subexpressions first.

    Obfuscated JS uses lookup tables (functions like _0x4b5b) where each call returns a string fragment. Tracing the full logic mentally without resolving those lookups first leads to confusion. Instead, paste the lookup function and its arguments into the browser console to decode each fragment individually, then trace the assembly.

    Tried: Running a generic JS deobfuscator tool and expecting a clean, readable password to appear.

    Automated deobfuscators reformat control flow and rename variables, but they rarely evaluate runtime expressions. The password fragments are still encoded inside array entries or function return values. You still need to manually evaluate the validation expression in the console after beautifying.

    Learn more

    A useful trick: open the browser console and type the name of any variable you see in the obfuscated JS. The console will show you its current value. You can also call the validation function directly with test values to observe its behavior.

    If the password is assembled from parts (e.g., var a = 'pic'; var b = 'oCTF';), just concatenate them mentally. Check for array operations too - sometimes the flag is stored as a reversed or shuffled array of characters.

    In client-side-again specifically, the obfuscation uses a lookup function (e.g. _0x4b5b) that maps numeric indices to string fragments, and validates the password through overlapping substring() position checks rather than plain concatenation. Evaluate the lookup function in the browser console to decode each argument, then assemble the substrings in positional order.

  3. Step 3
    Extract the flag from the JS
    Observation
    I noticed the deobfuscated expressions resolved to several string fragments that, when assembled in the order the validation equality check used them, formed a complete picoCTF{...} flag, which suggested manually or console-evaluating the final assembled expression to produce the submittable answer.
    Once you understand the string operations, manually execute them (in your head, on paper, or in the browser console) to reconstruct the final password/flag string.
    What didn't work first

    Tried: Submitting the reconstructed string without the picoCTF{} wrapper.

    The validation script may check only the inner portion of the flag (the part between the braces), and concatenate the picoCTF{} wrapper separately in the source. If you only extract the inner value, the submission will fail. Look for any string in the JS that assembles the full picoCTF{...} format.

    Tried: Concatenating the string fragments in the order they appear in the source file rather than the order the code assembles them.

    Obfuscated scripts often define string pieces out of sequence and then assemble them using index references or array positioning. Reading top-to-bottom gives the wrong order. Evaluate the final expression the validation function uses (often an equality check against a constructed string) in the console to get the correctly ordered result.

    Learn more

    The flag will either be in the standard picoCTF format directly, or it will be the input that passes the validation check. If the JS checks your input against a transformed version, reverse the transformation.

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.
  • Regex TesterTest regular expressions against a string with live match highlighting, flag toggles, and common CTF pattern shortcuts.

Flag

Reveal flag

picoCTF{not_this_again_...}

The flag is assembled from split string parts in the JavaScript source - concatenate them in the correct order.

Key takeaway

Client-side validation is not security; it is a UI convenience. Any secret used to validate input in the browser must be shipped to the browser, making it recoverable by anyone who reads the source or uses developer tools. Obfuscation raises the cost of extraction by seconds, not meaningfully. The same principle applies to license-key checks in desktop apps, mobile apps, and any compiled binary where the comparison value must reach the process doing the comparison.

Related reading

Want more picoCTF 2019 writeups?

Useful tools for Web Exploitation

What to try next