Category: web - Points: 50
The address in the description points to a login form. The page also provides us the PHP code behind the login form:
Each time the php is run a new array
$database is created storing the passwords of the two users:
Admin0. However, the password are composed by 31337 random characters, which makes the login page impossible to bruteforce or guess. If the password does not match, the password for the user
Layer7 is printed, but since it will be regenerated the next time, this information is useless.
Next we noted that the username is validated using the
filter function, allowing only usernames which satisfy the following regex:
Admin0 do not satisfy the regular expression, they are not even usable in the login form, so we have to look for something else.
$username is not in the
$database[$username] returns a
NULL value. Moreover, this value is compared to the
$password using the PHP loose comparison (PHP uses loose comparison with
!=, while it uses strict comparison with
The PHP loose comparison operator has a really strange behavior. This is its truth table:
The highlighted row is used when one of the two operands is
NULL. Since we want the result to be true, we need the password to be either
"". So we can just provide an empty password and the comparison should be verified, giving the flag in return.
We have to provide an username which verifies the
filter function (such as
Aa0) and an empty password, which is different from not providing the
password field at all (otherwise the
isset would return false and the message
Input Password would be displayed). We can use different tools to POST the needed data to the webpage. The easiest way is to use
wget -qO- http://prob.layer7.kr/login/index.php --post-data='username=Aa0&password='
This gives the following output:
<form method=post><input type=text name=username><input type=password name=password><input type=submit value=Login></form><br>Message : flag is a52a12ec82efd713433b16aea3f32cae!
So the flag is:
How to improve the code?
The problem here is that loose comparison tries to compare different types. The code could be improved using strict comparison, which has the following truth table:
Since we have no way to pass a
NULL parameter through a form, that would have prevented the exploit.