Frage

Das ist wahrscheinlich noch nie in der realen Welt passiert und kann niemals passieren, aber schauen wir uns das an: Sagen Sie, Sie hätten ein Git-Repository, verpflichten Sie sich und lassen Sie sich sehr sehr unglücklich: einer der Blobs endet mit demselbenSHA-1 als ein anderes, das bereits in Ihrem Repository ist.Frage ist, wie würde dies git handhaben?Einfach versagen?Finden Sie einen Weg, um die beiden Blobs zu verknüpfen, und überprüfen Sie, welches nach dem Kontext benötigt wird?

mehr ein Gehirn-Teaser als ein echtes Problem, aber ich fand das Thema interessant.

War es hilfreich?

Lösung

Ich habe ein Experiment gemacht, um herauszufinden, wie sich Git in diesem Fall verhalten würde. Dies ist mit Version 2.7.9 ~ RC0 + Next.20151210 (Debian-Version). Ich habe grundsätzlich nur die Hash-Größe von 160 Bit bis 4-Bit reduziert, indem ich den folgenden differig anwenden und git wiederaufbaut habe: generasacodicetagpre.

Dann habe ich ein paar begangen und bemerkte die folgenden.

    .
  1. Wenn ein Blob bereits mit demselben Hash existiert, erhalten Sie überhaupt keine Warnungen. Alles scheint in Ordnung zu sein, aber wenn Sie sich drängen, jemand klingt oder Sie wiederkehren, verlieren Sie die neueste Version (in Übereinstimmung mit dem, was oben erläutert wird).
  2. Wenn ein Baumobjekt bereits vorhanden ist und Sie einen Blob mit demselben Hash erstellen: Alles scheint normal zu sein, bis Sie entweder versuchen, sich zu drücken oder zu jemandem, der Ihr Repository klingt. Dann werden Sie sehen, dass der Repo beschädigt ist.
  3. Wenn ein Commit-Objekt bereits vorhanden ist und Sie einen Blob mit demselben Hash erstellen: gleich wie # 2 - beschädigt
  4. Wenn ein BLOB bereits vorhanden ist und Sie ein Commit-Objekt mit demselben Hash erstellen, fehlt es beim Aktualisieren der "Ref".
  5. Wenn bereits ein Blob vorhanden ist und Sie ein Baumobjekt mit demselben Hash erstellen. Beim Erstellen des Commits wird es versagen.
  6. Wenn ein Baumobjekt bereits vorhanden ist und Sie ein Commit-Objekt mit demselben Hash erstellen, fehlt es beim Aktualisieren des "Ref".
  7. Wenn ein Baumobjekt bereits existiert und Sie ein Baumobjekt mit demselben Hash erstellen, scheint alles in Ordnung zu sein. Wenn Sie jedoch begehen, wird das gesamte Repository den falschen Baum verweisen.
  8. Wenn ein Commit-Objekt bereits vorhanden ist und Sie ein Commit-Objekt mit demselben Hash erstellen, wird alles in Ordnung erscheinen. Aber wenn Sie sich begehen, wird das Commit niemals erstellt, und der Kopfzeiger wird in ein altes Commit verschoben.
  9. Wenn ein Commit-Objekt bereits vorhanden ist und Sie ein Baumobjekt mit demselben Hash erstellen, fehlt es beim Erstellen des Commit.

    für # 2 Sie erhalten in der Regel ein Fehler, wenn Sie "Git Push" ausführen: generasacodicetagpre.

    oder: generasacodicetagpre.

    Wenn Sie die Datei löschen und dann "Git Checkout File.txt" ausführen.

    Für # 4 und # 6 erhalten Sie in der Regel ein Fehler folgendermaßen: generasacodicetagpre.

    beim Laufen "git Commit". In diesem Fall können Sie in der Regel einfach "git Commit" erneut eingeben, da dies einen neuen Hash erstellt (wegen des geänderten Zeitstempels)

    Für # 5 und # 9 erhalten Sie in der Regel ein Fehler folgendermaßen: generasacodicetagpre.

    beim Laufen "git Commit"

    Wenn jemand versucht, Ihr korruptes Repository zu klonen, sehen sie normalerweise etwas wie: generasacodicetagpre.

    was mir "Sorgen" ist, dass in zwei Fällen (2,3) das Repository ohne Warnungen korrupt wird, und in 3 Fällen (1,7,8) erscheint alles in Ordnung, aber der Inhalt der Repository ist anders als was Sie erwarten es. Menschen, die klonen oder ziehen, haben einen anderen Inhalt als das, was Sie haben. Die Fälle von 4,5,6 und 9 sind in Ordnung, da es mit einem Fehler aufhört. Ich nehme an, es wäre besser, wenn es mit einem Fehler zumindest in allen Fällen mit einem Fehler fehlgeschlagen wäre.

