Boston key party 2015 - Schoolbus (levels 1 to 6)


Here is the solution to the 6 php challenges. Each of them consisted of a page with a form (password with or without name), as well as the php source of the page. The goal was to bypass php comparison to get it to print the flag.

Prudential - Level 1

I dont think that sha1 is broken. Prove me wrong.


In this challenge we need to bypass two tests to get the flag. First, the page checks that our name is not the same as our password. We could easily pass that test by giving two diferrent values, but then the second test (both the name and the password have the same hash) would fail. Since I'm not aware of any sha1 collision, I looked for a way to make that test fail while giving the same value in both field. A loose comparison is used to compare the name and the password, and we can see in the php type-comparison table that a loose comparison between two arrays is TRUE. Since we can make name and password as arrays by modifying the URL, we go to:

52.10.107.64:8001/?name[]=toto&password[]=tata

And that was enough to get the key. This is because the php sha1 function seems to fail when given an array as an input and returns null for both name and password.

Symphony - Level 2

A less than four characters number, bigger than 999?Maybe the bug is elsewhere.


Maybe the easiest of those challenges. We need to give numeric password less than 4 characters but whose value is larger than 999. Using powers of ten allowed us to give a large number with very few characters, and get the key:

52.10.107.64:8002/?password=1e3

Northeastern Univ - Level 3

Of course, a timing attack might be the answer, but Im quite sure that you can do better than that.


Here, php is expecting the flag itself as an input. Fortunately, it compares our input with the flag using both strcmp and a loose comparison. We can learn on the documentation of strcmp that the comparison between an array and a string returns NULL, which should allow us to get through that loose comparison. We can get the key by accessing:

52.10.107.64:8003/?password[]=toto

Museum Of Fine Arts - Level 4

Because cryptography is hard, we only implemented a hand-made PRNG. What could possibly go wrong?


This time, there is a puzzle to solve to get to the flag. When the page is generated, 4 random numbers are generated as well, the first three are printed, and the fourth is the password we have to guess. I was intrigued by the session_start() at the beginning of the php code, which I had never seen, not being a big php coder. Looking at the documentation, I learnt that it allowed to keep data between php pages, so I understood that was how the password was kept from one page to the other. The session id is sent through a cookie, and indeed I had the following cookie:

PHPSESSID=jq3nlh151p538eg2lkp73k61l3

However, I noticed that while the page checks if the $_GET['password'] is set, it never does it for the $_SESSION['password'], so what if we have an invalid session? I changed my cookie to a session ID I knew would not correspond to anything:

PHPSESSID=jq3nlh151p538eg2lkp73k61l3

And removed any value for password:

52.10.107.64:8004/?password=

That made the password compare to an empty variable, and gave me the key. It was later pointed out by a friend that seed used in the mt_srand function could only have 20000 values or so (because of the %rand(1,10000) + rand(1,10000), so another solution to this challenge would have been to generate all possible problems, generate the page, find the current problem in the previously generated list and solve the problem maybe the way the author was expecting.

Longwood Medical - Level 5

Because we dont trust mysqli_real_escape_string, we wrote our own military-grade sanitization method.


In this challenge, name and password are checked if valid by verifying if they are in the user database. Not being very familiar with SQL, I checked the usual unexpected parameters:

52.10.107.64:8005/?name=&password=
52.10.107.64:8005/?name[]=toto&password[]=tata
52.10.107.64:8005/?name=0&password=0

Luckily, that last test gave me the key. I think it is because the SQL request doesn't put quotes around the name and password values, but not being sure of anything I prefer not to give any explaination rather than giving a wrong one.

Brigham Circle - Level 6

Sanitization is hard, lets use regexp!


This final challenge is very similar to the first one, we have to bypass two comparisons that contradict each other. The first checks that the password is alphanumeric using a regular expression, and the second checks that the password contains the substring "--". By looking at the documentation for ereg, we can see that if an error occured, it will return FALSE, which would let us bypass the first comparison. Similarly, an invalid input to the strpos function returns NULL, which strictly doesn't compare to FALSE. So we can try to give an invalid input as an array using:

52.10.107.64:8006/?password[]=toto

To get the flag. While in the first problem, a strict comparison would have prevented us from getting the flag, here it is only because of that strict comparison that we succeed.