Reproduceerbare builds: Van broncode tot binair pakket zonder achterpoortjes
- November 15, 2017
- 0
Één van de voordelen van open source software is, dat je de broncode kunt bekijken om te controleren of er geen achterpoortjes in zitten. Maar slechts weinigen bouwen zelf hun volledige distributie op basis van die broncode. Hoe weet je zeker of de binaire pakketten van je distro wel uit de overeenkomstige broncode voortkomen? Met reproduceerbare builds verifieer je of er geen achterpoortje is ingeslopen.
Als lezer van Linux Magazine begrijp je natuurlijk het belang van toegang tot de broncode van software. Je hebt daarmee onder andere de vrijheid om de software aan te passen. Maar je kunt ook nakijken of de software je privacy respecteert en of er geen achterpoortjes in zitten. Maar net zoals slechts een fractie van de open source gebruikers zelf de broncode van software aanpast, zo controleert maar een minderheid van de gebruikers of de software die ze draaien wel voortkomt uit de overeenkomstige broncode. Het enige “bewijs” dat we van die correspondentie hebben, is dat iemand zegt dat het zo is; de distributie of het bedrijf dat de binaire pakketten aanbiedt.
Maar zelfs al vertrouw je de ontwikkelaars van je distributie blindelings (ook al kun je dat beter niet doen), het is altijd mogelijk dat een aanvaller erin geslaagd is om in de infrastructuur van je favoriete distributie in te breken en de binaire pakketten aan te passen. Dat is geen ondenkbaar scenario. In november 2012 gebruikte iemand een gelekte SSH-sleutel om in de servers van het FreeBSD-project in te breken (www.freebsd.org/news/2012-compromise.html), waardoor hij toegang had tot de third-partypakketten. Gelukkig bleek na controle dat er geen bestanden waren aangepast. In hetzelfde jaar werd op een conferentie van de CIA (theintercept.com/2015/03/10/ispy-cia-campaign-steal-apples-secrets/) een aangepaste versie van Xcode gedemonstreerd, die backdoors introduceerde in iOS-apps of OS X-programma’s, die ermee werden gebouwd. En onlangs nog kwam Linux Mint in het nieuws, omdat een aanvaller erin was geslaagd om op de website van de populaire distro naar een ISO-bestand met backdoor te verwijzen.
Als je die correspondentie tussen broncode en binair bestand nou zou willen verifiëren, dan stuit je al snel op een boel uitdagingen. Zonder te weten met welke compiler en met welke optimalisatie-instellingen de software is gecompileerd, welke library-versies er zijn gebruikt enzovoort, is het niet mogelijk om aan die taak te beginnen. Want je zou met exact dezelfde configuratie de broncode moeten kunnen compileren en dan vergelijken of het resulterende binaire bestand identiek is aan de software, die je hebt gedownload. En als je exact weet welk buildsysteem er is gebruikt, beginnen de grote uitdagingen pas. Kortom, we maken momenteel niet gebruik van alle mogelijkheden die open source software ons biedt.
Hoe klein kan een backdoor zijn?
Om een backdoor te creëren, hoef je niet altijd grote wijzigingen in het binaire bestand door te voeren. Zo kreeg OpenSSH 3.0.2 met een fout te maken (CVE-2002-0083) waarbij gebruikers root konden worden. De fout in de broncode was subtiel: er stond in een vergelijking > in plaats van >=. De patch in de broncode om de fout op te lossen was dan ook klein. In assembler was het verschil nog kleiner: de opdracht jle 30 werd vervangen door jl 30. Na compilatie werd die eerste assembleropdracht omgezet in de opcode 0x7e en die tweede in 0x7c. In het binaire talstelsel is dat respectievelijk 01111110 en 01111100, of slechts één bit verschil! Kortom, als een aanvaller geluk heeft, hoeft hij maar één bit in een binair bestand te veranderen om een root exploit te introduceren…
Bitcoin
In 2000 werd het idee van reproduceerbare builds al vermeld op de debian-devel mailinglist (lists.debian.org/debian-devel/2000/11/msg01758.html), maar niemand zag het potentieel. In 2007 kwam het onderwerp wederom onder de aandacht, toen Martin Uecker op diezelfde mailinglist (lists.debian.org/debian-devel/2007/09/msg00746.html) opwierp:
“I think it would be really cool if the Debian policy required that packages could be rebuilt bit-identical from source. At the moment, it is impossible to independently verify the integrity of binary packages.”
Maar ook deze keer waren de reacties lauw. De consensus leek te zijn: het zou inderdaad mooi zijn om reproduceerbare builds te hebben, maar het is praktisch niet haalbaar.
Één van de eerste projecten, dat de ernst van de zaak inzag en zich aan een implementatie waagde, was Bitcoin (bitcoin.org). Kwaadaardige aanpassingen in de Bitcoin-client leiden immers mogelijk tot onherroepelijke diefstal van grote hoeveelheden geld. Daarom creëerden de ontwikkelaars Gitian (gitian.org), een systeem waarmee je de Bitcoin-broncode compileert en de resulterende binary kunt vergelijken met het resultaat van anderen, die hetzelfde deden.
Ook het Tor-project, met zijn focus op anonimiteit en veiligheid, was een voorloper van reproduceerbare builds. In de nasleep van Edward Snowden’s onthullingen over surveillance door overheden, begon Mike Perry in 2013 aan een initiatief om de Tor Browser reproduceerbaar te maken (blog.torproject.org/blog/deterministic-builds-part-one-cyberwar-and-global-compromise) met de hulp van Gitian.
Pas door de successen van een reproduceerbare Bitcoin en Tor Browser begonnen anderen te geloven dat het mogelijk was om grotere codebases reproduceerbaar te maken. Enkele Debian-ontwikkelaars begonnen in 2013 te discussiëren over het onderwerp: zou het niet cool zijn als elke gebruiker van de 22.000 bronpakketten van Debian allemaal kan verifiëren of de binary, die hij heeft geïnstalleerd, wel de gecompileerde versie van het bronpakket is?
Deterministische builds
Gitian werkt eenvoudig: je compileert het pakket in een virtuele machine, die voor iedereen hetzelfde is, met dezelfde Linux kernel. Om verschillen in timestamps te voorkomen, maakt het project gebruik van libfaketime. Maar uiteindelijk is deze aanpak slechts een lapmiddel. Daarom besloten de Debian-ontwikkelaars om het anders aan te pakken. Ze wilden de tools en buildsystemen fixen (wiki.debian.org/ReproducibleBuilds/ExperimentalToolchain) en slechts als het echt niet anders kan naar lapmiddelen teruggrijpen.
Één van de manieren waarop dat gebeurt, is met de tool strip-nondeterminism. Deze normaliseert non-deterministische gegevens in bestanden in het buildproces, zoals een timestamp, de volgorde van bestanden, de hostnaam, gebruiker en groep, locale, namen van tijdelijke bestanden, enzovoorts. De ontwikkelaars sturen patches om pakketten reproduceerbaar te maken naar de maintainers van de pakketten, zodat uiteindelijk heel Debian reproduceerbaar zou moeten worden.
Builds die identiek zouden moeten zijn, verschillen vaak door timestamps in de binary
Zo krijgt veel software een timestamp als “build date”, maar het interesseert de eindgebruiker niet wanneer de software gebouwd is. Als je dan toch een timestamp in je binary wilt opnemen, dan is een beter alternatief het tijdstip van de laatste wijziging van de broncode. Dat is nuttige informatie én het blijft ongewijzigd als je dezelfde versie van de broncode opnieuw compileert. Debian heeft daarvoor de specificatie SOURCE_DATE_EPOCH (reproducible-builds.org/specs/source-date-epoch/) voorgesteld. SOURCE_DATE_EPOCH is gedefinieerd als het tijdstip van de laatste wijziging van de broncode sinds 1 januari 1970. Ondertussen hebben ook NetBSD, FreeBSD, Arch Linux en Guix deze aanpak overgenomen.
Verder is het bijna onmogelijk om een identieke binary uit broncode te genereren als de build-omgevingen niet genoeg op elkaar lijken. Daarom heeft Debian een nieuw bestand in het buildproces geïntroduceerd, .buildinfo (wiki.debian.org/ReproducibleBuilds/BuildinfoSpecification). Dit bevat onder andere de checksums van bronbestanden, gegenereerde binaries, de build dependencies en hun versies. Dit bestand kan later worden gebruikt om een identieke buildomgeving na te bouwen als je het pakket bit-voor-bit identiek wilt compileren.
Bij het onderzoeken welke problemen in een bepaald pakket reproduceerbaarheid in de weg staan, is de tool Diffoscope (diffoscope.org) handig. Diffoscope toont recursief de verschillen tussen twee archieven. Dat betekent dat je twee tar.gz-bestanden aan de tool kunt doorgeven, die beide gz-bestanden uitpakt, de directory’s in de tar-bestanden recursief afloopt en alle verschillen toont in een vorm, die voor ons mensen leesbaar is, naar keuze in platte tekst of HTML.
Hoe staan we ervoor?
Ondertussen hebben ontwikkelaars van diverse distributies en andere projecten zich verzameld in het Reproducible Builds (reproductible-builds.org) project. Deelnemende projecten zijn naast Debian ook coreboot, OpenWrt, NetBSD, FreeBSD, ElectroBSD, Arch Linux, Fedora, Baserock, Bitcoin, Tor Browser, F-Droid, NixOS en Guix.
Het Reproducible Builds project heeft statistieken (tests.reproducible-builds.org) van reproduceerbare pakketten van de verschillende deelnemende projecten online staan. Je krijgt er te zien hoever de projecten staan met het reproduceerbaar maken van hun pakketten, want alle pakketten worden er continu getest op hun reproduceerbaarheid. Bovendien is te zien wat de meest voorkomende problemen zijn en kun je per pakket de eventuele problemen bekijken.
Al 86% van de Debian-pakketten zijn reproduceerbaar
Het is verbazingwekkend wat voor een grote vooruitgang dit jonge project al heeft gemaakt. Ten tijde van de redactiesluiting zijn al 86% van de Debian-pakketten voor amd64 reproduceerbaar. Van de pakketten, die in de distributie als “required” staan aangeduid, zijn er nog maar 68% reproduceerbaar. Het is de bedoeling dat na Debian 9 (stretch) de Debian Policy (www.debian.org/doc/debian-policy) een nieuwe sectie 4.15 krijgt, “Sources must build reproducible binaries.” En aangezien Debian de moeder is van talloze afgeleide Linux-distributies (inclusief Ubuntu en Linux Mint) zal dit snel een grote impact hebben.
Enkele ontwikkelaars slaagden er zelfs al in 2013 in om 60% van de FreeBSD ports reproduceerbaar te maken. FreeBSD base is ondertussen bijna volledig reproduceerbaar. Het is niet verbazingwekkend dat kleinere projecten sneller volledige reproduceerbaarheid benaderen. Van de coreboot images zijn momenteel 98% reproduceerbaar. Van de OpenWrt-pakketten is 99,7% reproduceerbaar en van de images 12%.
Ben je zelf een maintainer of ontwikkelaar van een open source pakket? Werp dan eens een blik op de documentatie (reproducible-builds.org/docs/) van het Reproducible Builds project. Je vindt er uitleg over hoe je je pakket reproduceerbaar maakt. Vaak vereist dat slechts kleine veranderingen. Ook specifiek voor Debian vind je een how to (wiki.debian.org/ReproducibleBuilds/Howto) op de wiki van de distributie.
Macht aan de gebruiker
Maar het is niet voldoende om zoveel mogelijk pakketten reproduceerbaar te maken. De gebruikers moeten de reproduceerbaarheid ook eenvoudig kunnen nagaan. Zo zou de package manager een waarschuwing kunnen geven als je op het punt staat om een pakket te installeren dat (nog) niet reproduceerbaar is, zoals:
“Package foo is unreproducible. Do you really want to install it? (y/N)”
Of je zou in de instellingen van je package manager kunnen ingeven of je onreproduceerbare software al dan niet wilt installeren, zodat je die vraag niet meer te zien krijgt.
Het is overigens niet de bedoeling dat gebruikers elke keer dat ze een pakket installeren eerst de broncode compileren om dan na te gaan of het resultaat identiek is aan het te installeren pakket. Dan kunnen ze immers even goed gewoon alle pakketten, die ze willen installeren, zelf compileren! Maar als genoeg gebruikers zo nu en dan voor pakketten, die ze belangrijk vinden, controleren of de binary reproduceerbaar is uit de broncode, verkrijgen we een gedistribueerde controle. Als de distributie dan ook een systeem opzet, waarbij de gebruikers checksums van de door hen gegenereerde binaries online plaatsen, kun je bijvoorbeeld aangeven dat je een pakket van je distributie slechts vertrouwt als genoeg gebruikers bij hun verificatie dezelfde checksum hebben als het pakket dat je wilt installeren.
Een ander interessant toekomstbeeld is het reproduceerbaar maken van installatiemedia. Je kunt immers wel zeker zijn dat alle pakketten uit de officiële broncode voortkomen, maar als iemand in het ISO-bestand, waarmee je de distributie installeert, een backdoor heeft gestoken (zoals recent met Linux Mint gebeurde), dan heb je nog geen zekerheid. Kleinere projecten zoals coreboot en OpenWrt bieden al reproduceerbare images aan, maar voor complexere distributies zoals Debian is het een grote uitdaging.
Eigenlijk zouden reproduceerbare builds de norm moeten zijn. De snelle vooruitgang die Debian maakt, stemt ons gelukkig hoopvol. Wie weet zijn reproduceerbare builds over enkele jaren heel normaal en vinden we het vreemd als een distributie dit niet aanbiedt…