wget script, aber leiten Sie es nur dann an bash weiter, wenn SHA256 des Skripts mit einem Einzeiler übereinstimmt

9

wget http://example.com/install.sh -O - | bashführt das Skript automatisch aus, ist jedoch aufgrund möglicher (TLS) MITM-Angriffe usw. nicht sicher. Ist es möglich, einen Einzeiler zu erstellen, der das Skript herunterlädt, es aber nur ausführt, wenn sein Hash mit dem im Einzeiler angegebenen übereinstimmt? Es wäre schön, wenn der Einzeiler so etwas drucken würde, Warning! Hash mismatchwenn die Hash-Prüfung fehlschlägt.

maqp
quelle
1
Der erste Schritt wäre, das Rohr herauszunehmen, um zu schlagen. Der zweite Schritt besteht darin, Sie zur Eingabe des gültigen SHA256-Codes aufzufordern. Der dritte Schritt zum Generieren aus der Datei. Der vierte, der entweder das Skript ausführt oder eine Fehlermeldung ausgibt. Eine Zeile erschwert das Lesen und Debuggen als 10 Zeilen.
WinEunuuchs2Unix
Der Grund, warum ein Einzeiler für Rohrleitungen benötigt wird, besteht darin, die Zeit zu minimieren, die das System mit dem Netzwerk verbunden bleibt. Der Hash in einem Liner muss aus einer vertrauenswürdigen Quelle stammen, so wie es ein Fingerabdruck eines öffentlichen PGP-Schlüssels tun müsste, damit er nicht manuell eingegeben werden muss. Der Einzeiler wird vom Benutzer kopiert, sodass die Lesbarkeit zweitrangig ist.
Maqp
Wie planen Sie, die Hash-Summe zur Überprüfung zu erhalten? Können Sie das bitte etwas näher erläutern? Welche Informationen können wir aus lokalen Dateien erhalten und was können wir aus der Ferne erhalten? Der Vergleich der heruntergeladenen Datei mit einer lokal gespeicherten Hash-Summe und die anschließende Ausführung nach erfolgreicher Überprüfung ist in einer Zeile möglich. Ich bin mir jedoch nicht sicher, wie viel zusätzliche Überprüfung Sie sicher erhalten möchten, um einen Hash zu erhalten.
Byte Commander
Die Wurzel des Vertrauens kann persönlich präsentiert werden. Qubes-Projekt zum Beispiel. Ich verstehe, dass dies ein wichtiger Fingerabdruck anstelle von Hash ist, daher entspricht die obige Frage nicht ganz meinen Anforderungen.
Maqp

Antworten:

6

Sie möchten also herunterladen und ausführen http://example.com/install.sh.

Im Moment gehe ich davon aus, dass Sie den SHA256-Hash lokal in einer Datei namens gespeichert haben my-sha256.txt. Die Datei enthält nur den Hash selbst und ein Zeilenumbruchzeichen im Unix-Stil, daher muss ihre Größe genau 65 Byte betragen. Sie können es erstellen, indem Sie einfach Folgendes ausführen:

sha256sum ORIGINAL_FILE.SH | grep -Eo '^\w+' > my-sha256.txt

Wie Sie diese Hash-Datei von Ihrem Entwicklungscomputer an den Client verteilen, ist nicht Teil dieser Antwort (dennoch können Sie Ihre Frage klären und mich bitten, diesen Teil basierend auf Ihren detaillierten Spezifikationen zu aktualisieren).


Der eigentliche Befehl, den Ihr Client ausführen muss, um das Skript herunterzuladen, zu überprüfen und bei Erfolg auszuführen, könnte folgendermaßen aussehen:

t=$(mktemp) && wget 'http://example.com/install.sh' -qO "$t" && if sha256sum "$t" | grep -Eo '^\w+' | cmp -s my-sha256.txt ; then bash "$t" ; else echo FAIL ; fi ; rm "$t"

Leicht verkürzte und hässliche Version ohne Leerzeichen:

t=$(mktemp)&&wget 'http://example.com/install.sh' -qO"$t"&&if sha256sum "$t"|grep -Eo '^\w+'|cmp -s my-sha256.txt;then bash "$t";else echo FAIL;fi;rm "$t"

Zur besseren Lesbarkeit in mehreren Zeilen platziert:

t=$(mktemp) && 
wget 'http://example.com/install.sh' -qO "$t" && 
if sha256sum "$t" | grep -Eo '^\w+' | cmp -s my-sha256.txt 
    then bash "$t" 
    else echo FAIL 
fi 
rm "$t"

Wenn Sie den Hash direkt im Befehl als Zeichenfolge bereitstellen möchten, anstatt aus einer Datei zu lesen, verwenden Sie einfach eine meiner obigen ursprünglichen Befehlsversionen und ersetzen Sie das Vorkommen von my-sha256.txtdurch <(echo YOUR_HASH), indem Sie Ihren echten Hash anstelle des Platzhalters "YOUR_HASH" einfügen.

Erläuterung:

