[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