ipfs-desktop icon indicating copy to clipboard operation
ipfs-desktop copied to clipboard

Hardening Updates with Content-Addressing and IPNS

Open lidel opened this issue 6 years ago • 5 comments

Use of Electron Builder's Auto Update is tracked in https://github.com/ipfs-shipyard/ipfs-desktop/issues/668.

This is a placeholder issue about hardening the Auto Update process by introducing an additional IPFS-based integrity check that does not depend on Electron Builder service based on GitHub Releases.

We will create a proper threat model when Security WG is formed later in 2019, for now let's assume scenario where malicious update gets published via GitHub Releases.

Potential mitigation:

  1. Detect update happened
  2. Validate binary before first run:
    1. Get the CID of the local file via ipfs add --only-hash <local go-ipfs binary>
    2. Compare against <expected CID (source to be determined)> (value should be independent of GitHub Releases)

Impacted users:

  • Mac and Windows users (Electron Builder's Auto Update)
  • Linux/*BSD users that do not use Snap package, but installed update from distribution-specific package created by third party developers.
  • Users that choose to manually update the go-ipfs binary or using the ipfs-update tool

Open questions:

  • [ ] How to detect auto update happened?
  • [ ] Should we also detect go-ipfs binary changed? (check before every run)
  • [ ] How to handle js-ipfs? (no fat binary)
  • [ ] What will be the source of "valid" CIDs of go-ipfs binaries? IPNS?
    • Right now http://dist.ipfs.io provides CID of .zip/.gz archive (example), which is not useful for this exact case, but we could create something similar for unpacked binaries and publish it on IPNS under known key (lack of DNSLink removes the risk of DNS MITM and replaces it with pure IPNS+IPFS integrity guarantees)

lidel avatar Jan 09 '19 14:01 lidel

This is the model most software use for auto-update:

Code-sign the installer package with a known code signing certificate. Download the update and verify the signature before executing. Open an error page on the web if validation fails (URL hardcoded in the installed copy for this purpose - https://$url/?ver=$installed_ver&downloaded_hash=$downloaded_package_hash) that provides debugging information in the URL and offer users advise on manual updates. Trust and run the installer if it validates.

The code signing certificate should be kept in offline storage by two trusted developers and only be connected to a networked PC for the time it takes to sign the installer.

In other words, it's the auto-update downloader that should be responsible for validating that it downloaded a correctly signed package before running it. You can't rely on a secure distribution channel alone.

da2x avatar Jan 11 '19 21:01 da2x

Electron Builder allows us to use a generic provider although it does not specify which methods it should provide and how it works. I'll dig a bit into it. It would be nice to be possible to move away from GitHub to our own platform to have less concerns (#1189).

/cc @lidel @autonome

hacdias avatar Oct 30 '19 21:10 hacdias

According to those docs, we can specify several publishers in electron-builder. It sounds like a nice migration path: when we are sure self-hosted is stable, we can make it the new default (by making it first on the list) while also publishing manifest to github, so older version can pick it up and migrate away. We need to be careful tho, to not break autoupdate along the way – perhaps test new update mechanism with a separate app first?

@hacdias if you can, look into genric provider (a HTTPS server) – we should be able to set it up under *.ipfs.io. IIUC this is a matter of putting binaries and .yml manifests on a specific URL path.

Perhaps we could add autoupdate manifest to existing DNSLink website at dist.ipfs.io (ipfs/distributions)? If not, something like autoupdates.ipfs.io should be created.

lidel avatar Oct 30 '19 21:10 lidel

IPFS updates over IPFS! This issue shows how to pull the logic for fetching the update zip into our code, and then just pass the electron / squirrel update framework the zip and an artisinal, smol batch, locally made UPDATE manifest.

https://github.com/electron/electron/issues/5020#issuecomment-477636990

How to signal when a update is ready needs deciding on, but we could then attempt to fetch the zip via IPFS. If it fails for any reason, we could fall back to https, or just nudge the user that their IPFS is borkd, which seems kinda reasonable given desktops remit is to keep your IPFS node running.

I'd love to reduce our dependency on electron builder. It has caused us numerous issues over time.

olizilla avatar Jul 01 '20 08:07 olizilla

Some relevant notes in https://github.com/ipfs/ipfs-desktop/issues/1263#issuecomment-1386168223

lidel avatar Jan 17 '23 22:01 lidel