PHP Type Juggling
This article will cover PHP type juggling, and some different ways i have encountered it on hackthebox .
PHP has two comparisons; loose (==, =!) and strict (===). Strict comparison 1 = 1, but in loose 1 could mean many things 1 could equal true or 1. Meaning that there multiple meaning for the values used. This is a built in feature for PHP to force type conversion into specific data type.
PHP loose comparison does this to accommodate different data types for example; ‘9’ is different from 9. Adding the two data types in PHP will result in 18. In other languages like python will not accommodate such errors. PHP does this so the program might run as it was expected to. Accommodating human errors. Below are some examples of loose comparison.
'0e1234' == '0e4321'
'0e1234' == '0'
'0e1234' <= '1'
'0xf' == '15' #0xf in hexadecimal notation is 15
when php compares a string to a interger it has some weird quirks.
'000...000' == int(0)
'0e0...000' == int(0)
'1e0...000' == int(1)
'abc...000' == int(0) # if a string starts with a non numerical character it will default to int(0)
Another example is when PHP try’s to interpreter a string and its converted into PHP exponential notation 0e⁰²³⁴²⁶²³⁴²²⁴¹²⁵¹⁶⁷⁸⁹ 0e²³⁴²⁶²³⁴²²⁴¹²⁵¹⁶⁷⁸⁹ equates to int(0) as well. If the number after the first letter is 0 it will remove the leading zero.
In the above examples the entire string is converted into a numerical value, or something completely different. Confusing I know but here are some popular charts that show how loose comparison works.
phpsession, cookies, & passwords are susceptible to PHP type juggling. Allowing the attacker to take advantage of a PHP feature to gain access to valid user accounts. From what I have read, the attacker randomly generates cookies. Trying to predict the next cookie. The more random(entropy) the targets cookies have, the harder it is to preform this attack.
In the below example, PHP will convert both of the md5 hashes into integers. It will then compare the two values based on the integer. Even though the two hash are different they are both treated as value.
aa6fw…34tj4343 = 0
ff6dj..w221.5885m = 0
This is also applicable to PHP authentication