TyphoonCon 2021 Impasse
Table of Contents
Description: When I was doing a pentest on a given target, I found this page. I think it’s vulnerable, but I’m not good at PHP, are you?
Difficulty: Easy
Recon⌗
When you visit the site for the challenge it brings you to a page titled “Printer”, with an input bar and a checkbox for a debug option.
When I enter input and submit the form, it runs an HTTP GET request with echo '{my-input}'
as the value for the print
parameter. The value seems to be executed as PHP code, since the page displays “hello” afterwards.
This can be confirmed by looking at the JavaScript echoit
function, which is called upon submitting the form:
function echoit(){
var userVal=document.getElementById('userVal').value;
document.getElementById('userVal').value = "echo '"+userVal+"';";
}
Finally, with the debug option checked, the page invokes the PHP highlight_file(__FILE__);
function, which displays the index.php file source code with syntax highlighting.
Finding A Vulnerability⌗
The part of the source code I’m interested in is at the very top. It’s code designed to check user input for blocked strings and then eval
the input if it passes.
error_reporting(0);
if (isset($_GET['print'])) {
if (!empty($_GET['print'])){
$printValue= strtolower($_GET['print']);
$blocked = array("cat", "more" ,"readfile", "fopen", "file_get_contents", "file", "SplFileObject" );
$special_block= "nc";
$$special_block= "../flag.txt";
foreach ($blocked as $value) {
if (strpos($printValue, $value) || preg_match('/\bsystem|\bexec|\bbin2hex|\bassert|\bpassthru|\bshell_exec|\bescapeshellcmd| \bescapeshellarg|\bpcntl_exec|\busort|\bpopen|\bflag\.txt|\bspecial_block|\brequire|\bscandir|\binclude|\bhex2bin|\$[a-zA-Z]|[#!%^&*_+=\-,\.:`|<>?~\\\\]/i', $printValue)) {
$printValue="";
echo "<script>alert('Bad character/word ditected!');</script>";
break;
}
}
eval($printValue . ";");
}
}
I saw that the usual suspects for PHP command execution, such as system
, exec
, passthru
, etc. are blocked via the preg_match
function. I tried several methods of bypassing this, but it seems well written to me. Even if I was able to bypass this check, commands such as cat
, more
, etc. and the flag file itself are blocked strings.
This got me thinking - I have one GET parameter that is being filtered, but what other user input am I able to send to the server that is not being filtered? When I look at the request in Burp Suite, it becomes more clear.
I have lots of additional headers in the HTTP request that, to my knowledge, are not being used. After a quick search, I found the PHP function getallheaders()
which does just that - gets an array of all the HTTP headers. But that alone isn’t very useful. When I combine it with echo implode(getallheaders())
I can see some immediate results:
Command Execution⌗
Now that I know I can include arbitrary unfiltered input, I can change the echo
to an eval
and use the system
command in a new header to gain command execution:
When I run cat ../flag.txt
with the above command execution, I’m able to read the flag: S3D{M4y_Bl0ck3d_Array_B3_Y0ur_F1rst_W4y}
.