it-swarm.com.de

Ist das Teilen durch Null eine Sicherheitslücke?

Auch wenn Softwarefehler und Schwachstellen manchmal als dasselbe Konzept angesehen werden, muss mindestens ein bestimmter Aspekt zwischen ihnen bestehen, und ich denke, der bekannteste ist Ausnutzbarkeit (letzterer hat die Eigenschaft).

Was mich neugierig macht, ist, dass ich selbst nach vielen Fällen, in denen Fehler durch Teilen durch Null als Softwareprobleme gemeldet werden, kaum einen Angriff finden kann (außer DoS) mit Teilen durch -zero Bugs. Ich weiß, dass nicht alle Arten von Fehlern die gleichen Auswirkungen auf ein System in Bezug auf die Sicherheit haben. Gibt es jedoch eine Angriffsmethode, bei der Fehler, die durch Null geteilt werden, verwendet werden, um etwas anderes als DoS zu erreichen, wie beispielsweise die Eskalation von Berechtigungen?

81
Gwangmu Lee

Es geht darum, dass ein Ausnahmebehandler aufgerufen wird, um die Division durch Null zu behandeln. Im Allgemeinen wissen Angreifer, dass Ausnahmebehandlungsroutinen nicht so gut getestet sind wie normale Codeflüsse. Ihr Hauptlogikfluss ist möglicherweise solide und gründlich getestet, aber ein Ausnahmebehandler kann durch Interrupts ausgelöst werden, die an einer beliebigen Stelle im Code innerhalb seines Bereichs auftreten.

int myFunction(int a, int b, SomeState state) {

    state(UNINITIALIZED);
    try {
        state.something(a/b);
        state(NORMAL);
    }
    catch () {
        state.something(b/a);
        state(INVERTED);
    }
    return retval;
}

Dieser schreckliche Pseudocode zeigt, wie der Fehler ausgenutzt werden kann. Nehmen wir an, ein nicht initialisierter Staat ist irgendwie verwundbar. Wenn diese Routine aufgerufen wird, wird der Status zuerst nicht initialisiert. Wenn b Null ist, fängt es die Ausnahme ab und versucht, eine andere Logik auszuführen. Wenn jedoch sowohl a als auch b Null sind, wird erneut geworfen, wodurch der Zustand nicht initialisiert wird.

Die Division durch Null selbst war nicht die Sicherheitslücke, sondern der schlechte Code, der ausgenutzt werden kann.

105
John Deters

So fügen Sie ein anderes erfundenes hinzu, das jedoch auf einem realen Beispiel basiert:

Vor vielen (vielen) Monden lief auf meiner High School Novell Netware und hatte es so konfiguriert, dass die Schüler keine Eingabeaufforderung direkt ausführen konnten (was ärgerlich war, wenn Sie beispielsweise eine Diskette formatieren mussten). Es wurde jedoch festgestellt, dass, wenn Sie ein Kennwort mit mehr als X Zeichen eingegeben haben (d. H. Nur eine Weile eine Taste gedrückt gehalten haben), dies die Netware zum Absturz bringen und das System auf ... a dos Prompt zurücksetzen würde. Höchstwahrscheinlich war dies ein Pufferüberlauf, aber das Prinzip ist dasselbe: Wenn Sie es mit einem System (insbesondere einem eingebetteten) zu tun haben, das zumindest einige unerwartete Abstürze behandelt, indem Sie in einen Wartungsmodus versetzt werden, besteht ein Sicherheitsrisiko .

50
Foon

Wie die anderen Antworten vermuten lassen, hängt dies vollständig vom gesamten System ab. Das ist nicht nur der Code, sondern auch die Plattform, Sprache und der Compiler.

In c ++ ist beispielsweise die Division durch Null bei Ganzzahlen ein undefiniertes Verhalten. Eine der Regeln für diese bestimmte Sprache ist, dass der Compiler davon ausgehen kann, dass undefiniertes Verhalten niemals auftritt und dass er irgendetwas tun darf, wenn dies der Fall ist.

