Welche Sicherheitsrisiken / Sicherheitslücken muss jeder C-Programmierer kennen? [geschlossen]

13

Es gibt viele Sicherheitsrisiken, die durch den engen Kontakt mit der Hardware entstehen, im Gegensatz zur Verwendung gut getesteter und bewährter APIs aus höheren Programmiersprachen. Es ist viel einfacher, in C einen Pufferüberlauf zu verursachen als in einer Sprache wie Java.

Welche Risiken oder Schwachstellen (z. B. Pufferüberläufe) sollten jedem C-Programmierer bekannt sein (für C-Programmierer relevante IE-Schwachstellen)? Zu welchen Problemen könnten diese führen? Wie vermeide ich sie und was sind häufige Fehler, die dazu führen, dass diese in Programmen auftreten?

Anto
quelle
Was ist mit dieser Liste: owasp.org/index.php/Category:OWASP_Top_Ten_Project Was wird mehr benötigt als dies?
S.Lott
2
@ S.Lott: Es scheint sehr viel um Sicherheitsprobleme in der Webentwicklung zu gehen. Es scheint im Allgemeinen mehr Ressourcen dafür zu geben, als ich eigentlich verlange, wie es scheint.
Anto
@Anto: Bitte aktualisieren Sie die Frage, um zwischen allen Ressourcen zur Sicherheit und der Sicherheit zu unterscheiden, nach der Sie fragen.
S.Lott
@ S.Lott: Ich bin mir nicht sicher was du meinst. Ich bitte um Sicherheit, die für die meisten C-Programmierer von Bedeutung ist,
Anto
@Anto: "Es scheint im Allgemeinen mehr Ressourcen für diese [Web-Sicherheit?] Zu geben, als ich eigentlich verlange." Scheint zu sagen, dass Sie nach einer Sicherheit fragen, die keine Web-Sicherheit ist. Wahr? Wenn ja, aktualisieren Sie bitte die Frage, um zu erklären, wonach Sie suchen. Falsch? Dann Sie werden fragen , über Web - Sicherheit, in diesem Fall, warum nicht die OWASP - Liste in Ihrer Frage erwähnt?
S.Lott

Antworten:

13

Pufferüberläufe sind groß. In C ist standardmäßig nichts auf den Bereich geprüft, daher ist es sehr einfach, einen Puffer zu überschreiben. Es gibt eine Standardbibliotheksfunktion gets(), die nicht daran gehindert werden kann, den Puffer zu überlaufen, und die fast nie verwendet werden sollte.

Es gibt einige Techniken auf Implementierungsebene, die die Ausnutzung behindern, z. B. das Verwürfeln von Heap-Blöcken. Dadurch werden jedoch Pufferüberläufe in lokalen Puffern nicht gestoppt, was häufig interessante Dinge wie das Ändern der Adresse bewirken kann, an die eine Funktion zurückkehrt.

In C gibt es keine gute allgemeine Lösung. Viele Bibliotheksfunktionen verfügen über Versionen, die die Anzahl der Schreibvorgänge begrenzen. obwohl das zu berechnen ungeschickt sein kann. Es gibt Software, die Heap-Pufferüberläufe im Test erkennen kann, solange der entsprechende Test ausgeführt wird, und Stack-Überlauf wird beim Testen häufig als Absturz angezeigt. Ansonsten geht es um sorgfältige Codierung und Codeüberprüfung.

Ein verwandtes Problem ist das Problem, in einen Puffer zu schreiben, der um ein Zeichen zu klein ist, und zu vergessen, dass eine C-Zeichenfolge mit einer Länge von n Zeichen aufgrund des '\0'Terminators n + 1 Zeichen im Speicher benötigt . Wenn es dem Angreifer gelingt, eine Zeichenfolge ohne Terminator zu speichern, wird jede C-Funktion, die eine Zeichenfolge erwartet, so lange verarbeitet, bis sie ein Null-Byte erreicht. Dies kann dazu führen, dass mehr Informationen kopiert oder ausgegeben werden als gewünscht (oder der geschützte Speicher für einen DOS-Angriff erreicht wird) ). Die Lösung ist wiederum Sensibilisierung, Pflege und Codeüberprüfung.

