it-swarm.com.de

Ausnutzung der Verzögerung beim Scannen eines Festivaltickets

Wie ein Ticketsystem funktioniert

Ein Ticketsystem - eines, das Sie auf Festivals sehen - funktioniert folgendermaßen: Wenn ein Benutzer sein Ticket bezahlt, wird der Datenbank eine Zeile mit einer Spalte mit dem Namen is_scanned Hinzugefügt, deren Standardwert auf false gesetzt ist.

Sobald ein Wachmann auf dem Festival den Barcode (mit einer ID und einem eindeutigen Hash) mit seinem Gerät scannt, wird eine Anfrage an die Datenbank gesendet, um zu überprüfen, ob:

  1. der Benutzer, der mit der ID und dem Hash übereinstimmt, hat bezahlt, und
  2. wenn der Wert der Spalte is_scanned immer noch auf false gesetzt ist.

Wenn beide Bedingungen erfüllt sind, wird der Wert is_scanned Auf true, gesetzt, um zu verhindern, dass jemand anderes das Ticket/den Barcode kopiert.

Das Schwachstellenproblem

Das Problem hierbei ist die Zeit zwischen dem Senden der Anforderung durch das Scan-Gerät und dem Umschalten des Werts is_scanned Von false auf true.

Stellen Sie sich dieses Szenario vor: Alice hat ein gültiges Ticket, für das sie bezahlt hat, aber dann lässt sie Eve ihren Barcode kopieren und ändert den sichtbaren Namen auf dem falschen Ticket von Alice in Eve. Jetzt haben wir also zwei Tickets. Eine gültige und eine betrügerische, aber beide haben den gleichen Barcode. Der einzige Unterschied ist der Name.

Was ist, wenn das Ticket von Alice und Eve genau zur gleichen Zeit gescannt wird, wenn sie das Festival betreten ? Das Ticketsystem würde is_scanned Nicht auf true umschalten rechtzeitig, um sicherzustellen, dass Eve nicht mit demselben Barcode wie Alice eintreten konnte. Dies führt dazu, dass beide Tickets (die gültigen und die betrügerischen) den Wachen als "gültig" angezeigt werden.

Mögliche Lösungen

Natürlich hängt diese Art von Exploit wirklich von viel Glück ab, und obwohl dies theoretisch möglich ist ... würde dies in einem realen Szenario wahrscheinlich fehlschlagen.

Wie können wir diese Art von Exploit jedoch auch theoretisch besiegen?

Identifizierung

Ich habe diesen Exploit bereits mit der folgenden Methode berücksichtigt: Wenn ein Barcode gescannt wird, zeige ich nicht nur an, ob das Ticket gültig ist (erfüllt die zuvor angegebenen Bedingungen), sondern auch der Name in der Datenbank. Wenn der Name nicht mit dem auf dem Ticket übereinstimmt, wissen wir, dass das Ticket auf irgendeine Weise manipuliert wird. Wenn der Name, der auf dem Scan-Gerät angezeigt wird, nicht mit dem Namen auf der ID übereinstimmt (den jeder sowieso nachweisen muss, um das Alter nachzuweisen), ist die Eingabe ebenfalls nicht zulässig.

Die einzige Möglichkeit, diese Lösung zu umgehen, ist Identitätsbetrug, und dies liegt natürlich außerhalb der Verantwortung des Ticketsystems, dies zu überprüfen.

Verzögern

Eine andere Möglichkeit, dies theoretisch zu lösen, besteht darin, zwischen jeder Anforderung an die Datenbank-/Validierungs-API eine zufällige Verzögerungszeit hinzuzufügen. Auf diese Weise kann niemand gleichzeitig sein Ticket scannen ... da sich die Validierungszeit jedes Mal um eine zufällige Anzahl von Millisekunden verzögert.

Ich bin kein Fan davon, weil es:

  1. macht alles langsamer am Eingang
  2. ist nicht effektiv, wenn es nicht stark genug verzögert wird. Denn wenn die Datenbank 50 ms benötigt, um is_scanned Von false auf true zu aktualisieren, besteht die einzige Lösung darin, sie jedes Mal mit einem Intervall von mindestens 50 ms zu verzögern.

Andere Lösungen?

Welche anderen Lösungen finden Sie, um diesen Exploit zu lösen?

42
O'Niel

Die von Ihnen beschriebene Sicherheitsanfälligkeit ist Race Condition .