Das Skript / der Einzeiler erstellt zuerst eine temporäre Datei mit mktemp(verwendet den temporären Ordner des Systems /tmp).
Anschließend wird wgetIhr Installationsskript von der angegebenen URL heruntergeladen und in der temporären Datei gespeichert.
Jetzt berechnen wir die Hash-Summe, filtern nur den Hash-Wert aus der Ausgabe von sha256sumund vergleichen diesen mit dem, was wir in out gespeichert haben my-sha256.txt.
Wenn beide Hashes gleich sind, werden wir bashmit unserer temporären Skriptdatei als Argument aufrufen , andernfalls echo FAILkönnten wir oder Sie eine benutzerdefinierte Fehlermeldung ausgeben.
Am Ende bereinigen wir in beiden Fällen unsere temporäre Datei.


Wenn Sie jedoch auf das Problem der sicheren Verteilung des Hashs zur Überprüfung des ursprünglichen Skripts zurückkommen, hilft Ihnen diese obige Lösung nicht viel, da sie ein Problem löst, indem ein anderes der gleichen Art erstellt wird.

Was Sie eigentlich tun sollten, ist, ein GPG-Schlüsselpaar zu erstellen (und Ihren öffentlichen Schlüssel auf einem Schlüsselserver zu veröffentlichen), Ihr Skript damit zu signieren und die komprimierte signierte Binärdatei zum Download anzubieten. Lassen Sie dann den Client das Skript gpgerneut überprüfen und entschlüsseln und führen Sie es bei Erfolg aus.

Byte Commander
quelle
Das funktioniert super! Mir ist aufgefallen, dass Ihr ungekürzter Einzeiler '^\w+ 'stattdessen greift '^\w+', was nicht funktioniert. Das einzige, was für meine Bedürfnisse fehlt, ist die Angabe des SHA256-Hash innerhalb des Einzeilers. Gibt es einen saubereren Weg, dies zu tun als h=$(mktemp); t=$(mktemp); echo '14b652ef7e7a5b3ae92351ee9695bce956a904db562f16a7c48cfcd3f4b7c937' > $h; wget 'https://example.com/install.sh' -qO "$t" && if sha256sum "$t" |grep -Eo '^\w+' |cmp -s $h ; then bash "$t" ; else echo ERROR: Invalid SHA256 hash ; fi ; rm "$t"; rm "$h";?
Maqp
Mein Fall hat eine Race-Bedingung für Systemkompromisse vom Punkt, den Benutzer install.sh herunterlädt, bis zum Punkt install.sh, der Netzwerkschnittstellen beendet. Manueller Programm- / Schlüssel- / Signatur-Download, Schlüsselimport, Signaturüberprüfung, Entpacken, Navigation und Ausführung von install.sh verschwenden viel Zeit. Der SHA256-Einzeiler erhöht das Vertrauen zwischen den Downloads, ändert sich jedoch für jede Version meines Programms. Ich brauche also wahrscheinlich einen Einzeiler mit angeheftetem PGP-Fingerabdruck, der den Schlüssel herunterlädt und importiert, den Fingerabdruck vergleicht und dann install.sh und seine Signatur herunterlädt, die Datei überprüft und dann install.sh an bash weiterleitet.
Maqp
1
@maqp Ich verstehe immer noch nicht ganz, was Ihr eigentliches Ziel ist und warum Sie sich so ungewöhnliche Einschränkungen setzen. Vielleicht wäre es hilfreich, wenn Sie das Gesamtbild Ihrer Aktivitäten teilen könnten? Ich kann Ihnen auch nur empfehlen, den Chatraum zu besuchen . Es ist wahrscheinlich einfacher, dort einen schnellen Dialog zur Klärung zu führen und von vielen Leuten dort Input zu erhalten.
Byte Commander
2
Ich glaube, ich habe es verstanden:gpg --keyserver pgp.mit.edu --recv-keys <GPG pub key SHA1 fingerprint> && wget https://example.com/install.sh{,.asc} -q && gpg --verify install.sh{.asc,} && bash install.sh
Maqp
1
@maqp Vielleicht möchten Sie dies als separate Antwort zur besseren Lesbarkeit veröffentlichen? Die eingeschränkten Formatierungsoptionen in Kommentaren machen es hier etwas schwierig.
Byte Commander
0

Da GPG-Fingerabdrücke unsicheren SHA-1-Hash verwenden , handelt es sich hier um einen Einzeiler, der die Authentifizierung mit inoffiziellem SHA256-Hash ermöglicht, der aus dem öffentlichen Schlüssel mit berechnet wird

gpg --export <key ID> | sha256sum

Befehl:

h="<SHA256 hash of exported public key>"; fp="<PGP key SHA1 fingerprint>"; f='key.pub'; gpg --keyserver pgp.mit.edu --recv $fp && gpg --export $fp > $f && if sha256sum $f | grep -Eo '^\w+' | cmp -s <(echo $h); then rm $f && wget https://example.com/install.sh{,.asc} -q && gpg --verify install.sh{.asc,} && bash install.sh; else rm $f; echo "ERROR: Signing key had invalid SHA256 hash"; fi;

maqp
quelle