Andere Tipps

Ursprüngliche Antwort (2012) (siehe shattered.io 2017 SHA1-Kollision unten)

Diese alte (2006) Antwort von Linus ist möglicherweise immer noch relevant:

Nein. Wenn es das gleiche SHA1 hat, bedeutet dies, dass wir, wenn wir das Objekt vom anderen Ende erhalten, das bereits vorhandene Objekt nicht überschreiben.

Wenn also jemals eine Kollision auftritt, wird das " frühere "Objekt in einem bestimmten Repository immer überschrieben. Beachten Sie jedoch, dass" früher "offensichtlich pro Repository in dem Sinne ist, dass es sich um das Git-Objekt handelt Das Netzwerk generiert eine DAG, die nicht vollständig geordnet ist. Während sich verschiedene Repositorys darüber einig sind, was bei direkter Abstammung "früher" ist, haben möglicherweise zwei verschiedene Repos die beiden erhalten, wenn das Objekt durch separate und nicht direkt verwandte Zweige gekommen ist Objekte in unterschiedlicher Reihenfolge.

Aus Sicherheitsgründen ist das "frühere Überschreiben" jedoch genau das, was Sie wollen: Denken Sie daran, dass Sie nach dem Git-Modell in erster Linie nur Ihrem eigenen Repository vertrauen sollten.
Wenn Sie also einen "git pull" erstellen, sind die neuen eingehenden Objekte per Definition weniger vertrauenswürdig als die Objekte, die Sie bereits haben, und als solche wäre es falsch, ein neues Objekt zuzulassen Ersetzen Sie eine alte.

Sie haben also zwei Kollisionsfälle:

  • die versehentliche Art , bei der Sie irgendwie sehr, sehr unglücklich sind und zwei Dateien am Ende dieselbe SHA1 haben.
    Zu diesem Zeitpunkt wird beim Festschreiben dieser Datei (oder beim Ausführen eines "git-update-index", um sie in den Index zu verschieben, aber noch nicht festgeschrieben) der SHA1 des neuen Inhalts berechnet, jedoch , da er übereinstimmt Bei einem alten Objekt wird kein neues Objekt erstellt, und der Commit-or-Index zeigt auf das alte Objekt .
    Sie werden es nicht sofort bemerken (da der Index mit dem alten Objekt SHA1 übereinstimmt und das bedeutet, dass so etwas wie "git diff" die ausgecheckte Kopie verwendet), aber wenn Sie jemals einen Diff auf Baumebene machen (oder Sie machen einen klonen oder ziehen oder ein Auschecken erzwingen) Sie werden plötzlich feststellen, dass sich diese Datei in etwas völlig anderes geändert hat, als Sie erwartet hatten.
    Sie würden diese Art von Kollision also im Allgemeinen ziemlich schnell bemerken.
    In verwandten Nachrichten stellt sich die Frage, was gegen die versehentliche Kollision zu tun ist.
    Lassen Sie mich zunächst die Leute daran erinnern, dass die versehentliche Art der Kollision wirklich sehr, sehr, sehr unwahrscheinlich ist, also werden wir sie höchstwahrscheinlich nie in der gesamten Geschichte des Universums sehen.
    Aber wenn es passiert, ist es nicht das Ende der Welt: Was Sie höchstwahrscheinlich tun müssten, ist nur die Datei zu ändern, die leicht kollidierte, und einfach ein neues Commit mit den geänderten zu erzwingen Inhalt (fügen Sie einen Kommentar mit der Aufschrift "/* This line added to avoid collision */" hinzu) und bringen Sie git dann die magische SHA1 bei, die sich als gefährlich erwiesen hat.
    In ein paar Millionen Jahren müssen wir vielleicht ein oder zwei "vergiftete" SHA1-Werte zu git hinzufügen. Es ist sehr unwahrscheinlich, dass es sich um ein Wartungsproblem handelt;)

  • Die Kollision eines Angreifers , weil jemand SHA1 gebrochen (oder brutal erzwungen) hat.
    Dieser ist eindeutig viel wahrscheinlicher als der unbeabsichtigte, aber per Definition ist er immer ein "entferntes" Repository. Wenn der Angreifer Zugriff auf das lokale Repository hätte, hätte er viel einfachere Möglichkeiten, Sie zu vermasseln.
    In diesem Fall ist die Kollision kein Problem : Sie erhalten ein "schlechtes" Repository, das sich von dem unterscheidet, was der Angreifer beabsichtigt hat, aber da Sie es nie tatsächlich verwenden werden Sein kollidierendes Objekt unterscheidet sich buchstäblich nicht von dem Angreifer, der überhaupt keine Kollision gefunden hat , sondern nur das Objekt verwendet, das Sie bereits hatten (dh es entspricht zu 100% dem "Trivialen").