Es gibt verschiedene Möglichkeiten, damit umzugehen, aber ich würde mit einem SELECT ... FOR UPDATE SQL-Abfrage, die die ausgewählten Zeilen sperrt, um neue Schreibvorgänge zu verhindern, bis die aktuelle Transaktion festgeschrieben wird.

Überprüfen Sie unbedingt Ihre RDBMS-Dokumentation, um zu überprüfen, wie sie korrekt implementiert wird:

154
Benoit Esnard

Die andere Lösung ist absolut richtig und macht Sinn für größere Systeme, bei denen es nicht so einfach ist.

Mit den Daten, die Sie haben, das ist relativ einfach, könnten Sie sich für eine nicht blockierende Option entscheiden:

UPDATE [FESTIVAL_TICKET] 
  SET IS_SCANNED = TRUE
WHERE TICKET_ID = @ScannedKey 
  AND IS_SCANNED = FALSE

Dies ist eine atomare Operation. Keine zwei Benutzer der Datenbank können dies ausgeben nd die Zeile aktualisieren lassen. Die Person, die "1 Zeile betroffen" zurückgibt (offensichtlich gibt es eine Möglichkeit, dies im Code herauszufinden, analysieren Sie keinen Text dafür). Alle anderen erhalten null Zeilen, die von der Anweisung betroffen sind. Wenn Sie benutzerfreundlich sein möchten, können Sie jetzt überprüfen, warum es nicht gefunden wurde, ob es sich um die falsche ID handelt oder ob es bereits gescannt wurde.

Das wichtige Detail ist jedoch, dass die Aussage atomar ist. Nur einer wird gewinnen, egal wie nahe er an der Zeitdifferenz Null liegt. Weil Sie nicht mehr lesen und dann schreiben müssen. Sie haben das Lesen und Schreiben in einer atomaren Operation.

87
nvoigt

Der Nachteil dieses scheint zu sein, dass eine Person hineinkommen könnte kostenlos (mit einem kopierten Ticket).

Für kleine Ereignisse ist das wahrscheinlich richtig.
Wenn Sie jedoch aus irgendeinem Grund zu viel Verzögerung hinzufügen, riskieren Sie mehr als das Einsteigen einer Person .
Die Ticket-Scanner lassen nur ein paar zusätzliche Personen durch, wenn ihre Geräte blockieren oder zu langsam sind ... weil die meisten von ihnen wahrscheinlich gültige Tickets haben, oder?

Ich habe dies bei einem Großereignis in diesem Kalenderjahr beobachtet, an dem Tausende Fans von Musikern teilnahmen, die viele Leute haben davon gehört.
Die Ticketfirma war eine große (vielleicht die, für die Sie arbeiten?) Und sie befand sich an einem Ort, der speziell für die Ticketannahme gebaut wurde.
Meine Party war eine von denen, die ohne Scan durchgelassen wurden (und ja ... ich hatte ein gültiges/legales Ticket).
Ich musste ein paar Minuten dort stehen und die Ticketnehmer beobachten, bevor ich herausfinden konnte, warum es passiert war.

TL; DR;
Codieren Sie nicht für alle Fälle wenn Personen beteiligt sind.
Schießen Sie für zwei oder drei Neunen (99% -99,9%) und nennen Sie es einen Tag.
Speichern Sie die Nick-Auswahl, wenn nur Maschinen beteiligt sind ... dann können Sie ein paar Neuner bekommen.

15

Diese Antwort hat bereits eine großartige und kostengünstige Antwort. Ich würde jedoch meine eigene Antwort sowohl aus Software Engineering als auch aus Sicherheitsgründen hinzufügen. Dies kann hilfreich sein für zukünftige ähnliche Fragen zu unwahrscheinlichen Exploits .

und während es theoretisch möglich ist ... In einem realen Szenario würde dies wahrscheinlich fehlschlagen.

Und was ist dann der potenzielle Schaden im Vergleich zu den Kosten? Ich werde beweisen, dass Ausgaben und Kopfschmerzen für zusätzliche Sicherheit das Risiko nicht wert sind.

Jetzt ist die bereits vorgeschlagene und akzeptierte Lösung, um die Rennbedingungen mit SQL-Transaktionen ordnungsgemäß zu handhaben und die Verantwortung/Kosten auf die Datenbank zu verlagern, die beste, branchenübliche und billigere Lösung. Es könnte das Ende des Falls sein, da die Antwort tatsächlich akzeptiert war.