Alles beinhaltet einen Absturz mit einer Fehlermeldung und Aufräumen, einen Absturz ohne Fehlermeldung und alles in einem seltsamen Zustand oder den schrecklichsten Versuch, weiterzumachen, als wäre nichts passiert.

In der Praxis versuchen die meisten guten modernen Compiler, sauber abzustürzen, wenn sie auf so etwas treffen. Dies sollte jedoch deutlich machen, warum davon ausgegangen wird, dass es sich um eine Sicherheitsanfälligkeit handelt. Wenn Sie Ihren Code nur mit einem anderen Compiler oder anderen Einstellungen erstellen und den Code nicht einmal ändern, kann das Programm von einem sauberen Absturz bis zum Löschen Ihrer Datenbank reichen.

19
Josiah

Insgesamt kann bei einem falsch konfigurierten Webserver eine PHP -Umgebung den physischen Pfad zum Skript anzeigen, wenn eine Division durch Null verursacht wird (interner Pfadverlust):

<?php
$denominator = $_GET['number'];
echo 1/$denominator;

Beim Zugriff auf script.php? Number = 0 konnten wir sehen:

Warnung: Division durch Null in /var/www/html/script.php in Zeile 3.

Während ich in meinen Workshops und Vorträgen manchmal sage, dass alle Sicherheitsprobleme in Software im Wesentlichen Fehler sind, ist das Gegenteil nicht automatisch der Fall.

Ich würde jedoch nicht auf die Verwertbarkeit als Argument eingehen. Nur weil Sie und ich keinen Weg finden, etwas auszunutzen, heißt das nicht, dass jemand, der schlauer ist, es nicht eines Tages tun wird. Wir müssten einen formalen Beweis liefern, dass es nicht ausnutzbar ist. Viel Glück mit formalen Beweisen in aktuellen Programmiersprachen.

Um Ihre Frage zu beantworten: Eine Division durch Null könnte eine Schwachstelle oder ein Teil davon sein. In der Regel Dies führt zu einer Ausnahme und damit zur Beendigung der Software. Dies allein könnte eine wichtige Information für einen Angreifer sein (er weiß jetzt, dass eine Variable Null war).

Es ist unwahrscheinlich, dass die Division durch Null allein eine Sicherheitslücke darstellt, aber in einem größeren Kontext kann sie Teil des Problems sein.

Um die Schleife zu schließen, sollten Sie alle Fehler immer ernsthaft behandeln. Wenn Sie nicht sicher sein können (z. B. dass Ihre Abteilung eine Variable verwendet, die Sie nicht steuern), müssen Sie sie abfangen und verarbeiten, ob sicher oder nicht. "Ja, es ist ein Fehler, aber ich sehe nicht, wie er ausgenutzt werden kann" ist keine sicherheitsbewusste Denkweise.

13
Tom

Die Division durch Null ist nicht von Natur aus eine Sicherheitslücke.

Wenn Sie jedoch einen Anwendungsserver zum Absturz bringen und offline bleiben können, indem Sie ihn durch Null teilen, kann dies eine Denial-of-Service-Sicherheitsanfälligkeit darstellen.

10

Ich denke, letztendlich wird Ihre Antwort auf das individuelle System im Spiel ankommen. Wie geht das System damit um, durch 0 zu teilen? Wenn es elegant ist, sind Ihre Angriffsoptionen begrenzt oder nicht vorhanden. Wenn es etwas Funky macht, können Sie wahrscheinlich mit etwas da reinkommen.

Grundsätzlich können daraus keine Standardangriffe hervorgehen - das ist mir sowieso bekannt -, aber Computer können Fehler immer schlecht behandeln, und der schlechte Umgang mit Fehlern ist die Quelle vieler Schwachstellen.

5
securityOrange

Wenn ein Programm nur vertrauenswürdige Daten empfängt und keine Verhaltensanforderungen erfüllen müsste, wenn böswillig gestaltete Daten angegeben werden, kann möglicherweise etwas effizienterer Code generiert werden, als dies erforderlich wäre, wenn bestimmte Verhaltensanforderungen an ihn gestellt würden musste sich für alle Daten treffen.