Kollision der identischen Datei mit demselben SHA1).

Die Frage Die Verwendung von SHA-256 wird regelmäßig erwähnt, aber vorerst nicht umgesetzt (2012).
Hinweis: Ab 2018 und Git 2.19 wird der Code für die Verwendung von SHA-256 überarbeitet.


Hinweis (Humor): Sie können ein Commit für ein bestimmtes SHA1 -Präfix mit dem Projekt gitbrute von Brad Fitzpatrick (bradfitz) .

gitbrute erzwingt ein Paar von Autoren- + Committer-Zeitstempeln so, dass das resultierende Git-Commit das gewünschte Präfix hat.

Beispiel: https://github.com/bradfitz/deadbeef


Daniel Dinnyes weist darauf hin, dass in den Kommentaren zu 7.1 Git Tools - Revisionsauswahl , einschließlich:

Es besteht eine höhere Wahrscheinlichkeit, dass jedes Mitglied Ihres Programmierteams in derselben Nacht von Wölfen in nicht verwandten Vorfällen angegriffen und getötet wird.


Auch in jüngerer Zeit (Februar 2017) shattered.io wurde die Möglichkeit des Fälschens eines SHA1-Kollision:
(Weitere Informationen finden Sie in meiner separaten Antwort , einschließlich des Google+ Posts von Linus Torvalds.)

  • a / erfordert immer noch über 9.223.372.036.854.775.808 SHA1-Berechnungen. Dies erforderte eine Prozessorleistung von 6.500 Jahren Einzel-CPU-Berechnungen und 110 Jahren Einzel-GPU-Berechnungen.
  • b / würde eine -Datei (mit demselben SHA1) fälschen, aber mit der zusätzlichen Einschränkung würden deren Inhalt und Größe den identischen SHA1 erzeugen (eine Kollision mit dem Inhalt) allein reicht nicht aus): siehe " Wie wird der Git-Hash berechnet? "): a blob SHA1 wird basierend auf dem Inhalt und Größe berechnet.

    Siehe " Lebensdauer kryptografischer Hash-Funktionen " von Valerie Anita Aurora für mehr.
    Auf dieser Seite stellt sie fest:

    Google hat 6500 CPU-Jahre und 110 GPU-Jahre aufgewendet, um alle davon zu überzeugen, dass wir SHA-1 nicht mehr für sicherheitskritische Anwendungen verwenden müssen.
    Auch weil es cool war

    Weitere Informationen finden Sie in meiner separaten Antwort unten .

nach pro git :

