# PHP Loose comparison

PHP has this particular functionality called Type juggling, it essentially tries to predict what a programmer wants to do with a variable, it usually checks whats's inside a variable and tries to convert it, for example if a string contains only numbers it will convert it to either an integer or a float, this behaviour can sometimes cause issues, especially when loose comparison is used.

{% hint style="info" %}
PHP8 won't try to cast string into numbers anymore, <https://dustri.org/b/php8-from-a-security-point-of-view.html#:~:text=PHP8%20won't%20try%20to,Snuffleupagus'%20sloppy%20comparison%20prevention%20feature.>
{% endhint %}

In PHP there are 2 main types of comparison

* Strict comparison (===)&#x20;
* Loose comparison (==)

### Loose comparison

Loose comparison compares only the value of the variable and not the type, it uses type juggling to try and predict the type of the variable

<figure><img src="/files/iCVYgMFtu3SrpknckabA" alt=""><figcaption><p><a href="https://www.php.net/manual/en/types.comparisons.php">https://www.php.net/manual/en/types.comparisons.php</a></p></figcaption></figure>

***

### Strict comparison

Strict comparison instead compares both the value of the variable and the type, it doesn't do any kind of type juggling since it also compares the type of the variable

<figure><img src="/files/LihvnEg6USvGrP1B1rIc" alt=""><figcaption><p><a href="https://www.php.net/manual/en/types.comparisons.php">https://www.php.net/manual/en/types.comparisons.php</a></p></figcaption></figure>

### Some examples

these examples may work or not depending on the version of php that is currently in use

```php
var_dump(15 == "15");  // bool(true)
var_dump('0xdeadbeef' == '3735928559');  // bool(true) works on versions before php7
```

another peculiar example is :&#x20;

```php
var_dump('10e3' == '1e4');  // bool(true)
```

Here PHP interprets boh the strings `10e3` and `1e4` as a scientific notation, PHP first converts this numbers into floats and the procedes with the comparison

* `10e3` becomes $$10×10 ^2 = 1000$$
* `1e4` becomes $$1×10 ^3 = 1000$$

### Magic Hashes

Due to PHP juggling, when comparing hashes to another variable, if the hash starts with `0e` it will again be interpreted as a scientific notation and it's value is going to equal to 0

{% code overflow="wrap" %}

```php
var_dump('0e123' == '0'); # bool(true)
var_dump(md5('sQcRTBkePLSY') == md5('fQvn3oAoYNfo')); # bool(true)
// it translates to : var_dump('0e576163277785256730155739473379' == '0e935872100939536813194636270943');
```

{% endcode %}

You can find whole lists of magic hashes on various algorithms here : <https://github.com/spaze/hashes>

### Challenge

<https://websec.fr/level10/index.php>

a simple ctf challenge showcasing this kind of vulnerability


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://pentestbook.r4yan.com/type-juggling/php-loose-comparison.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
