I am seeing quite a bit of misinformation about how package managers work so I'd love to share what I have learned. I work with index files on a daily basis, and we might possibly generate more index files than any other organization on the planet. Here is my chance to share some of this knowledge!
TLDR/Summary

We can trust the Release file because it was signed by Ubuntu. We can trust the Packages file because it has the correct size and checksum found in the Release file. We can trust the package we just downloaded because it is referenced in the Packages file, which is referenced in the Release file, which is signed by Ubuntu.

Some basic package manager principles

I work with APK, DEB, and RPM based package managers and each of them behave very similar. Each repository has a top level file, signed by the repository's maintainer, that includes a list of files found in the repository and their checksums. When your package manager does an update, it looks for this top level file.

For DEB based systems, this is the Release file

For APK based systems, this is the APKINDEX.tar.gz file

For RPM based systems, this is the repodata.xml file

These files are all signed by the repository's gpg key. So the Release file found athttp://us.archive.ubuntu.com/ubuntu/dists/bionic/Release and is signed by Ubuntu and the gpg key is included in your distribution. Let's hope Ubuntu doesn't let their gpg key into the wild. Assuming that Ubuntu's gpg key is safe, this means that the system can verify that the Release file did in fact come from Ubuntu. If you are interested, you can click on the previous link, or navigate to Ubuntu's repository and open up one of their Release files.

Release file

In the Release file you'll see a list of files and their checksum. Example:55f3fa01bf4513da9f810307b51d612a 6214952 main/binary-amd64/Packages

9f666ceefac581815e5f3add8b30d3b9 1343916 main/binary-amd64/Packages.gz

706fccb10e613153dc61a1b997685afc 96 main/binary-amd64/Release

9eae32e7c5450794889f9c3272587f5e 1019132 main/binary-amd64/Packages.xz

5dd0ca3d1cbce6d2a74fcc3e1634ac12 96 main/binary-arm64/Release

The left column is the checksum, then the size of the file, and lastly the location of the file. So we can download the files referenced in the Release file and check them for the correct size and checksum. The Packages or Packages.gz file is the one we care about in this example. It contains information about the packages available to the package manager (apt in this case but again, almost all of the package managers behave very similar).

Packages file

Since we know that we can trust the Release file (because we have proven it was signed by Ubuntu's gpg key), we can then proceed to download the contents of the Release file. Let's look at the Packages file specifically as it contains a list of packages, their size, and checksum.

Filename: pool/main/a/accountsservice/accountsservice_0.6.45-1ubuntu1_amd64.deb

Size: 62000

MD5sum: c2cffd1eb66b6392f350b474e583adba

SHA1: 71d89bd380a465397b42ea3031afa53eaf91661a

SHA256: d0b11d1d27fe425bc91ea51fab74ad45e428753796f0392e446e8b2450293255

The Packages file includes a list of packages with information about where the file can be found, the size of the file, and various checksums of the file. If you download a file through commands like apt install and any of these fields are incorrect, apt will throw an error and not add it to the apt database.

It's time to debunk some myths!

Can an attacker send me a fake Release file?

Sure, but apt will throw it out because it's not signed by Ubuntu (or whoever your repository maintainer is like centos, rhel, alpine, etc)

Can an attacker send me an old index from an earlier date that was signed by Ubuntu that has old packages in it with known exploits?

Sure, but apt will throw it out because it will have a date (in the Release file) that is older than what is stored in the apt database. For example, the current bionic main Release file has this date in it: Date: Thu, 26 Apr 2018 23:37:48 UTC So if you supply it with a Release file older than that timestamp, it will throw it out because it is older than what it currently knows about.

I hope this helps clear the air!

Shameless plug. If you are serious about security and not just compliance, check out our Polymorphic Linux repositories. https://polyverse.io/ We provide "scrambled" or "polymorphic" repositories for Alpine, Centos, Fedora, RHEL, and Ubuntu. We use the original source packages provided in the official repositories and build the packages but with memory locations in different places and ROP chains broken.

Installation

Installation is a one line command that installs our repository in your sources.list or repo file. There is no agent or running process installed. It is literally just adding our repository to your installation. The next time you do an `apt install httpd` or `yum install docker` you'll get a polymorphic version of the package from our repository. You can see it in action in your browser with our demo: https://polyverse.io/learn/

What does it do?

Many of the replies in this post referenced an attacker tricking a server into an older version of a package that has a known exploit. We stop this. Even if you are running an old version of a package, with a known exploit, memory based attacks will not work on the scrambled package because the ROP chain has been broken or as we call it "scrambled". So with our packages, you can run older versions of a package and not be effected by the known exploits. This also means that you are protected from zero day attacks just by having our version of the package.

FREE! For individuals and open source organizations you can use our repositories for free. I hope you try it out!