Wenn Sie zufällig ein Objekt begehen, das Hashes mit demselben SHA-1-Wert als vorheriges Objekt in Ihrem Repository als vorheriges Objekt hassen, wird das vorherige Objekt bereits in Ihrer GIT-Datenbank angezeigt und davon ausgehen, dass es bereits geschrieben wurde. Wenn Sie versuchen, dieses Objekt wieder anzurufen, erhalten Sie immer die Daten des ersten Objekts.

So würde es nicht versagen, aber es würde auch nicht Ihr neues Objekt speichern.
Ich weiß nicht, wie das auf der Befehlszeile schauen würde, aber das wäre sicherlich verwirrend.

ein bisschen weiter unten, dass derselbe Bezugszeichen versucht, die wahrscheinliche Ness einer solchen Kollision zu veranschaulichen:

Hier ist ein Beispiel, um Ihnen eine Vorstellung davon zu geben, was es brauchen würde, um eine SHA-1-Kollision zu erhalten. Wenn alle 6,5 Milliarden Menschen auf der Erde programmiert wurden, und jede Sekunde war jeder Code, der das Äquivalent der gesamten Linux-Kernel-Geschichte (1 Million git-Objekte) war und in ein enormes Git-Repository drückte, würde es 5 Jahre dauern, bis Dieses Repository enthielt ausreichend Objekte, um eine Wahrscheinlichkeit von 50% einer einzelnen SHA-1-Objektkollision zu haben. Eine höhere Wahrscheinlichkeit besteht darin, dass jedes Mitglied Ihres Programmierteams von Wölfen in nicht zusammenhängenden Vorfällen in derselben Nacht angegriffen und getötet wird.

Um meine vorherige Antwort aus dem Jahr 2012 hinzuzufügen, gibt es jetzt (Februar 2017, fünf Jahre später) eine Beispiel für eine tatsächliche SHA-1-Kollision mit shattered.io , bei der Sie zwei Kollisionen herstellen können PDF-Dateien: Dies ist eine digitale SHA-1-Signatur für die erste PDF-Datei, die auch als gültige Signatur für die zweite PDF-Datei missbraucht werden kann.
Siehe auch " Seit Jahren vor der Tür des Todes ist die weit verbreitete SHA1-Funktion jetzt tot " und diese Abbildung .

Update 26. Februar: Linus hat die folgenden Punkte in einem Google+ Beitrag bestätigt :

(1) Zunächst einmal - der Himmel fällt nicht. Es gibt einen großen Unterschied zwischen der Verwendung eines kryptografischen Hashs für Dinge wie Sicherheitssignaturen und der Verwendung eines solchen zum Generieren einer "Inhaltskennung" für ein inhaltsadressierbares System wie git.

(2) Zweitens bedeutet die Art dieses speziellen SHA1-Angriffs, dass es eigentlich ziemlich einfach ist, ihn abzuwehren, und es wurden bereits zwei Sätze von Patches für diese Abschwächung veröffentlicht.

(3) Und schließlich gibt es tatsächlich einen recht einfachen Übergang zu einem anderen Hash, der die Welt nicht zerstören wird - oder sogar zu alten Git-Repositories.

Informationen zu diesem Übergang finden Sie unter Q1 2018 Git 2.16 , in dem eine Struktur hinzugefügt wird, die den Hash-Algorithmus darstellt. Die Implementierung dieses Übergangs hat begonnen.

Ab Git 2.19 (Q3 2018) hat Git SHA-256 als NewHash ausgewählt und ist dabei, es in den Code zu integrieren (was bedeutet, dass SHA1 immer noch die Standardeinstellung ist (Q2 2019, Git 2.21), aber SHA2 wird der Nachfolger sein)


Ursprüngliche Antwort (25. Februar) Aber:

