pentesterlab.com Open in urlscan Pro
54.87.134.91  Public Scan

URL: https://pentesterlab.com/blog/php-security-is-improving
Submission: On July 23 via manual from BR — Scanned from DE

Form analysis 0 forms found in the DOM

Text Content

10010101 101110 11001 001 101 0111 101101 01101
Home Exercises Blog Bootcamp AppSecSchool Go Pro
Login | Sign up


IS PHP REALLY GETTING BETTER?


Share


There’s been a lot of chatter about PHP being insecure, but as Luke Stephens
points out in his article, "People who say 'PHP is insecure' are uninformed",
this is far from the truth. He breaks down why this belief is outdated and
misinformed. One thing this article does not cover is something a lot of people
don't realize: Programming languages change over time. PHP from 15 years ago is
different from today's PHP.

BLAST FROM THE PAST...

If you are old-school, you probably remember Stefan Esser (i0n1c) and "The Month
of PHP Bugs". Basically, Stefan spent March 2007 dropping vulnerabilities in
PHP—not PHP applications, but PHP itself. This "Month of PHP Bugs" was started
to increase awareness about PHP's lack of security. At the time, the PHP
Hardened team was working on providing hardened versions of PHP (the "suhosin"
patch). You can still find details about those bugs on web.archive.org: "The
Month of PHP Bugs".

Around this era, PHP applications were extremely common and had a very poor
security track record.

All of this didn't help PHP's reputation. But it was 17 years ago, and a lot has
changed since then. One main thing is that PHP has reduced the number of
surprising behaviors for developers. Let's dive in!

PHP HAS CHANGED AND IS CHANGING

The PHP language has evolved significantly over the years. Many tricks to find
vulnerabilities in PHP applications or exploit vulnerabilities in PHP have been
rendered obsolete with new versions. Let's look at some of the significant
changes!

NULL BYTES...

PHP used to rely on C functions to access files. C functions are notoriously bad
at handling NULL bytes (\x00 or URL-encoded %00). If you pass the string
/etc/passwd\x00hacktheplanet to read a file, C functions will stop at the NULL
byte and read the file /etc/passwd. This behaviour created a lot of
vulnerabilities or made a lot of weaknesses exploitable. PHP moved away from
this with PHP 5.3.4 by fixing CVE-2006-7243.

PCRE_EVAL

Another surprising behavior in PHP was available when you had control over a
regular expression. The infamous PCRE_EVAL or /e could be used to have the
result evaluated as PHP code, allowing for quick remote code execution. For
example, in the snippet below:



  echo preg_replace("/test/e","get_current_user()", "test");

will end up replacing test with get_current_user() and execute
get_current_user() as PHP code... An real-life example of the danger of this can
be found by analyzing CVE-2005-2086: a remote code execution impacting PHPBB.
This behavior was removed in PHP 7.0.0 (released in December 2015)

LOOSE COMPARISONS

Loose comparisons have also been a big issue in PHP. Why does "php" == 0 or why
does "1`uname`" == 1? This unexpected behavior was changed in PHP 8.0. Look for
the little stars in the image below and the notes below the table:




While we're at it, why is declare(strict_types=1); so rarely used by PHP
applications?

ASSERT AND RCE

PHP 8.0 also impacted the ability to gain remote code execution (RCE) by
leveraging assert(). The contrived example below illustrates the issue:

  echo assert(trim("'".$_GET['a']."'")); 

and will lead to code execution.

ASSERT AND RAISING...

Another unexpected behavior of PHP was the fact that, by default, assert()
wouldn't stop the execution of the code. Admittedly, you could change this
behavior, but as good application security engineers know: "defaults matter".
With PHP 8.0 (August 2023), the behavior has changed, and a failing assert()
will stop the execution of the code by default! Before PHP 8.0, the following
code:

  echo assert(true == false);
  echo "HACK";

will echo HACK in the default PHP configuration

HASH_HMAC()

Speaking of warnings, the following code illustrates a good trick to bypass a
signature check - passing an array instead of a string:

hash_hmac('sha256',  array(), "HACKTHEPLANETWITHPENTESTERLAB");

This code returned NULL and raised a warning until PHP 8.0; since then, it has
been raising a TypeError.

HTMLENTITIES AND SINGLE QUOTES...

Another trick to find quick bugs in PHP applications was to look for values
echoed in a page in JavaScript using single quotes. This used to work because
PHP didn't escape single quotes by default. Again, in application security,
defaults matter! This behavior was changed with PHP 8.1.

Before PHP 8.1:

echo htmlentities("\"'<>"); //returns &quot;'&lt;&gt; 

After PHP 8.1:

echo htmlentities("\"'<>"); //returns &quot;&#039;&lt;&gt;

SO, IS PHP GREAT NOW?

Well, there are still some surprises and interesting behaviors that were
recently fixed in PHP. For example, check out this bug in password_verify() (The
first comment is worth reading just to learn how not to do application
security).

PHP 8.1 also introduced new features that may surprise developers and likely
bring a few bugs: $_FILES[...]["full_name"]. It's worth keeping an eye out for
this in your next reviews.

CONCLUSION

PHP has come a long way from its insecure past. While it has made significant
strides in improving security and reducing unexpected behaviors, it's crucial
for developers to stay informed about new features and potential security
issues. Keeping up-to-date with the latest changes ensures that PHP applications
remain secure and robust.

Written by Louis Nyffenegger

Founder and CEO @PentesterLab

support@pentesterlab.com Privacy Policy Terms of Service Careers Logo

© 2024 PentesterLab