[wp-trac] [WordPress Trac] #39309: Secure WordPress Against Infrastructure Attacks

WordPress Trac noreply at wordpress.org
Wed Jul 10 06:18:07 UTC 2019


#39309: Secure WordPress Against Infrastructure Attacks
------------------------------------------+---------------------
 Reporter:  paragoninitiativeenterprises  |       Owner:  pento
     Type:  task (blessed)                |      Status:  closed
 Priority:  normal                        |   Milestone:  5.2
Component:  Upgrade/Install               |     Version:  4.8
 Severity:  critical                      |  Resolution:  fixed
 Keywords:  has-patch                     |     Focuses:
------------------------------------------+---------------------

Comment (by dd32):

 I've had a few questions asking for a status update on where this ticket
 ended up, here's a rough long summary -
 '''tl;dr:''' The current implementation isn't robust enough and needs a
 team to pick it up and run with a solution.

 At the launch of WordPress 5.2 we had Theme Package signatures being
 served, and that was it, the server-side implementation of this wasn't as
 secure as we wanted but with the intention that it'd be updated shortly
 thereafter as we rolled it out to Plugins and Core.

 Then we found the performance issues affecting 32bit PHP installations
 when using Sodium_Compat - #47186, Theme Package signatures were
 temporarily disabled with the intention of being re-enabled after
 WordPress 5.2.1 was more used than 5.2.0. Theme Signatures were never re-
 enabled as the timing of the release wasn't the best, and no-one has ever
 followed up on it being still disabled - so we assume those speed issues
 were completely fixed, but we're not really sure?

 Now that we've sorted out the algorithm speed issues (We think?) we can
 move forward, but in order to do so there's a few remaining questions we
 ran into while figuring out the WordPress.org side of things
 1. How do we mark a key as compromised and to no longer trust it? Current
 Answer: Release a new version of WordPress with a new alternate key - but
 what about those who don't update immediately? etc.
 2. How do we rotate signing keys regularly keeping them with a limited
 timespan (Either X major WordPress releases, or X months/years) and having
 older WordPress installations still being able to trust a new key they've
 never seen?
 3. Split signing into groups by type, ie. KeyA can sign Core releases
 only, a plugin signed by KeyA should be rejected.
 4. Only trust a signature from a key during it's lifespan - ie. If a key
 was valid for 2019-01-01 until  2019-06-01, a signature from that key on
 2019-09-01 shouldn't be valid. Oh, and it shouldn't be trusted if used for
 a signature after 2019-04-01 anymore as key was compromised or mishandled,
 but we still want to trust it for a signature from 2019-02-01.
 5. How do we handle a maliciously signed package? Lets say that somehow
 someone gets a plugin package signed that should never have been signed
 (but the key isn't compromised) how do we prevent WordPress trusting that
 signature?

 The above shows that using Ed25519 / Sodium_Compat is only part of the
 solution we need, we've got an algorithm, but we actually need a
 "platform" around it instead - that scope is far larger than this ticket
 ever really suggested.

 On the topic of Item 2, perhaps we need to have a chain of keys that can
 be trusted, ie. WordPressA trusts KeyA, gets presented KeyC through a
 secure API and can trust it / add it to it's local set of keys as it's
 signed by KeyB, and KeyB was signed by KeyA during a validity period.
 Something like that would require a key manifest containing key objects
 similar to something like this (Note: 100% not super thought through, this
 might not be a good solution at all)
 {{{
 {
   key: PUBKEY-B,
   not-valid-before: "2019-05-01 00:00:00",
   not-valid-after: "2019-12-01 00:00:00",
   valid-for: [ "core" ],
   signed: {
     PUBKEY-A {
       signature: SIGN OF PUBKEY-B by PUBKEY-A,
       when: 2019-05-01 12:34:56
     }
   }
 }
 }}}

 On the topic of Item 3, we could have potentially used `HMACSHA384` with a
 per-package-type seed key here, which would've at least ensured that the
 hash of a intentionally signed Core package would be different from an
 intentionally signed plugin package.

 When it comes to Items 3/4 perhaps packages shouldn't have just be a
 signature of a hash, but rather a signature of a manifest containing all
 the relevant details we need to work with, for example:
 {{{
 {
   signature: SIGNATURE OF PAYLOAD,
   payload: {
     what: "core",
     filename: "wordpress-5.3.zip"
     date: 2019-04-01 12:34:56,
     hash: sha384_hmac 12345678 WordPressCore,
   }
 }
 }}}
 But that doesn't add any way of verifying that the date within the payload
 is actually when it was signed, only when the signer claimed to have
 signed it.. If I compromised a key on 2019-05-01 I could back-date my
 signature to 2019-04-01 and no-one would know.

 Perhaps we need something like certificate transparency, where there's a
 public ledger of package signatures that can be referenced against, and
 can be trusted as you know who signed it when, etc.

 Some of these scenario's are things that can be at first thought are over
 engineering, but the idea is that we're securing the process end-to-end
 rather than just at the network level, and ensuring that we're ready for
 the day (hopefully far far in the future) where a signing key is
 compromised.
 If I were to give you a USB drive containing a WordPress package, you
 should be theoretically able to verify that yes it came from WordPress.org
 and I didn't modify it, falsify it's signature, or signed it myself using
 a copy of a key I obtained maliciously at some time in the past.

 cc @pento @paragoninitiativeenterprises and anyone else who has been
 active on this ticket.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/39309#comment:89>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list