Wie bereits erwähnt, könnte das Ereignis, dass beide Teilnehmer genau im richtigen Moment gescannt werden und den Exploit der Rennbedingungen auslösen, in Millionenquoten geschätzt werden, wenn nicht Milliarden Größenordnung. Um Ihnen eine qualitative Vorstellung von Milliardärsquoten zu geben, lesen Sie diesen Artikel über Lotterien und stellen Sie fest, dass das Spielen für dieses SuperEnalotto oben auf der zweiten Liste eine sein könnte einfaches Spiel im Vergleich zum Scannen von zwei Tickets, und die Belohnung ist definitiv konsistent. Die Gewinnchancen stellen die Ausnutzbarkeit einer Sicherheitsanfälligkeit dar und werden normalerweise in diskrete Ebenen unterteilt ([sehr] unwahrscheinlich, [sehr] wahrscheinlich). Ich vergleiche immer nicht deterministische sicherheitsrelevante Ereignisse mit Lotterie, um einen vertrauten Vergleich zu ermöglichen.

Zur weiteren Verdeutlichung werden die Gewinnchancen beeinflusst von:

  • Die Möglichkeit für die beiden, ihre Bewegung über die Warteschlangen zu synchronisieren und gleichzeitig das Ticket an den Wachmann zu übergeben. Dies impliziert, dass die beiden ständig miteinander kommunizieren und sich selbst trainieren, ganz zu schweigen von dem Glück (die Wahrscheinlichkeit!), Dass sich ihre Linien mit vorhersehbaren Geschwindigkeiten bewegen
  • Die körperliche Bewegung der Wachen. Nicht alle Wachen nehmen sich genau die Zeit in Millis, um die Tickets zu scannen. Sie bewegen die Arme mit unterschiedlichen Geschwindigkeiten. Eines der Tickets kann von den Händen des Wachmanns fallen, ein Wachmann kann das Ticket rückwärts halten. Ein Wachmann kann sich umdrehen, um zu überprüfen, ob die Leitung nicht hinter ihnen eingeklemmt ist. Mit anderen Worten, es gibt eine übermäßige Entropie, um einen Angriff zu planen
    • Unbemannte Ticketprüfautomaten könnte sind von diesem Faktor nicht betroffen
  • Die Zeit, die das Computersystem benötigt, um das Ticket zu scannen , damit die beiden Scans in den gleichen Zeitraum fallen und die Sicherheitsanfälligkeit ausgenutzt wird.

Hier ist also die Überlegung zum Software-Engineering.

Ticket hat einen Preis, ist also X $ wert. Ich schätze, dass die Größe von X in der Größenordnung von 50-100 liegen kann. Für jede Person, die die Sicherheitsanfälligkeit ausnutzt und die Einrichtung betrügerisch betritt, gilt ein Verlust von X USD.

Die Implementierung komplexerer Überprüfungen (z. B. Kontrolle des Passnamens) ist teuer beide in Bezug auf den in der Softwareentwicklungsphase erforderlichen Code und die Zeit, die die Personen benötigen, um die Einrichtung zu betreten . Sicherheitspersonal wird stündlich bezahlt. Die Implementierung einer Sicherheitsüberprüfung nach Ben-Gurion-Art * ist für Ehrliche viel teurer und schmerzhafter.

Jetzt möchten Sie besser schlafen und sicher sein, dass niemand Ihr System ausnutzen kann. Wieviel kostet das? Nachdem Sie einen exorbitanten Geldbetrag für die Sicherung Ihres Systems gezahlt haben, stellen Sie möglicherweise fest, dass Ihr Konkurrent, der ein "ungeschütztes" System betreibt, einen Verlust von 80 US-Dollar mit einer Wahrscheinlichkeit von über einer Million toleriert. Es ist schwer, diese Wahrscheinlichkeit zu quantifizieren. Da Sie mehr Chancen haben, die härteste Lotterie der Welt zu gewinnen, sollten Sie besser darauf wetten, Ihren Job endgültig zu verlassen!

Fazit: In unserem Beruf sind Gewinnchancen unser bester Schlafpartner!

