PHP8 was released on the 26th of November 2020. It brought a lot of interesting things, security-wise, but also showcases a couple of (minor) missed opportunities in my opinion.
PHP8 won't try to cast string into numbers anymore, thanks to the
Saner string to number comparisons RFC,
meaning that collision with hashes starting with
0e and the likes are finally
a thing of the past! This is a subset of Snuffleupagus' sloppy comparison
The Consistent type errors for internal functions RFC
will prevent things like
0 == strcmp($_GET['username'], $password) bypasses,
strcmp won't return
null and spit a warning any longer,
but will throw a proper exception instead. This was also a nice opportunity
for PHP to add annotations for functions parameters and return types.
The Stricter type checks for arithmetic/bitwise operators and PHP RFC: Reclassifying engine warnings RFC are in the same spirit.
Moreover, DynASM isn't designed with processing/compilation/execution of untrusted code in mind, and doesn't do things like constants blinding and advanced folding to mitigate against spraying, nor random padding/nop insertion, nor ensuring that the memory region is never both writeable and executable to prevent direct code injection. This means that it's now way easier to gain native code execution when exploiting memory corruptions, albeit to be fair, most attackers are happy with a php code execution, and won't push further.
Having a JIT comes with a lot of code complexity and maintenance burden. I'll be without doubt a great source of bugs, for a minor speed improvement on real-life workloads.
password_hashnow automatically generates a salt, accepting a user-provided one is deprecated.
cryptwill now fail instead of silently falling back to DES when an unknown salt format was provided. The parameter is also made mandatory, hashing without a salt is now unsupported.
- RFC 5652 is now exposed via the OpenSSL extension.
- The error control operator, aka
@won't silence fatal errors anymore, meaning that poorly written webshells will have more chances to leave traces in your logs.
libxml_disable_entity_loaderis now deprecated, even if it's not (yet) reflected in php's documentation. This is acceptable since PHP8 now requires at least libxml 2.9.0, which comes with external entity loading disabled by default.
- Access to undefined constants will throw an error, instead of being silently
interpreted as a string, no more
SALTbeing silently converted to
create_functionwas removed, closing its infamous code injection vector.
array_key_existsthrows when passed an array/object, instead of silently doing nonsense.
mb_ereg_replacehas been removed.
- Metadata associated with a phar will no longer be unserialized, killing a low-hanging RCE vector.
get_magic_quotes_runtimehave been removed, people will now have to do proper sanitization instead.
- As usual, a couple of memory safety issues were fixed, some exploitable.
- Snuffleupagus is currently being ported to php8!
opposed to constants, are still not an error, meaning that things like
salt might (and will) go unnoticed.
Array to a string will only yield a
Warning instead of an
error, albeit that now that
__toString can finally
throw, it might hopefully change
in the near future.
An other missed opportunity in my opinion is that there is still no
way to disable some PHP's wrappers, except via
but this can be reversed with
Wrappers are scary: the main use I've seen for the
exfiltrating data via
php://filter/convert.base64-encode/resource=/some/file, and is a decent
stuff lurking in the shadows.
Providing a way to reduce this attack surface (like making streams opt-in)
would be welcome.