Da einige Aufgaben nur die Verarbeitung vertrauenswürdiger Daten umfassen, während andere die Verarbeitung von Daten aus nicht vertrauenswürdigen Quellen umfassen, ermöglicht der C-Standard Implementierungen, die nur für die ersteren Aufgaben vorgesehen sind, Optimierungen vorzunehmen, die für die für die letzteren vorgesehenen und für die vorgesehenen unangemessen sind für letztere Aufgaben geeignet sein, um Garantien zu bieten, die Optimierungen unnötig behindern würden, die bei der Verarbeitung der ersteren nützlich sein könnten.

Leider bietet der Standard keine Mittel, mit denen Implementierungen angeben können, welche Arten von Verhaltensgarantien sie über die vom Standard vorgeschriebenen hinaus bieten. Als C89 geschrieben wurde, erwarteten die Autoren, dass "der Marktplatz" einen besseren Job als die Autoren des Standards machen könnte, um zu bestimmen, welche Arten von Implementierungen welche "populären Erweiterungen" unterstützen sollten, indem sie sich zumindest etwas vorhersehbar verhalten, wenn der Standard Nein auferlegt Anforderungen, und diese Einstellung hat sich nicht geändert, obwohl sie nicht mehr auf den heutigen Compiler-Markt passt.

Gegeben etwas wie:

if (x != 0) launch_nuclear_missiles();
... and then, possibly in another function
z=y/x;

einige Leute würden einen Compiler, der das "if" durch einen bedingungslosen Aufruf von launch_nuclear_missiles() ersetzt, als einem überlegen ansehen, der nur launch_nuclear_missiles aufruft, wenn x nicht Null ist, aber Ein solches Verhalten wäre nur dann angemessen, wenn Aufgaben verarbeitet werden, die niemals nicht vertrauenswürdige Eingaben beinhalten.

Wenn man weiß, dass die verwendeten Compiler die Arten schwacher Verhaltensgarantien aufrechterhalten, die Allzweck-Compiler selbstverständlich angeboten haben und die das Schreiben von Programmen erleichtern, die schwache Verhaltensbeschränkungen erfüllen können, selbst wenn böswillig gestaltete Eingaben gegeben werden, Dann kann die Division durch Null keine Sicherheitslücken aufweisen. Bei aggressiv optimierenden Compilern, die nicht für Aufgaben mit nicht vertrauenswürdiger Eingabe geeignet sind, muss jedoch eine ausreichende Sicherheitsüberprüfungslogik hinzugefügt werden, um alle Vorteile zu negieren, die solche "Optimierungen" hätten bieten können.

5
supercat

aber gibt es eine Angriffsmethode, bei der Fehler, die durch Null geteilt werden, verwendet werden, um etwas anderes als DoS zu erreichen, beispielsweise die Eskalation von Berechtigungen?

Schnellsuche in der CVE-Datenbank von MITRE zeigt, dass die Division durch Null meistens Denial-of-Service verursacht, aber ein besonderer Fall CVE-2005-0998 erlaubt etwas anderes:

Beschreibung Mit dem Web_Links-Modul für PHP-Nuke 7.6 können Angreifer über einen ungültigen show-Parameter vertrauliche Informationen abrufen, wodurch eine Division durch Null ausgelöst wird PHP Fehler, der den vollständigen Pfadnamen des Servers verliert.

Dies selbst ermöglicht keine Eskalation von Berechtigungen oder bestimmte Angriffe, aber im Allgemeinen können vertrauliche Informationen bei der Erstellung anderer Angriffe hilfreich sein. Mit anderen Worten, die Division durch Null allein könnte nur ein Sprungbrett sein.

4

Ich sehe, woher du kommst. An sich ist es schwierig zu erkennen, wie nur ein Rechenfehler verwendet werden kann, um alles zu verursachen, was eine Dateneingabe erfordert (wie die Codeausführung).

