Categories
incident update

Update on Git.php.net Incident

Hi everyone, I would like to provide an update regarding the git.php.net security incident. To briefly summarize the most important information: We no longer believe the git.php.net server has been compromised. However, it is possible that the master.php.net user database leaked. master.php.net has been migrated to a new system main.php.net. All php.net passwords have been…

Hi everyone,

I would like to provide an update regarding the git.php.net security
incident. To briefly summarize the most important information:

The following is a more detailed explanation of what happened and which
actions were taken.

When the first malicious commit was made under Rasmus’ name, my initial
reaction was to revert the change and revoke commit access for Rasmus’
account, on the assumption that this was an individual account compromise.
In hindsight, this action didn’t really make sense, because there was (at
the time) no reason to believe that the push occurred through Rasmus’
account in particular. Any account with access to the php-src repository
could have performed the push under a false name.

When the second malicious commit was made under my own name, I reviewed the
logs of our gitolite installation, in order to determine which account was
actually used to perform the push. However, while all adjacent commits were
accounted for, no git-receive-pack entries for the two malicious commits
were present, which means that these two commits bypassed the gitolite
infrastructure entirely. This was interpreted as likely evidence of a
server compromise.

Shortly after that, we made the decision to discontinue git.php.net and
make GitHub our primary repository host instead. Retaining our own Git
infrastructure would have required setting up a new git.php.net server
after determining the root cause of the compromise. This would take a lot
of time and disrupt PHP development in the meantime. A basic migration to
GitHub could be performed much more quickly, as most repositories were
already mirrored there. At this point, a lot of development was already
going through GitHub anyway, and our own Git infrastructure was mostly a
security liability and complication to the development workflow, so it was
not a hard decision to make the switch.

Something I was not aware of at the time is that git.php.net
(intentionally) supported pushing changes not only via SSH (using the
gitolite infrastructure and public key cryptography), but also via HTTPS.
The latter did not use gitolite, and instead used git-http-backend behind
Apache2 Digest authentication against the master.php.net user database. I’m
not sure why password-based authentication was supported in the first
place, as it is much less secure than pubkey authentication.

Based on access logs, we can determine that the commits were indeed pushed
using HTTPS and password-based authentication. An excerpt of relevant log
entries is shown below:

[redacted] – rasmus@[redacted] [27/Mar/2021:19:19:23 -0700] “GET
/push/php-src.git/info/refs?service=git-upload-pack HTTP/1.1″ 401 941
[redacted] – rasmus@[redacted] [27/Mar/2021:19:19:28 -0700] “GET
/push/php-src.git/info/refs?service=git-upload-pack HTTP/1.1″ 401 941
[redacted] – rasmus [27/Mar/2021:20:56:51 -0700] “GET
/push/php-src.git/info/refs?service=git-receive-pack HTTP/1.1″ 200 125315
[redacted] – rasmus [27/Mar/2021:20:58:13 -0700] “POST
/push/php-src.git/git-receive-pack HTTP/1.1″ 200 1080
[redacted] – nikita.ppv [28/Mar/2021:09:09:15 -0700] “GET
/push/php-src.git/info/refs?service=git-upload-pack HTTP/1.1″ 401 941
[redacted] – nikita.ppv [28/Mar/2021:09:09:18 -0700] “GET
/push/php-src.git/info/refs?service=git-upload-pack HTTP/1.1″ 401 941
[redacted] – nikitappv [28/Mar/2021:09:09:35 -0700] “GET
/push/php-src.git/info/refs?service=git-upload-pack HTTP/1.1″ 401 941
[redacted] – nikitappv [28/Mar/2021:09:09:36 -0700] “GET
/push/php-src.git/info/refs?service=git-upload-pack HTTP/1.1″ 401 941
[redacted] – nikita [28/Mar/2021:09:09:50 -0700] “GET
/push/php-src.git/info/refs?service=git-upload-pack HTTP/1.1″ 401 941
[redacted] – nikita [28/Mar/2021:09:09:53 -0700] “GET
/push/php-src.git/info/refs?service=git-upload-pack HTTP/1.1″ 401 941
[redacted] – nikic [28/Mar/2021:09:11:31 -0700] “GET
/push/php-src.git/info/refs?service=git-receive-pack HTTP/1.1″ 401 941
[redacted] – nikic [28/Mar/2021:09:11:31 -0700] “GET
/push/php-src.git/info/refs?service=git-receive-pack HTTP/1.1″ 401 941
[redacted] – nikic [28/Mar/2021:09:13:28 -0700] “GET
/push/php-src.git/info/refs?service=git-receive-pack HTTP/1.1″ 200 123263
[redacted] – nikic [28/Mar/2021:09:13:39 -0700] “POST
/push/php-src.git/git-receive-pack HTTP/1.1″ 200 1079

It is notable that the attacker only makes a few guesses at usernames, and
successfully authenticates once the correct username has been found. While
we don’t have any specific evidence for this, a possible explanation is
that the user database of master.php.net has been leaked, although it is
unclear why the attacker would need to guess usernames in that case.

The master.php.net system, which is used for authentication and various
management tasks, was running very old code on a very old operating system
/ PHP version, so some kind of vulnerability would not be terribly
surprising. We have made a number of changes to increase the security of
this system:

  • master.php.net was migrated to a new system (running PHP 8) and renamed
    to main.php.net at the same time. Among other things, the new system
    supports TLS 1.2, which means you should no longer see TLS version warnings
    when accessing this site.
  • The implementation has been moved towards using parameterized queries,
    to be more confident that SQL injections cannot occur.
  • Passwords are now stored using bcrypt.
  • Existing passwords were reset (use main.php.net/forgot.php to generate a
    new one).

Previously, passwords were stored in a format compatible with HTTP Digest
authentication (essentially a plain md5 hash), which was required for HTTP
authentication on git.php.net and svn.php.net. As git.php.net has been made
read-only as a result of this incident, we decided to make svn.php.net
read-only as well, and thus remove the need to store passwords in an
insecure format. Only a small handful of PECL extensions were still using
the SVN server. The following SVN repositories had semi-recent activity and
have been migrated to GitHub:

https://github.com/php/pecl-authentication-krb5
https://github.com/php/pecl-caching-varnish
https://github.com/php/pecl-database-dbase
https://github.com/php/pecl-datetime-hrtime
https://github.com/php/pecl-datetime-timezonedb
https://github.com/php/pecl-math-trader
https://github.com/php/pecl-networking-geoip
https://github.com/php/pecl-processing-rrd
https://github.com/php/pecl-system-expect
https://github.com/php/pecl-text-pdflib
https://github.com/php/pecl-tools-svn
https://github.com/php/pecl-xml-xmldiff

Please contact me at nikic@php.net if additional migrations or permission
adjustments are needed. Please also report any issues you encounter with
main.php.net — it’s likely that some things broke during the migration.

Regards,
Nikita

Read More

Leave a Reply

Your email address will not be published. Required fields are marked *