Insp3ct0r
Goal: a small site whose own How section boasts that it was made with HTML, CSS and JavaScript. That list is the map.
Approach
Section titled “Approach”View the page source. The first third is sitting in a comment buried in the markup for the How tab, and the head declares the site’s own stylesheet and script.
<!-- Html is neat. Anyways have 1/3 of the flag: picoCTF{tru3_d3 -->
<link rel="stylesheet" type="text/css" href="mycss.css"><script type="application/javascript" src="myjs.js"></script>Both paths are relative, so they resolve against the page’s own address, and in the browser’s source view they are clickable. Follow each and read to the bottom.
/* You need CSS to make pretty pages. Here's part 2/3 of the flag: t3ct1ve_0r_ju5t *//* Javascript sure is neat. Anyways part 3/3 of the flag: _lucky?832b0699} */Three fragments, fifteen characters, fifteen characters, sixteen. Concatenated in order they close their own braces.
picoCTF{tru3_d3t3ct1ve_0r_ju5t_lucky?832b0699} The eight characters before the brace belong to the deployment rather than to the puzzle, and separate builds of it close on separate tails. jupiter.challenges.picoctf.org no longer resolves, so a reader following along today is served a different deployment and gets whatever tail was built into it.
Why it works
Section titled “Why it works”Nothing here is hidden, it is only unrendered. A comment survives parsing and sits in the document as a node the renderer simply never paints, and a stylesheet is applied rather than displayed. Only the first third is in the page itself, and the other two arrived as separate requests the head told the browser to make, so reading a page and reading its sources are different acts.
The two attributes are worth separating while they are side by side, because they are not interchangeable. href gives the address of a resource the document is related to, and the browser decides what to do with it from the element and its rel, which for a stylesheet means fetch and apply. src gives the address of a resource that is fetched and embedded, effectively becoming the element’s content, which is why a script uses it and a link does not. Both leave a trail in the source, and following that trail is the entire solve.