Abhängig von der Sprache kann es jedoch zu Problemen bei der Flusskontrolle oder zum selektiven Absturz von Threads usw. kommen. Auf diese Weise können Sie andere Probleme verschärfen oder, wenn Sie wirklich (unglücklich) sind, direkt dazu führen, dass ein Pfad ausgelöst wird, der dies verursacht etwas ausnutzbares verdoppeln. Denken Sie daran, dass die Dateneingabe und der Fehler nicht unbedingt identisch sein müssen.

Dies ist ein bisschen erfunden, aber sagen wir zum Beispiel, Sie haben ein Objekt, das sich bereits in einer verknüpften Liste befindet, verschoben, indem Sie dem Kopf eine Kopie hinzugefügt und dann iteriert haben, bis Sie sie gefunden und die Kopie entfernt haben. Wenn Sie dies in einem Thread tun und aus irgendeinem Grund (sagen wir, jemand fügt eine Statistikdruckanweisung in die Iterationsschleife ein, die falsch ist), wird die Liste möglicherweise mit 2 Kopien desselben Elements in einem schlechten Zustand belassen. Wenn dies aufgeräumt wird: doppelt frei ...

Wenn Sie den Inhalt dieses neuen Elements steuern und die Statistik durch Null dividieren lassen und dennoch genügend Inhalt steuern können, kann dies durchaus ausgenutzt werden.

Nicht wahrscheinlich, aber möglich.

3
ANone

Die Frage könnte besser formuliert werden als "Warum wird Denial of Service als Sicherheitslücke angesehen?". Wenn der Prozessor unter Linux auf einem x86-Prozessor eine Ganzzahl durch 0 teilt (oder den minimalen vorzeichenbehafteten Ganzzahlwert geteilt durch -1, dank supercat), empfängt das Programm ein SIGFPE-Signal. In Windows ist dies eine illegale Operation. Der C/C++ - Standard betrachtet es als undefiniertes Verhalten, was bedeutet, dass Sie nicht zuverlässig wissen können, was passieren wird, wenn Sie sich nur den Code ansehen.

Normalerweise führt dies, wie bei vielen, aber nicht allen Denial-of-Service-Sicherheitslücken, zu einem "Absturz". Hier sind einige Möglichkeiten, was Sie nutzen können, wenn ein Programm abnormal beendet wird:

  • Es könnte einem anderen Programm ermöglichen, dieselben Ressourcen wie das erste zu verwenden (wie ein Port) und sich als dasselbe Programm auszugeben.
  • Ein Absturz kann alle vom Programm verwendeten Bereinigungsvorgänge umgehen, die ausgenutzt werden könnten.
  • Wenn der Exit-Code des Programms in einem anderen Programm verwendet wird, das den Signalstatus der PID des untergeordneten Prozesses nicht überprüft, könnte das Programm einen Fehlercode zurückgegeben haben. Auf meinem Linux-Computer setzen die folgenden beiden Programme beispielsweise $? (Die Variable, die in Shell-Skripten zur Darstellung des Rückkehrcodes des vorherigen Befehls verwendet wird) auf 136: int main(int argc, char** argv) { return 1 / (argc - 1); } und int main() { return 136; }
  • Abstürze können zu Coredumps führen, die geschützten Speicher wie Sicherheitsschlüssel, Passwörter und das Rezept für Coca-Cola enthalten können.

Aufgrund von Optimierungen kann der Compiler außerdem davon ausgehen, dass der Divisor niemals 0 sein kann, und möglicherweise Code optimieren, den Sie möglicherweise nicht berücksichtigt haben. Dies gilt nur für kompilierte Sprachen wie C und C++, die ein undefiniertes Verhalten (oder ein gleichwertiges Verhalten) für die Division durch Null aufweisen. Ich konnte keinen optimierten Code erstellen, der dies anhand der Beispiele in einigen anderen Antworten in clang oder gcc tut, aber nichts hindert sie oder andere Compiler daran, dies in der Vergangenheit oder in der Zukunft zu tun.

2
Erroneous