Es gibt ein weiteres Risiko für die printf()Familie. Wenn Sie jemals schreiben char * str; ... printf(str);, bereiten Sie sich auf Probleme vor, wenn strbeim Drucken ein '%' enthalten ist. Die %nFormatanweisung ermöglicht printf()das Schreiben in den Speicher. Die Lösung ist printf("%s", str);oder puts(str);. (Verwenden Sie snprintf()stattdessen auch den C99 sprintf().)

Die Verwendung von Ganzzahlen ohne Vorzeichen, insbesondere als Schleifenindizes, kann Probleme verursachen. Wenn Sie einem vorzeichenlosen Wert einen kleinen negativen Wert zuweisen, erhalten Sie einen großen positiven Wert. Das kann Dinge wie die Verarbeitung von nur N Instanzen von etwas oder in eingeschränkten Funktionen wie untergraben strncpy(). Untersuchen Sie alle vorzeichenlosen Ganzzahlen. Möglicherweise möchten Sie dies vermeiden unsigned short, da ein großer Wert in einem dieser Werte in einen großen positiven Wert in einem umgewandelt wird int.

Vergessen Sie nicht, dass eine Zeichenkonstante in C tatsächlich eine ist int. Das Schreiben von so etwas char c; while((c = getchar()) != EOF) ...kann leicht fehlschlagen, da es EOFin a nicht darstellbar ist char.

Es gibt viel mehr charakteristische C-Fehler, die mir einfallen, aber diese können Sicherheitsprobleme verursachen.

David Thornley
quelle
Es ist nicht erforderlich, printf("%s", str)eine nackte Saite zu verwenden, wenn puts(str)derselbe Job ausgeführt wird.
Blrfl
@Blrfl fügt aber putsein Zeilenumbruchzeichen hinzu, während printfdies nicht der Fall ist.
Rechtsfalte
Könnte auch tun fputs(str, stdout), was nicht.
Blrfl
In Bezug auf den Ganzzahlüberlauf: Die Verwendung von vorzeichenbehafteten Ints ist keine Lösung, da ein Überlaufen diese zu UB führt. Die einzige (schmerzhafte) Lösung besteht darin, entweder formal zu beweisen, dass Sie niemals überlaufen, oder zur Laufzeit zu prüfen (aber korrekt zu prüfen, was auch schwierig ist, ohne dass die Prüfung überläuft).
Sleske
@DavidThornley: C11 & C ++ 14 Standard entfernt bekommt () Funktion aus der Standardbibliothek aufgrund seiner Gefährlichkeit.
Zerstörer
5

Einige der C-spezifischen Risiken umfassen: Pufferüberläufe , Formatierungszeichenfolgenangriffe und Ganzzahlüberläufe .

Nemanja Trifunovic
quelle
1
Pufferüberläufe sind nicht C-spezifisch - jede Sprache mit Zeigern kann dies haben. Ganzzahlige Überläufe gelten für nahezu jede Sprache und können auch in verwaltetem Code leicht auftreten.
Steve
1
@Steve, es sind nicht wirklich Zeiger, die dieses Problem verursachen, aber wie die Sprache keine Array-Grenzen erzwingt.
Doug T.
2
@Steve die Frage war nicht nach Dingen, die nur C betreffen, sondern etwas, das C-Programmierer beachten sollten.
AttackingHobo
1
@Steve: C ist ungewöhnlich anfällig für Pufferüberläufe, teilweise aufgrund der mangelnden Unterstützung für die Bereichsprüfung und der Anzahl der Bibliotheksfunktionen, die Puffer für Sie gerne überlaufen lassen.
David Thornley
Ich verstehe, dass die Frage insbesondere nach C gestellt wird, aber ich denke, es lohnt sich zu klären, falls die Antwort aus dem Zusammenhang gerissen wird, dass diese Risiken allgemeiner sind. Insbesondere Entwickler von verwaltetem Code (IMHO) sind in Bezug auf die Sicherheit viel zu selbstgefällig, und insbesondere Ganzzahlüberläufe wirken sich auf die meisten Sprachen aus.
Steve
4

