0xl4ugh CTF : Micro

Context

We are given the address to a website, the source code that website and also we have access to the admin:admin credentials.

Writeup

Looking at the source code, we see that checks if the username parameters contains the word admin through the Check_Admin function. Then if there is a match, it checks through $_SERVER['REMOTE_ADDR']!=="127.0.0.1" if it originates from localhost.

        if(Check_Admin($username) && $_SERVER['REMOTE_ADDR']!=="127.0.0.1")
        {
            die("Admin Login allowed from localhost only : )");
        }
        else
        {
            send_to_api(file_get_contents("php://input"));
        }   
function Check_Admin($input)
{
    $input=iconv('UTF-8', 'US-ASCII//TRANSLIT', $input);   // Just to Normalize the string to UTF-8
    if(preg_match("/admin/i",$input))
    {
        return true;
    }
    else
    {
        return false;
    }
}

Then if it passes all the checks it is sent to a Flask API where the username and password will be checked. We cannot bypass _SERVER['REMOTE_ADDR'], it is a deadend. However, we could potentially bypass the regex in a way that makes the username not match the regex but still be interepreted as 'admin' when it reaches the API. However, I've learned the hardway that this is a deadend.

What we could potentially exploit is the fact that it is using Flask and PHP as they could behave differently. And it does, I found out that when we pass a parameter twice (eg. username=abc&username=test), PHP will get the second occurence of username and Flask will get the first.

So we bypass the regex by using this payload :

username=admin&username=test&password=admin&login-submit=

And voila ! We get our flag :