ta wird nach einem NUL ausgeblendet (obwohl NUL nicht immer in einer betrügerischen Datei vorhanden ist ).
Nicht jeder aktiviert transfer.fsck , aber GitHub: jeder Push würde im Falle eines fehlerhaften Objekts oder einer defekten Verbindung abgebrochen werden. Obwohl ... es einen Grund gibt, ist dies nicht standardmäßig aktiviert .
  • Eine PDF-Datei kann beliebige Binärdaten enthalten, die Sie ändern können, um einen kollidierenden SHA-1 zu generieren, im Gegensatz zu gefälschtem Quellcode.
    Das eigentliche Problem beim Erstellen von zwei Git-Repositorys mit demselben Head-Commit-Hash und unterschiedlichen Inhalten. Und selbst dann bleibt der Angriff verworren .
  • Linus fügt hinzu :

    Der ganze Punkt eines SCM ist, dass es sich nicht um ein einmaliges Ereignis handelt. aber über kontinuierliche Geschichte. Das bedeutet auch grundsätzlich, dass a Ein erfolgreicher Angriff muss im Laufe der Zeit funktionieren und nicht erkennbar sein.
    Wenn Sie einen SCM einmal zum Narren halten können, geben Sie Ihren Code ein, und er wird angezeigt nächste Woche entdeckt, haben Sie eigentlich nichts Nützliches getan. Nur du hat sich verbrannt.

    Joey Hess versucht diese PDF-Dateien in ein Git-Repo und fand er :

    Dazu gehören zwei Dateien mit demselben SHA und derselben Größe, die erhalten werden verschiedene Blobs dank der Art und Weise, wie Git den Header dem vorstellt Inhalt.

    joey@darkstar:~/tmp/supercollider>sha1sum  bad.pdf good.pdf 
    d00bbe65d80f6d53d5c15da7c6b4f0a655c5a86a  bad.pdf
    d00bbe65d80f6d53d5c15da7c6b4f0a655c5a86a  good.pdf
    joey@darkstar:~/tmp/supercollider>git ls-tree HEAD
    100644 blob ca44e9913faf08d625346205e228e2265dd12b65    bad.pdf
    100644 blob 5f90b67523865ad5b1391cb4a1c010d541c816c1    good.pdf
    

    Beim Anhängen identischer Daten an diese kollidierenden Dateien werden generiert Bei anderen Kollisionen werden Daten nicht vorangestellt.

    Der Hauptangriffsvektor (Fälschung eines Commits) wäre also :

    • Generieren Sie ein reguläres Commit-Objekt.
    • Verwenden Sie das gesamte Festschreibungsobjekt + NUL als ausgewähltes Präfix und
    • Verwenden Sie den Kollisionsangriff mit identischem Präfix, um die kollidierenden guten / schlechten Objekte zu generieren.
    • ... und das ist nutzlos, weil die guten und schlechten Festschreibungsobjekte immer noch auf denselben Baum zeigen!

      Außerdem können Sie kryptoanalytische Kollisionsangriffe gegen SHA-1 in jeder Datei mit cr-marcstevens/sha1collisiondetection

      Das Hinzufügen eines ähnlichen Checks in Git selbst würde einige Berechnungskosten verursachen .

      Beim Ändern des Hashs Linux-Kommentare :

      Die Größe des Hashs und die Auswahl des Hash-Algorithmus sind unabhängige Aspekte.
      Was Sie wahrscheinlich tun würden, ist zu einem 256-Bit-Hash zu wechseln. Verwenden Sie diesen intern und in der nativen Git-Datenbank und dann standardmäßig nur zeige den Hash als 40-stellige Hex-Zeichenfolge (ähnlich wie wir bereits in vielen Situationen abkürzen).
      Auf diese Weise sehen Tools rund um Git die Änderung erst, wenn sie übergeben werden ein spezielles "--full-hash" -Argument (oder "--abbrev=64" oder was auch immer - Die Standardeinstellung ist, dass wir mit 40 abkürzen.

      Ein

  • Eferrer "> Übergangsplan (von SHA1 in eine andere Hashfunktion) wäre noch komplex, , aber aktiv studiert.
    eine generationsporticetagcode-Kampagne ist in laufzeit :

    Update 20. März: Github Detail A möglich Angriff und der Schutz :

    sha-1-Namen können durch verschiedene Mechanismen Vertrauen zugewiesen werden. Zum Beispiel ermöglicht es Ihnen, dass Sie ein Commit oder -Tag kryptografisch unterschreiben können. Dadurch wird nur das Commit- oder Tag-Objekt selbst angemeldet, das wiederum auf andere Objekte zeigt, die die tatsächlichen Dateidaten mithilfe ihrer SHA-1-Namen enthalten. Eine Kollision in diesen Objekten könnte eine Signatur erstellen, die gültig erscheint, was jedoch auf verschiedene Daten hinweist, als der Unterzeichner beabsichtigt. Bei einem solchen Angriff sieht der Unterzeichner nur die Hälfte der Kollision, und das Opfer sieht die andere Hälfte.

    Schutz:

    Der jüngste Angriff verwendet spezielle Techniken, um Schwachstellen im SHA-1-Algorithmus auszunutzen, die in viel weniger Zeit eine Kollision finden. Diese Techniken hinterlassen ein Muster in den Bytes, die beim Berechnen des SHA-1 der beiden Kollidierpaare erfasst werden können.

    github.com führt jetzt diese Erkennung für jeden SHA-1 aus, und bricht den Vorgang ab, wenn Hinweise auf die Hälfte eines kollidierenden Paars ist. Das verhindert, dass Angreifer GitHub verwendet, um ein Projekt zu überzeugen, das "unschuldige" Hälfte ihrer Kollision anzunehmen, sowie daran hindern, die bösartige Hälfte zu verhindern.

    siehe " convert-to-object_id " von marc stevens


    wieder mit Q1 2018 git 2.16 Hinzufügen einer Struktur, die Hash-Algorithmus repräsentiert, die Implementierung eines Übergangs zu einem neuen Hash hat angefangen.
    Wie oben erwähnt, wird der neue unterstützte Hash sha-256 .

    Ich denke, Kryptographen würden feiern.

    Zitat aus Wikipedia-Artikel zu SHA-1 :

    Im Februar 2005 wurde ein Angriff von Xiaoyun Wang, Yiqun Lisa Yin und Hongbo Yu angekündigt. Die Angriffe können Kollisionen in der Vollversion von SHA-1 finden, die weniger als 2 ^ 69 Operationen erfordern.(Eine Brute-Force-Suche würde 2 ^ 80 Operationen erfordern.)

    Es gibt verschiedene Angriffsmodelle für Hashes wie SHA-1, aber das normalerweise diskutierte ist die Kollisionssuche, einschließlich Marc Stevens ' HashClash Tool.

    "Ab 2012 gilt der effizienteste Angriff gegen SHA-1 als sei derjenige von Marc Stevens [34] mit geschätzten Kosten von 2,77 Mio. USD Brechen Sie einen einzelnen Hashwert, indem Sie CPU-Leistung von Cloud-Servern mieten. "

    Wie bereits erwähnt, können Sie eine Hash-Kollision mit git erzwingen. Dadurch werden jedoch die vorhandenen Objekte in einem anderen Repository nicht überschrieben. Ich würde mir vorstellen, dass selbst git push -f --no-thin die vorhandenen Objekte nicht überschreibt, aber nicht 100% sicher ist.

    Das heißt, wenn Sie sich in ein Remote-Repository hacken, können Sie Ihr falsches Objekt zum älteren dort machen und möglicherweise gehackten Code in ein Open-Source-Projekt auf Github oder ähnlichem einbetten. Wenn Sie vorsichtig waren, könnten Sie vielleicht eine gehackte Version einführen, die neue Benutzer heruntergeladen haben.

    Ich vermute jedoch, dass viele Dinge, die die Entwickler des Projekts tun könnten, Ihren millionenschweren Hack entweder aufdecken oder versehentlich zerstören könnten. Insbesondere ist das eine Menge Geld, wenn ein Entwickler, den Sie nicht gehackt haben, jemals den oben genannten git push --no-thin ausführt, nachdem er die betroffenen Dateien geändert hat, manchmal sogar ohne den --no-thin abhängig.

    Lizenziert unter: CC-BY-SA mit Zuschreibung
    Nicht verbunden mit StackOverflow
    scroll top