Hier ist ein leicht zu übersehendes Risiko, das Probleme verursachen kann, deren Behebung Stunden dauern wird.

Betrachten Sie den folgenden Code, der problemlos kompiliert werden kann.

if(lpstr_current_state = CONST_EMERGENCY_STATE_HOLY_CRAP)
{
    do_warn_joint_chiefs_of_staff_of_nuclear_attack();
}

Wenn Sie überprüfen, ob es vorhanden lpstr_current_stateist CONST_EMERGENCY_STATE_HOLY_CRAP, weisen Sie es tatsächlich zu. Es ist besser, die konstante Variable immer links zu setzen. Wenn Sie die Konstante links setzen, schlägt der Compiler fehl, da Sie einer Variablen keinen Wert zuweisen können.

if(CONST_EMERGENCY_STATE_HOLY_CRAP = lpstr_current_state)
{
    do_warn_joint_chiefs_of_staff_of_nuclear_attack();
}

Dann können Sie sich leicht sagen: "Heiliger Mist, das hätte schlimm sein können", während Sie den zu lesenden Code korrigieren ...

if(CONST_EMERGENCY_STATE_HOLY_CRAP == lpstr_current_state)
{
    do_warn_joint_chiefs_of_staff_of_nuclear_attack();
}
Kristofer Hoch
quelle
7
Dies ist für einen Compiler im Gegensatz zu einigen anderen Problemen leicht zu erkennen und als Warnung zu kennzeichnen. Leider machen es nicht alle Compiler einfach.
David Thornley
2
Dies kann in anderen Sprachen als C geschehen, in jeder Sprache, die =und verwendet ==.
FrustratedWithFormsDesigner
3
Dies ist auch keine wirkliche Sicherheitslücke, dies ist ein Fehler.
Chris Pitman
1
Diese werden Yoda-Bedingungen genannt.
2
@Kristofer Hoch: Wenn wir einen wahrscheinlichen C-Fehler als Risiko bezeichnen und ihn hier in Betracht ziehen, brauchen wir ein viel größeres Forum.
David Thornley
0

Es gibt nur ein Sicherheitsrisiko: Die Tatsache, dass es Personen außerhalb gibt, die ihr Bestes tun, um Schwachstellen in Ihrer Software zu erkennen und sie zu ihrem eigenen Vorteil auszunutzen. Alles andere folgt von dort.

Wenn Sie also denken, "niemand, der bei klarem Verstand ist ...", müssen Sie sofort denken, "außer jemand, der sich in die Computer anderer Leute hacken möchte, würde genau das tun".

Die größte Konsequenz ist, dass Sie immer dann, wenn Sie auf Ereignisse außerhalb reagieren (z. B. indem Sie von außen gelieferte Daten verarbeiten), davon ausgehen müssen, dass diese Daten unter der Kontrolle Ihres schlimmsten Feindes standen.

gnasher729
quelle
Obwohl ich den Absätzen zwei und drei zustimmen würde, ist es in meinen Augen ein bisschen schwierig, dem Angreifer die Schuld zu geben. Für einen erfolgreichen Angriff sind immer zwei erforderlich: Ein Programmierer, der es vermasselt, und ein Angreifer, der den Programmierer auf frischer Tat ertappt. Die Sicherheitslücke ist jedoch vorhanden, bevor der Angreifer sie ausnutzen kann. Und dafür ist der Programmierer verantwortlich zu machen.
cmaster