ACECTF 2025 - web - Webrypto
A PHP web challenge exploiting an error-handling flaw in md5()
Initial Analysis
Challenge Description
1
2
3
4
5
I think we can all agree that most of us grew up watching the iconic cartoon Tom & Jerry. Every kid would feel that surge of adrenaline during the thrilling chases and chaotic conflicts between the mischievous mouse and the ever-determined cat. The excitement of those scenes—the heart-pounding moments of escape—sometimes felt almost real.
But then, I heard a little rumor: what if all those chases were fake? What if Tom and Jerry were actually friends all along? That revelation shook me. I had no one to ask about this mind-bending twist, so I decided to take matters into my own hands—I created a web app to settle this question once and for all.
I know the truth now. Do you think you can uncover it too?
When visiting the website, I found a PHP source code snippet:
1
2
3
4
5
6
7
8
9
10
11
12
<?php
include('flag.php');
highlight_file(__FILE__);
// Check if parameters 'tom' and 'jerry' are not equal
if ($_GET['tom'] != $_GET['jerry']) {
echo "<br>Parameter 1 Met!<br>";
if (md5('ACECTF' . $_GET['tom']) == md5('ACECTF' . $_GET['jerry'])) {
echo $FLAG; // If the condition is true, print the flag
}
}
Understanding the Code
- The script includes
flag.php
, which contains the flag. - The source code of the file is displayed.
- It checks if the
tom
andjerry
GET parameters have different values. - It applies an MD5 hash with the salt
ACECTF
and compares the results. - If both conditions are satisfied, the flag is printed.
Analysis and Exploitation
Step 1: Bypassing the First Condition
To pass the first condition, tom
and jerry
must have different values. A simple URL like this works:
1
https://webchall.link/?tom=a&jerry=b
This satisfies $_GET['tom'] != $_GET['jerry']
.
Step 2: Bypassing the Hash Check
PHP’s MD5 function is vulnerable to hash collisions, but since a salt (ACECTF
) is added, a traditional MD5 collision attack won’t work. However, there is another vulnerability in PHP: an error-handling flaw caused by hashing an array.
Step 3: Exploiting the Vulnerability:
If we send the parameters as arrays, PHP will treat them differently when hashing. Using the following payload:
1
https://webchall.link/?tom[0]=0&jerry[1]=0
tom[0] = 0
andjerry[1] = 0
are treated as arrays.- The first condition
(tom != jerry)
is still true because PHP treats array comparisons differently. Sincetom = array(0=>0)
andjerry = array(1=>0)
, they are considered different arrays, thus passing the first check. - When PHP tries to hash the values using MD5, it expects a string but receives an array, leading to an error-to-null vulnerability.
- Since
md5("ACECTF".NULL) == md5("ACECTF".NULL)
always evaluates to true, this occurs because PHP attempts to hash an array, which is invalid. Whenmd5()
receives an array instead of a string, PHP triggers a warning:Warning: md5() expects parameter 1 to be string, array given
. As a result, MD5 returnsNULL
for both values, making them identical and passing the comparison check. When attempting to hash an array, PHP throws a warning and returnsNULL
. As a result, both hashes compare as equal, satisfying the second condition and revealing the flag!
Conclusion
This challenge demonstrates an error-handling flaw in PHP, where comparisons between arrays and strings behave unexpectedly. Instead of exploiting hash collisions directly, we bypassed the security check using a PHP array conversion trick.
Key Takeaways
- PHP has weak type handling that can lead to unintended vulnerabilities.
- MD5 is not collision-resistant, but adding a salt makes basic attacks harder.
- Using arrays in GET parameters can lead to unexpected behaviors in security checks.
- Error-handling flaws can be exploited when input validation is not strict.
- PHP generates a warning when trying to hash an array, but the execution continues, which can be leveraged for exploits.
Hope this write-up helps you in future CTF challenges!