[wp-trac] [WordPress Trac] #39309: Secure WordPress Against Infrastructure Attacks
WordPress Trac
noreply at wordpress.org
Fri Dec 16 17:50:15 UTC 2016
#39309: Secure WordPress Against Infrastructure Attacks
------------------------------------------+-----------------------------
Reporter: paragoninitiativeenterprises | Owner:
Type: enhancement | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Upgrade/Install | Version: trunk
Severity: normal | Keywords:
Focuses: |
------------------------------------------+-----------------------------
(Similar to #25052 but much more focused on the implementation details)
== Background ==
Recommended reading:
1. http://seclists.org/oss-sec/2016/q4/478
2. https://www.wordfence.com/blog/2016/11/hacking-27-web-via-wordpress-
auto-update/
3. https://paragonie.com/blog/2016/10/guide-automatic-security-updates-
for-php-developers
Currently, if an attacker can compromise api.wordpress.org, they can issue
a fake WordPress update and gain access to every WordPress install on the
Internet that has automatic updating enabled. We're two minutes to
midnight here (we were one minute to midnight before the Wordfence team
found that vulnerability).
Given WordPress's ubiquity, an attacker with control of 27% of websites on
the Internet is a grave threat to the security of the rest of the
Internet. I don't know how much infrastructure could withstand that level
of DDoS. (Maybe Google?)
The solution is to make the automatic update mechanism secure **even if
the update server is totally owned up**. As published in the third link,
the core elements of a totally secure automatic update system are:
1. Offline Cryptographic Signatures
2. Reproducible Builds
3. Decentralized Authenticity / Userbase Consistency Verification
4. Transport-Layer Security
5. Mirrors and Other Availability Concerns
6. Separation of Privileges
However, I'm mostly interested in 1, 2, and 3. I believe 4 is already
implemented (if not, this just became a lot scarier).
== Proposed Solution ==
We're going to have to roll this out in phases, rather than all at once.
1. Offline Cryptographic Signatures
1. Decide on a digital signature algorithm and/or cryptography library
to use.
2. Generate a keypair for the release managers to use.
3. Pin the public key in a major release (e.g. 4.8 or 4.9).
4. Add signature verification to the update process, but for the first
release or two, **don't enforce it**. Just collect data until we're sure
it works for everyone.
5. Enforce digital signatures. Then this is satisfied.
2. Reproducible Builds.
1. The update file should be easily reproduced by any end user.
2. The update file and update served by api.wordpress.org should be
easily verifiable.
3. We wrote Pharaoh for auditing PHP Archives; something similar may be
useful for WP updates: https://paragonie.com/project/pharaoh
3. Decentralized Authenticity / Userbase Consistency Verification
* See below.
4. Make plugin/theme updates secure.
Once core updates are secure, the next step is to allow plugin/theme
developers to upload their own public keys which can be used to sign their
own extensions.
If you want a reference implementation, we already have a working secure
automatic update system built into CMS Airship (which is GPL 3):
* https://paragonie.com/blog/2016/05/keyggdrasil-continuum-cryptography-
powering-cms-airship
*
https://github.com/paragonie/airship/blob/master/src/Engine/Continuum.php
*
https://github.com/paragonie/airship/blob/master/src/Engine/Keyggdrasil.php
=== Decentralized Authenticity ===
In CMS Airship, we're totally decentralized: Every Airship maintains its
own record of every update file or new/revoked public key since its
inception. (This is because CMS Airship aims for maximum security.)
For WordPress, I'm recommending a federated model instead, but the
concepts are mostly the same:
1. Notaries (WordPress blogs or other services that opt in to
hosting/verifying the updates) will mirror a Merkle tree which contains
(with timestamps and signatures):
* Any new public keys
* Any public key revocations
* Cryptographic hashes of any core/extension updates
2. WordPress blogs will have a pool of notaries they trust explicitly.
(This can be provided by your hosting provider, who runs the single source
of truth for all their clients, so long as they themselves practice due
diligence.)
3. When an update is received from the server, after checking the
signature against the WP core's public key, they will poll at least one
trusted Notary (send a challenge nonce, current timestamp, a checksum of
the update file, and any other useful identifying metadata e.g. "wp-core
version 4.9.2"). The Notary will verify that the update exists and matches
the checksum on file, and respond with a signed message containing:
* The challenge nonce
* The response timestamp
* Whether or not the update was valid
This will be useful in the event that the WP.org's signing key is ever
compromised by a sophisticated adversary: If they attempt to issue a
silent, targeted update to a machine of interest, they cannot do so
reliably: To pull off their attack, they have to allow the Merkle tree
(that is mirrored by every Notary) to record/broadcast evidence of their
attack in order for it to succeed. So while targeted attacks may still be
theoretically possible, it will no longer be possible to do them silently.
In addition to a security layer, it's a deterrent against the most
sophisticated threats.
=== Securing Plugins and Themes ===
This will probably be the last piece tackled. Basically: Offer the same
signing capabilities to theme/plugin developers that will already be in
the hands of the core team.
This can be done piecemeal (i.e. optional field on WP.org that allows them
to upload their public key, generated by some tooling we provide
developers). We should incentivize packages that provide their own
signature by, for instance, placing them higher in the listings and/or
giving them an attractive and desirable UI element that says "we're
secure".
If we one day reach near-100% coverage of the WP ecosystem with digital
signing, we can discuss making it mandatory.
== Implementation Recommendations ==
Okay, this section is going to be technical so feel free to skip most of
this if you're not into cryptography.
TL;DR - We need a libsodium polyfill, which Paragon Initiative Enterprises
is willing to write for free if (and only if) the cost of an independent
third party audit is covered by the community and/or the community's
corporate sponsors.
=== Digital signatures ===
PHP, out of the box, only supports RSA signatures (via the OpenSSL
extension), but doesn't support RSASSA-PSS+MGF1SHA256. PKCS1v1.5 padding
is unacceptable.
It may be tempting to move towards something like ECDSA, but a mix of
security concerns (the Sony ECDSA k-value reuse incident, invalid curve
attacks against Weierstrass curves) makes us wary even of RFC 6979
(deterministic ECDSA).
We propose a standardized digital signature algorithm based on twisted
Edwards curves. Namely, **Ed25519** or **Ed448** (EdDSA over the RFC 7748
curves).
=== Merkle Trees ===
The TrimmedMerkleTree in Halite is probably the best starting point:
https://github.com/paragonie/halite/blob/master/src/Structure/TrimmedMerkleTree.php
Halite's Merkle tree implementations are based on the BLAKE2b hash
function (a SHA3 finalist with great performance in software based on the
ChaCha20 round function).
=== Checksums ===
One of the following algorithms should be used where ever a checksum is
required:
* BLAKE2b
* SHA-512/256
* SHA-512/224
* SHA-384
At no point should MD5 or SHA1 be considered. SHA-256 and SHA-512 are
vulnerable to length-extension attacks and are not recommended.
== Action Plan ==
First, if this plan is agreeable by WordPress's security team, we'll get
to work on a libsodium polyfill that works as far back as PHP 5.2.4 (in
the spirit of WordPress's backwards compatibility tradition).
Once that's finished, independently audited by cryptography experts, and
released to the public, we'll work on getting the core cryptographically
signed. This will require some additional tooling; the release managers
will need to run a command to produce a valid signature of the update file
before releasing it.
After core updates are signed and signatures are being verified, we'll
build the decentralized verification layer.
Then, we can move forward with making everyone's plugins and extensions
securely delivered.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/39309>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list