Schlussfolgerung 2: Angriffe auf Rennbedingungen können wahrscheinlich auf automatisierten Netzwerksystemen ausgenutzt werden, auf denen Angreifer offensichtlich synchronisieren sich auf die Mikrosekunde !!! Das könnte auch multiplizieren den Schaden, also begrüßen Sie die besten Sicherheitsmaßnahmen dann!

Schlussfolgerung 3: Wenn das System bereits ausgeführt wird, ist der Aufwand für das Patchen mit der akzeptierten Antwort (Design, Entwicklung, Test, UAT, Rollout, PMO ...) ist teurer dass der mögliche Schaden. Bitte kommentieren Sie unten

* Ich habe das als Beispiel angeführt, weil die Sicherheitsleitungen am Flughafen in Israel legendär lang und gründlich sind

Hier gibt es bereits gute Antworten, die einen Großteil der Exploits von Datenbankteilen abdecken. Aber ich wollte meine reale Erfahrung hinzufügen, nachdem ich im Bereich Event (Open Air Festival) gearbeitet und ein Ticketvalidierungssystem und Anwendungen entwickelt hatte.

Eine der großen Herausforderungen ist die Netzwerkstabilität, da die Annahme, dass alle Scan-Geräte ständig über Netzwerkfunktionen verfügen, völlig falsch ist. Während des Scanvorgangs kann es zu Verzögerungen, Unterbrechungen oder Nichtverfügbarkeit kommen, die die Kundeneinträge für das Ereignis nicht verzögern sollten (zumindest aus unserer Sicht erfordern andere Ereignisse möglicherweise eine strengere Validierung).

In unserer Anwendung wurden Tickets mit einer Signatur validiert, aber erst synchronisiert und in die Datenbank übernommen, wenn das Netzwerk aktiv war. Die Anwendung hat die validierten/festzuschreibenden Tickets in einem Bucket gespeichert und versucht, so viele Tickets wie möglich festzuschreiben, sobald das Netzwerk verfügbar war. Es wird auch vermieden, ein INSERT pro Ticket zu machen.

Am weitesten von der Veranstaltung entfernt erreichte WLAN überhaupt nicht. Um die Kosten für einen anderen Router für nur 10 Meter mehr Reichweite zu sparen, könnten die Scan-Geräte zwischen ihnen kommunizieren und ihre Verbindungen teilen. Das heißt, wenn nur eines der Geräte Zugang zum WLAN hätte, könnten die anderen theoretisch ihre Eimer an das WLAN oder an das nächstgelegene Gerät in Reichweite senden, das es weiterleitet.

Das wirkliche Leben hat uns gezeigt, dass die meisten Scangeräte mindestens einmal pro Minute die Verbindung verloren haben.

Theoretisch könnte ein Ticket von so vielen nicht verbundenen Geräten gescannt werden, wie es möchte, jedoch nur einmal pro Gerät. Dies ist eine Rassenbedingung , aber viel trivialer, um das auszunutzen, was andere Antworten erwähnt haben.


Ein Wort zum How to prevent it?:

Sie können den Race-Zustand verhindern, indem Sie die Parallelität entfernen, wie dies bei einer Sperre der Fall ist. Dies führt zu Latenzen, da Sie die Fähigkeit Ihrer Datenbank, gleichzeitige Schreibvorgänge zu akzeptieren, grundsätzlich reduzieren.

Dann stellt sich die Frage, ob es sich lohnt. Können wir weitere Verzögerungen bis zur Validierung akzeptieren, um die korrekte Authentifizierung sicherzustellen? Wird dies verhindern, dass Menschen eine offene Tür finden oder über einen Zaun springen?

4
Cyrbil

Eine gute Lösung könnte darin bestehen, eine Nachrichtenwarteschlange zu verwenden, anstatt Verzögerungen zu verursachen. Das gescannte Ticket wird nicht sofort verarbeitet, sondern wartet, bis alle gesendeten Tickets verarbeitet wurden. Das System gibt keine Antwort zurück, es sei denn, das Ticket hat die Warteschlange verlassen und wurde ordnungsgemäß verarbeitet. Ein Argument dafür wäre, dass es langsam sein könnte, weil jeder warten muss, bis andere fertig sind. Sie können die Ticket-IDs jedoch logisch teilen, z. B.: 2 Warteschlangen, 1 für ungeradzahlige Tickets und 1 für geradzahlige. oder geben Sie einfach Gruppennummern in die ID selbst ein.

2
paolord