Hier gibt es einige sehr spezifische Antworten. Ich würde zustimmen, dass eine (nicht behandelte) Division durch Null in erster Linie ein funktionales Problem ist - aber das bedeutet nicht, dass es nicht als Sicherheitsproblem ausgenutzt werden kann. In der Tat gibt es so viele Fehler, die ausgenutzt werden können. Die Klassifizierung von "funktional" gegenüber "Sicherheit" bei Anwendung auf Fehler erscheint etwas sinnlos.

Sie schließen eine Kategorie von Sicherheitsproblemen (DOS) ab, ohne zu diskutieren, was Sie hier als außerhalb des Geltungsbereichs liegend betrachten. Das offensichtlichste Szenario ist, dass das Auslösen des Fehlers dazu führt, dass die Instanz des Programms gestoppt wird. Es gibt jedoch subtilere Effekte: Wenn dadurch große Datenmengen in das Dateisystem geschrieben werden (z. B. ein Core-Dump), bietet sich eine Möglichkeit für einen zweiten DOS-Typ, indem das Dateisystem aufgefüllt wird.

Jefrey erwähnt die Offenlegung für eine PHP -Anwendung - aber Fehlermeldungen, Protokolle und Core-Dumps bieten eine reichhaltige Auswahl für Leute, die versuchen, Informationen zu extrahieren, auf die sie keinen Zugriff aus Programmen haben sollten, die in einer beliebigen Sprache geschrieben sind.

Wenn die vorzeitige Beendigung des Programms zu einer Reaktion führt, kann ein Angreifer zu einem Zeitpunkt seiner Wahl ein bestimmtes Programm auslösen. Er hat eine gewisse Kontrolle darüber, was Ihr System tut, was eine Eskalation von Angriffen/Berechtigungen erleichtern kann.

Selbst wenn das Steuerungssystem manuell ist, gibt es immer noch einen Übergangszustand für das System, in dem das Sicherheitsverhalten weniger genau definiert ist und in dem Assets wie Passphrasen, Passwörter und private Schlüssel im Flug sind.

1
symcbean

Hier ist ein Beispiel, wo es einen Unterschied machen könnte.

Es ist zu 100% erfunden - aber viele Klassen von Exploits werden durch theoretische "erfundene" Beispiele identifiziert, bis spezifische Beispiele gefunden werden.

Es ist Pseudocode.

try:
   get the average cpu usage per logged in user
   if this average is too high, tell the person logging on that we're busy.
   get login credentials
   verify login credentials
   if credentials are invalid, tell them to go away
   restrict access for this session to the correct access for this user
if there is an exception:
   do nothing

let the user in

In diesem Fall wird die durchschnittliche CPU pro angemeldetem Benutzer möglicherweise als "Gesamt-CPU/Anzahl der angemeldeten Benutzer" berechnet. Wenn keine angemeldeten Benutzer vorhanden sind, wird "durch 0 teilen" angezeigt und es wird direkt zum "Wenn" übersprungen Es gibt eine Ausnahmeklausel. Dies umfasst das Einschränken des Zugriffs - die neue Sitzung hat möglicherweise Zugriff, der dem zuletzt angemeldeten Benutzer entspricht, oder unbegrenzten Zugriff.

Während dieses Beispiel den gesamten Code zusammen zeigt, ruft Ihr Hauptcode häufig etwas auf, das etwas anderes aufruft, und die beiden Aspekte, die interagieren (in diesem Fall Division durch 0 und die Tatsache, dass die Ausnahme ignoriert wird), werden möglicherweise in Teilen ausgeführt des Codes, die weit voneinander entfernt sind.

Wie viele Leute erwähnt haben, ist die Division durch Null (allein) kein Sicherheitsfehler oder überhaupt ein Fehler. Soweit mir bekannt ist, haben die meisten (vielleicht alle!) Programmiersprachen klar dokumentierte Informationen darüber, was passiert, wenn durch Null geteilt wird. Ich denke, so ziemlich jede Sprache, die Ausnahmen hat, hat eine Ausnahme für die Division durch Null (ich habe gesehen, dass ein mechanischer Taschenrechner in einer Endlosschleife stecken geblieben ist).

1
AMADANON Inc.