flarum / framework

Simple forum software for building great communities.
http://flarum.org/
6.37k stars 834 forks source link

Cryptograhpically Sign releases #3968

Open maltfield opened 8 months ago

maltfield commented 8 months ago

Current Behavior

Currently it is not possible to verify the authenticity or cryptographic integrity of the downloads from flarum.org or github.com because the releases are not cryptographically signed.

This makes it hard for flarum users to safely obtain the flarum software, and it introduces them (and potentially their user's data) to watering hole attacks.

Steps to Reproduce

  1. Go to the flarum.org
  2. Click Download Now
  3. ???

Expected Behavior

A few things are expected:

  1. I should be able to download the flarum PGP key out-of-band from popular third-party keyservers (eg https://keys.openpgp.org/)
  2. I should be able to download a cryptographic signature of the release (or, better, the releases' digest file, such as a SHA256SUMS.asc file) along with the release itself
  3. The downloads page itself should include a link to the documentation page that describes how to do the above two steps

Screenshots

No response

Environment

Everything, all versions. Extensions too.

Output of php flarum info

Output of "php flarum info", run this in terminal in your Flarum directory.

Possible Solution

See "Expected Behaviour" Section

Additional Context

No response

maltfield commented 8 months ago

Many large organizations sign their releases with PGP, and some of them have written best-practices guides based on their experiences, which I recommend looking into:

  1. https://infra.apache.org/release-signing
  2. https://docs.opendev.org/opendev/system-config/latest/signing.html
  3. https://wiki.debian.org/Subkeys
  4. https://riseup.net/en/security/message-security/openpgp/best-practices

Please let me know if you have any questions regarding how to generate a PGP signing keypair, safely distribute its public key, sign your packages with this key, and how to document the process for users to cryptographically verify your release's signatures for their authenticity and integrity.

luceos commented 8 months ago

Although I understand where this is coming from and I certainly agree to improved security. It's one thing to start doing it, it's another to keep doing it. Taking extensions into this is another complexity I won't even want to think about considering they are published and maintained by third parties.

Being a small team with only a handful of skills, it might be too far reached to adopt this now. I don't know how the others feel about this, but this would definitely be something for the future and not for now.

maltfield commented 8 months ago

Let's not include extensions in the scope of this ticket. I think you'll find this ticket is very achievable. It should only add a few minutes to your release workflow.

Please let me know if I can help in any way, as it's a prereq for our org to have this (and I imagine many other orgs also will skip over Flarum since there's currently no secure way to verify it after download).

SychO9 commented 8 months ago

For reference, this is the build script for the packages: https://github.com/flarum/installation-packages/blob/main/bin/build.sh

and these are the docs: https://github.com/flarum/docs

Feel free to contribute if you would like.

maltfield commented 8 months ago

@SychO9 The signing is done after the build. Can you please tell me which of your team members are responsible for uploading the finished releases? They need to generate PGP keys following best practices, and I'm happy to assist them with this (it's just a few commands that they have to run on their personal machines; I can't do this for you in a PR because private keys should be -- private).

Is the build.sh script always executed by the same person? Or is this often handed-off between people? If it's multiple people, then you need to decide if you want to [a] have individuals sign releases with their own personal keys, or if you [b] have a shared "Flarum Release Signing Key" that's shared by all release engineers. There are many projects that choose [a] and many that choose [b]. There's security and usability trade-offs to both.

Please let me know which team members are responsible for uploading finished flarum releases.

SychO9 commented 8 months ago

@maltfield the script is never run by an individual. The script is triggered by an individual or automatically and runs on a github workflow (this is necessary).

Private keys are not a problem. GitHub allows storing secrets that can be used in workflows without exposing their values.

So feel free to contribute commands there, probably after the tar and zip commands.

Otherwise we'll look into it some point 👍

maltfield commented 8 months ago

Unfortunately it's not an option to store PGP private keys on GitHub. For release signing to be useful (release signing is done to protect against attacks like infrastructure compromise), the private keys must be stored offline; release signing private keys should not be stored on a server .

If the build script is executed in your CI process, then--after a release is made--your release engineers would just need to confirm its integrity, sign it, and then upload the signature to the release. As I said, this process will add a few minutes to your release process. Is your release process documented anywhere?

Please let me know which of your team members should be delegated the task of signing flarum releases.

luceos commented 8 months ago

Michael,

We absolutely see the benefit of implementing this, if it would not add another layer of effort or complexity to our current processes. We are not a big software team that can assign such a task to a fixed team member, our core team can be counted on one hand.

I understand that others do this and I understand it is wise given it adds another layer of security, but right now we don't have the luxury to commit to this.

We will obviously keep this issue open so that it reminds us of taking action. But we will not implement this soon. Please do understand our position on this.

With kindest regards, Daniël.

maltfield commented 8 months ago

ok, well, I'm happy to do as much of the work as I can, but obviously you do need to be able to commit to a few hours of initial setup and a few minutes per every release.

Generate PGP Key

When you have someone who has a few hours to work with me, please have them execute the following on their machine to generate a 4096-bit RSA PGP key pair.

Note: These commands are for linux; let me know if you use a different OS and I can contribute instructions accordingly

gpg --full-generate-key

When prompted, specify:

  1. 1 for RSA
  2. 4096 for key size
  3. 1y for key expiration
  4. y for "yes"

As for the name of the key, you have to decide if you want to have one key shared between all of your release engineers, or if you want to have individual keys for each person.

If you want to have one shared key, then I recommend typing Flarum Release Signing Key <YYYY.MM> for the key's Real Name prompt (replacing <YYYY.MM> with the current year & month).

If you want individual keys for each person, then type the person's full name for the Real Name prompt.

For the Email address, I recommend typing your catch-all inbox for inquiries, such as info@flarum.org. Or, if you have per-person keys, then type the person's email address.

You can leave the Comment field blank. Just press enter.

Type O for "Okay" to generate the key.

Finally, type a password that will be used to symmetrically encrypt your private key on-disk. Symmetric encryption is only as good as the password is long. I recommend using a password manager (eg KeyPassXC) to generate (and securely store) a random passprhase that's >= 20 characters long.

As an example, see the below execution of the above-listed steps

user@disp9050:~$ gpg --full-generate-key
gpg (GnuPG) 2.2.27; Copyright (C) 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
  (14) Existing key from card
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 1y
Key expires at Fri 28 Feb 2025 03:34:47 PM -05
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: Flarum Release Signing Key 2024.02
Email address: info@flarum.org
Comment: 
You selected this USER-ID:
    "Flarum Release Signing Key 2024.02 <info@flarum.org>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: key D1D9CE40E7285B3D marked as ultimately trusted
gpg: directory '/home/user/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/user/.gnupg/openpgp-revocs.d/50B80A4CE7D7C92B47DB76FDD1D9CE40E7285B3D.rev'
public and secret key created and signed.

pub   rsa4096 2024-02-29 [SC] [expires: 2025-02-28]
      50B80A4CE7D7C92B47DB76FDD1D9CE40E7285B3D
uid                      Flarum Release Signing Key 2024.02 <info@flarum.org>
sub   rsa4096 2024-02-29 [E] [expires: 2025-02-28]

user@disp9050:~$ 

Share Public Key

The execution above will generate [a] a private key (that you don't share with anyone or upload to any servers) and [b] a public key (that you share in as many places as possible; users need this to verify signatures made with your private key).

Please let me know once your release engineer(s) have generated a PGP key following the above steps. Once you do, execute the following commands and paste them into this ticket.

gpg --list-sigs
gpg --armor --export

After you paste the output from the above commands into this ticket, and then I'll be able to submit a PR with all the changes needed to implement this ticket.