Intigriti’s PHP challenge breakdown
Let’s discuss issues with the PHP code shared by Initgriti! We will discuss on how you can shoot yourself in the foot with PHP’s shenanigans!
Today I came across this tweet from Intigriti:
Can you guess what the issue in this code is?
Introduction
The code snippet is for PHP, and PHP is quite popular among hackers for being so ridiculous and having quite a lot of issues! And we will discuss one of the important is Type Juggling — some call it a feature, some see it as thing full of bugs, depending on which lens you use to look at it ;)
So the thing in PHP is that if you compare 2 values using ‘==’ operator and perform “loose” comparisons, the results could be quite unexpected due to PHP not being strictly typed — that is, there’s no notion of string and ints, its decided by the PHP dynamically based on the value a variable holds and the operations performed on it can lead to type-conversions.
This table can summarize what I meant by loose conversions resulting in unexpected results:
So in PHP,
1 == true
results in true
and so does
-1 == true
And this must make you think — “Then how do I ensure my comparisons are exact?”
For that, we have “===” operator in PHP which will make comparisons as you would expect.
As you can see, only the diagonal entries of the following table have “true”, other non-diagonal values are “false” because the values differ and thus the strict comparison results in “false”.
Okay, enough theory now, let’s see how the code shared was vulnerable!
The Issues
Let’s see the code and discuss the potential issues.
So, what do you think are some of the vulnerabilities?
Type Juggling? Yes correct!
And anything else?
Use of md5 hash? No…, its an issue but it doesn’t implies any vulnerability.
Okay, so Type Juggling is the vulnerability. Can we exploit it and print the unreachable code branch without trying to crack the md5 hash.
Seems like we can!
The Solution
So in order to pass the checks and get to the desired print statement, I need to pass ‘admin’ as the username and the password still is the missing piece...
So how can we pass this check? Any ideas? Type Juggling? Yes indeed!
We will leverage Type Juggling since loose comparison is being performed due to the use of ‘==’ operator.
If you notice, the right hand side is “0e….”.
0e notation is the scientific notation which is expressed as:
0 * (10 raised to the power the number after ‘0e’) which would be ‘0’ ofcourse!
0 * anything = 0 (right?)
And therefore if we are able to influence the md5 hash and result in a value that is also of type 0e followed by a number, then it will be treated as a numeric value (scientific notation) and result in 0.
Easy enough… I found this article which told me a few possible values for password that can result in the hash we desire (0e followed by all numbers):
So '240610708' & 'QNKCDZO'
can be used!
I just hosted the code snippet using the following command:
php -S 127.0.0.1:8081
Tried both possible password values (there could be more values obviously due to collisions in MD5):
And the server logs should look like this:
Closing Thoughts
PHP is quite a fantastic programming language for a pentester because of so many ways available to shoot yourself in the foot.
Especially the type juggling and function arguments order mess up being the most common issues!
So with that, I would close this post. I hope this post was informational and fun to read. In case you enjoyed it, please share it among your friends in the infosec community :)
Let me know your feedback in the comments below and feel free to connect on twitter: @_SecurityGOAT
You can also send any topic you wish to learn more about. Send me DM on Twitter or let me know in the comments :)
Lastly, the line which should mostly be a plain ol’ boring one which I have to copy from my previous post every single time!!!! — if you have been enjoying my work and would love to support me, consider checking my Patreon page or you can even Buy Me a Coffee :)
See ya!
Until next time my friend, keep learning and happy hacking.