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.

index

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.

input

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.

burp

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:

headers

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:

cmd

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}.