Warum ist dieser code anfällig für buffer-overflow-Angriffe?
int func(char* str)
{
char buffer[100];
unsigned short len = strlen(str);
if(len >= 100)
{
return (-1);
}
strncpy(buffer,str,strlen(str));
return 0;
}
Dieser code ist anfällig für einen buffer-overflow Angriff, und ich versuche, herauszufinden, warum. Ich denke, es hat zu tun mit len
erklärt wird, eine short
statt einer int
aber ich bin mir nicht wirklich sicher.
Irgendwelche Ideen?
InformationsquelleAutor der Frage Jason | 2015-04-28
Du musst angemeldet sein, um einen Kommentar abzugeben.
Auf den meisten Compilern der maximale Wert eines
unsigned short
ist 65535.Jedem Wert über, wird gewickelt, also 65536, wird zu 0, und 65600 wird 65.
Dies bedeutet, dass die langen Ketten der richtigen Länge (z.B. 65600) übergeben den Scheck und überlauf des Puffers.
Verwenden
size_t
zum speichern des Ergebnisses derstrlen()
nichtunsigned short
und vergleichenlen
zu einem Ausdruck, der direkt codiert die Größe desbuffer
. So zum Beispiel:InformationsquelleAutor der Antwort orlp
Das problem ist hier:
Wenn die Zeichenfolge größer als die Länge der Ziel-Puffer strncpy wird, kopieren Sie über. Sie sind auf Basis der Anzahl der Zeichen der Zeichenkette als Zahl zu kopieren, anstatt die Größe des Puffers. Der richtige Weg, dies zu tun ist wie folgt:
Was dieser tut, ist die Menge der kopierten Daten, um die tatsächliche Größe des Puffers minus eins für das null-Endzeichen. Dann setzen wir das Letzte byte im Puffer, um das null-Zeichen als zusätzlicher Schutz. Der Grund für dieses ist, weil strncpy kopiert bis zu n bytes, einschließlich des abschließenden null, wenn strlen(str) < len - 1. Wenn nicht, dann ist die null wird nicht kopiert, und Sie haben ein crash-Szenario, denn jetzt ist Ihr Puffer hat eine nicht beendete Zeichenkette.
Hoffe, das hilft.
EDIT: Nach weiterer Prüfung und input von anderen, eine mögliche Codierung für die Funktion folgt:
Da wir bereits wissen, die Länge der Zeichenfolge ist, können wir mit memcpy kopieren Sie die Zeichenfolge aus dem Ort, auf den verwiesen wird, die von str in den Puffer. Beachten Sie, dass der pro-das Handbuch Seite für strlen(3) (auf einem FreeBSD 9.3-system), das folgende angegeben:
Welche ich zu interpretieren sein, dass die Länge des string enthält nicht die null. Das ist der Grund, warum ich kopiere len + 1 bytes enthalten den Wert null, und der test überprüft, um sicherzustellen, dass die Länge < Größe des Puffer - 2. Minus eins, da der Puffer beginnt bei der position 0 und minus andere zu stellen Sie sicher, es gibt Raum für die null.
EDIT: Stellt sich heraus, die Größe von etwas, das beginnt mit 1, während der Zugriff beginnt mit 0, so ist der -2 war vorher falsch, da würde es wieder ein Fehler für alles > 98 bytes sein, aber es sollte > 99 bytes.
EDIT: Obwohl, die Antwort über ein unsigned short ist in der Regel richtig als die maximale Länge, die dargestellt werden können, 65.535 Zeichen, ist es eigentlich egal, weil wenn der string länger ist als der Wert umwickeln. Es ist wie mit 75,231 (das ist 0x000125DF) und abkleben der oberen 16 bits geben Sie 9695 (0x000025DF). Das einzige problem, das ich sehe, ist, dass die ersten 100 chars Vergangenheit 65.535 ein, als die Länge überprüfen Sie erlauben das kopieren, sondern es wird lediglich eine Kopie der ersten 100 Zeichen der Zeichenfolge in allen Fällen und null die Zeichenkette beenden. So auch mit dem rundum-Ausgabe, der Puffer noch nicht übergelaufen.
Dies kann oder kann nicht in sich selbst ein Sicherheitsrisiko darstellen, je nach Inhalt des Strings und was Sie verwenden es für. Wenn es nur straight text ist lesbarer, dann gibt es in der Regel kein problem. Sie bekommen einfach einen abgeschnittenen string. Allerdings, wenn es so etwas wie eine URL oder auch ein SQL-Befehl-Sequenz, könnten Sie ein problem haben.
InformationsquelleAutor der Antwort Daniel Rudy
Obwohl Sie mit
strncpy
die Länge der cutoff-Frequenz, ist immer noch abhängig von den übergebenen string-Zeiger. Sie haben keine Ahnung, wie lange Zeichenfolge (die Position des null-Terminators relativ zu dem Zeiger, das ist). So ruftstrlen
allein öffnet Sie, um die Anfälligkeit. Wenn Sie wollen, sicherer zu sein, verwenden Siestrnlen(str, 100)
.Vollständigen code korrigiert werden würde:
InformationsquelleAutor der Antwort Patrick Roberts
Die Antwort mit die Verpackung ist Recht. Aber es ist ein problem glaube ich noch nicht genannt wurde
if(len >= 100)
Gut, wenn Len wäre 100 würden wir kopieren 100 Elemente ein, wir würden keinen nachgestellten \0. Dass klar würde bedeuten, jede andere Funktion, abhängig von der richtigen endete string würde, gehen weit über das ursprüngliche array.
Den string problematisch aus C ist IMHO nicht lösbar. Sie würden immer besser, haben einige Grenzen, bevor der Anruf, aber auch das wird nicht helfen. Es gibt kein bounds checking und damit buffer overflows immer kann und leider auch passiert....
InformationsquelleAutor der Antwort Friedrich
Darüber hinaus die Sicherheit Probleme beim Aufruf
strlen
mehr als einmal sollte man in der Regel nicht die Verwendung von string-Methoden strings, deren Länge genau bekannt ist [für die meisten string-Funktionen es gibt nur einen wirklich schmalen Gehäuse, wo Sie verwendet werden sollten--die Saiten, für die eine maximale Länge garantiert werden kann, aber die genaue Länge ist nicht bekannt]. Einmal die Länge der Eingabe-Zeichenkette bekannt ist und die Länge der Ausgabe-Puffer bekannt ist, sollte man sich überlegen, wie groß eine region kopiert werden sollen, und verwenden Sie dannmemcpy()
tatsächlich führen Sie die Kopie in Frage. Obwohl es möglich ist, dassstrcpy
vielleicht übertreffenmemcpy()
beim kopieren einer Zeichenfolge, die nur aus 1-3 bytes oder so, auf vielen Plattformenmemcpy()
ist wahrscheinlich mehr als doppelt so schnell beim Umgang mit größeren strings.Zwar gibt es einige Situationen, in denen die Sicherheit würde auf Kosten der performance, das ist eine situation, wo der sichere Ansatz ist auch schneller. In einigen Fällen kann es sinnvoll sein, code zu schreiben, die nicht sicher ist gegen unheimlich-Verhalten-Eingänge, wenn der code Speisung der Eingänge kann dafür sorgen, dass Sie gut erzogen, und wenn der Schutz vor Fehlverhalten Eingänge würde die Leistung beeinträchtigen. Sicherstellen, dass die string-Längen sind nur einmal überprüft, verbessert beide Leistung und Sicherheit, obwohl man extra was getan werden kann, um zu helfen, Wache Sicherheit, selbst wenn tracking-string-Länge manuell: für jede Zeichenkette, die erwartet wird, um eine nachgestellte null, schreiben die nachfolgenden null explizit statt zu erwarten, dass die Quell-Zeichenfolge. Also, wenn man das schreiben einer
strdup
äquivalent:Beachten Sie, dass die Letzte Anweisung konnte in der Regel verzichtet werden, wenn die memcpy hatte verarbeitet
len+1
bytes, aber es einen anderen thread waren zum ändern der Quell-string die Folge könnte ein nicht-NUL-terminierte Ziel-string.InformationsquelleAutor der Antwort supercat