ClickCease Die Bugs hinter den Schwachstellen Teil 5

Inhaltsübersicht

Abonnieren Sie unseren beliebten Newsletter

Schließen Sie sich 4.500+ Linux- und Open-Source-Experten an!

2x im Monat. Kein Spam.

Die Bugs hinter den Schwachstellen Teil 5

Joao Correia

April 27, 2023 - Technischer Evangelist

Willkommen zum letzten Teil unserer fünfteiligen Serie, in der wir uns mit den Codefehlern beschäftigen, die für die Sicherheitslücken und Exploits verantwortlich sind, vor denen wir uns schützen wollen. In diesem Teil gehen wir auf die letzten fünf Einträge der Mitre CWE Top 25von Platz 5 bis hin zu Platz 1.

 

Sie finden Teil 1 hier, Teil 2 hier, Teil 3 hierund Teil 4 hier.

 

5. Außerhalb der Grenzen lesen

 

Out-of-bounds-Read tritt auf, wenn ein Produkt Daten über das Ende oder vor dem Anfang des vorgesehenen Puffers liest. Dies kann es Angreifern ermöglichen, sensible Informationen von anderen Speicherplätzen zu lesen oder einen Absturz zu verursachen. 

 

Betrachten Sie zum Beispiel den folgenden C-Codeausschnitt, der aus einem Array mit einer benutzergesteuerten Eingabe liest:

#include <stdio.h>




int get_element(int *array, int len, int index) {

    int result;




    if (index < len) {

        result = array[index];

    } else {

        printf("Invalid index: %d\n", index);

        result = -1;

    }




    return result;

}




int main() {

    int my_array[5] = {10, 20, 30, 40, 50};

    int index = -1; // Simulating user-controlled input

    int value = get_element(my_array, 5, index);

    printf("Value at index %d: %d\n", index, value);




    return 0;

}

 

In diesem Beispiel prüft die Funktion get_element, ob der angegebene Index innerhalb der maximalen Grenze des Arrays liegt, aber sie prüft nicht die minimale Grenze. Dadurch können negative Werte als gültige Array-Indizes akzeptiert werden, was zu einem Out-of-Bounds-Read führt. Um dieses Problem zu entschärfen, fügen Sie eine Prüfung für die minimale Grenze hinzu:

 

if (index >= 0 && index < len) {

    result = array[index];

}

 

4. Unsachgemäße Eingabevalidierung

 

Eine unsachgemäße Eingabevalidierung liegt vor, wenn ein Produkt Eingaben oder Daten empfängt, diese aber nicht oder falsch validiert, was zu einem veränderten Kontrollfluss, einer willkürlichen Kontrolle über eine Ressource oder der Ausführung von willkürlichem Code führt.

 

private void buildList(int untrustedListSize) {

    if (0 > untrustedListSize) {

        die("Negative value supplied for list size, die evil hacker!");

    }

    Widget[] list = new Widget[untrustedListSize];

    list[0] = new Widget();

}


In diesem Beispiel prüft der Code, ob die Größe von untrustedListSize negativ ist, aber er prüft nicht, ob sie Null ist. Wenn ein Nullwert angegeben wird, erstellt der Code ein Array der Größe 0 und versucht dann, ein neues Widget an der ersten Stelle zu speichern, was eine Ausnahme auslöst. Um dieses Problem zu vermeiden, sollten Sie umfassende Eingabevalidierungstechniken verwenden, die alle potenziell relevanten Eigenschaften der Eingabe berücksichtigen, und sich nicht ausschließlich auf die Suche nach bösartigen oder missgestalteten Eingaben verlassen. In diesem Fall sollten wir stattdessen prüfen, ob die untrustedListSize größer als 0 ist.

 

3. Unsachgemäße Neutralisierung spezieller Elemente, die in einem SQL-Befehl verwendet werden (die gefürchtete "SQL Injection")

 

Eine SQL-Injektion liegt vor, wenn eine Anwendung einen SQL-Befehl ganz oder teilweise unter Verwendung von extern beeinflussten Eingaben aus einer vorgeschalteten Komponente konstruiert, ohne spezielle Elemente, die den beabsichtigten SQL-Befehl verändern könnten, zu neutralisieren oder falsch zu neutralisieren. 

#include <stdio.h>

#include <stdlib.h>

#include <string.h>




int main(int argc, char *argv[]) {

    char query[1024];

    char *user_input = argv[1];




    snprintf(query, sizeof(query), "SELECT * FROM users WHERE username='%s'", user_input);




    printf("Generated query: %s\n", query);




    // Execute the query...




    return 0;

}

 

In diesem Beispiel wird die Benutzereingabe direkt mit der SQL-Abfrage verknüpft, was es einem Angreifer ermöglicht, bösartigen SQL-Code einzuschleusen. Um SQL-Injection zu verhindern, verwenden Sie parametrisierte Abfragen, vorbereitete Anweisungen oder gespeicherte Prozeduren, um Benutzereingaben von SQL-Anweisungen zu trennen. In diesem Fall sollten wir vorbereitete Anweisungen verwenden:

 

#include <stdio.h>

#include <stdlib.h>

#include <mysql/mysql.h>




(...)




MYSQL_STMT *stmt = mysql_stmt_init(con);

    if (!stmt) {

        fprintf(stderr, "mysql_stmt_init() failed\n");

        exit(1);

    }




    const char *query = "SELECT * FROM users WHERE username=?";

    if (mysql_stmt_prepare(stmt, query, strlen(query)) != 0) {

        fprintf(stderr, "mysql_stmt_prepare() failed: %s\n", mysql_stmt_error(stmt));

        exit(1);

    }



Durch die Verwendung von vorbereiteten Anweisungen werden die Benutzereingaben als Daten und nicht als Teil der SQL-Abfrage behandelt, wodurch SQL-Injection effektiv verhindert wird.

2. Unsachgemäße Neutralisierung von Eingaben bei der Erstellung von Webseiten (oder "Cross-Site Scripting")

Cross-Site-Scripting (XSS)-Schwachstellen treten auf, wenn eine Anwendung vom Benutzer kontrollierbare Eingaben nicht oder falsch neutralisiert, bevor sie in eine Ausgabe eingefügt werden, die als Webseite für andere Benutzer dient. 

 

Betrachten Sie das folgende PHP-Codefragment:

 

$Benutzername = $_GET['benutzername'];

echo "Willkommen, " . $Benutzername . "!";

 

In diesem Beispiel wird die Benutzereingabe direkt in die Webseite eingebettet, ohne dass sie ordnungsgemäß bereinigt wird, so dass ein Angreifer bösartigen HTML- oder JavaScript-Code einfügen kann. Um XSS zu verhindern, sollten Sie Benutzereingaben validieren und bereinigen, sichere Ausgabekodierungstechniken verwenden, wenn Sie Benutzereingaben in Webseiten anzeigen, und Inhaltssicherheitsrichtlinien einsetzen, um die Auswirkungen eines XSS-Angriffs zu verringern. In diesem Fall sollten wir die Benutzereingaben vor der Anzeige bereinigen:

 

$Benutzername = htmlspecialchars($_GET['username'], ENT_QUOTES, 'UTF-8');

echo "Willkommen, " . $Benutzername . "!";

 

1. Unzulässiges Schreiben

 

Out-of-bounds write" tritt auf, wenn ein Produkt Daten über das Ende oder vor den Anfang des vorgesehenen Puffers hinaus schreibt, was zu Datenbeschädigung, einem Absturz oder Codeausführung führen kann. 

 

Betrachten Sie zum Beispiel den folgenden C-Codeausschnitt, der in ein Array schreibt:

#include <stdio.h>




void fill_array(int *array, int len) {

for (int i = 0; i <= len; i++) {

  array[i] = i * 10;

 }

}




int main() {

 int my_array[5];

 fill_array(my_array, 5);

 for (int i = 0; i < 5; i++) {

     printf("Element at index %d: %d\n", i, my_array[i]);

 }




return 0;

}


In this example, the function `fill_array` writes to the array `my_array` using the loop variable `i`. However, the loop condition is `i <= len`, which allows the loop to run one iteration beyond the intended bounds of the array, causing an out-of-bounds write.

 

To avoid this issue, ensure that you use proper boundary checks when writing to buffers. In this case, the loop condition should be `i < len`:

 

for (int i = 0; i < len; i++) {

    array[i] = i * 10;

}

 

Mit dieser Änderung schreibt der Code korrekt in das Array innerhalb seiner Grenzen und verhindert so eine Out-of-bounds-Schreibschwachstelle.

 

Schlussfolgerung

 

Für Entwickler ist es von entscheidender Bedeutung, sich der häufigen Code-Fehler bewusst zu sein, die zu Schwachstellen in ihren Anwendungen führen können. Wenn Sie diese Probleme verstehen und sichere Programmierpraktiken implementieren, können Sie das Risiko der Ausnutzung durch Angreifer erheblich verringern.

 

Im Folgenden finden Sie einige allgemeine Grundsätze zur sicheren Kodierung, die Sie im Auge behalten sollten:

 

  • Geringstes Privileg

Stellen Sie sicher, dass Ihre Anwendungen mit den minimalen Berechtigungen ausgeführt werden, die zur Erfüllung ihrer Aufgaben erforderlich sind. Dies begrenzt die potenziellen Auswirkungen eines Sicherheitsverstoßes, indem es die Möglichkeiten des Angreifers einschränkt, seine Privilegien zu erweitern oder unbefugten Zugriff auf sensible Daten oder Systemressourcen zu erhalten.

 

  • Sichere Standardwerte

Entwerfen Sie Ihre Anwendungen so, dass die Sicherheitseinstellungen standardmäßig aktiviert sind. Die Benutzer sollten die Sicherheitsfunktionen explizit deaktivieren müssen, anstatt sie zu aktivieren. Dies fördert eine sicherere Benutzererfahrung und verringert die Wahrscheinlichkeit unsicherer Konfigurationen.

 

  • Eingehende Verteidigung

Implementieren Sie mehrere Sicherheitsebenen in Ihren Anwendungen, so dass bei einem Verstoß gegen eine Ebene die anderen weiterhin Schutz bieten können. Dazu kann die Kombination von Eingabevalidierung, Ausgabeverschlüsselung und Zugriffskontrolle gehören, um eine umfassende Verteidigung gegen verschiedene Angriffe zu gewährleisten.

 

  • Sicheres Versagen

Entwerfen Sie Ihre Anwendungen so, dass sie im Falle eines Fehlers oder einer unerwarteten Eingabe sicher abbrechen. Wenn beispielsweise eine Anwendung bei der Verarbeitung einer Benutzereingabe auf einen Fehler stößt, sollte sie keine sensiblen Informationen preisgeben oder unbeabsichtigten Zugriff gewähren. Stattdessen sollte sie den Fehler anständig behandeln und dem Benutzer eine nützliche Fehlermeldung liefern.

 

  • Einfach halten

Komplexität ist der Feind der Sicherheit. Streben Sie nach Einfachheit in Ihrem Code und minimieren Sie die Verwendung komplexer Konstrukte, die schwer zu verstehen und zu warten sind. Dadurch lassen sich potenzielle Sicherheitsprobleme leichter erkennen, und die Wahrscheinlichkeit, dass bei der Entwicklung oder Wartung neue Schwachstellen eingeführt werden, sinkt.

 

  • Regelmäßig Abhängigkeiten aktualisieren

Halten Sie die Abhängigkeiten Ihrer Anwendung auf dem neuesten Stand, da veraltete Bibliotheken und Frameworks Sicherheitsschwachstellen verursachen können. Suchen Sie regelmäßig nach Updates und Patches und integrieren Sie diese in Ihre Entwicklungs- und Bereitstellungsprozesse.

 

Wenn Sie diese Prinzipien der sicheren Kodierung einbeziehen und die in dieser Serie erwähnten häufigen Code-Fehler beheben, sind Sie auf dem besten Weg, sicherere Anwendungen zu entwickeln und Ihre Benutzer vor potenziellen Sicherheitsbedrohungen zu schützen.

Zusammenfassung
Die Bugs hinter den Schwachstellen Teil 5
Artikel Name
Die Bugs hinter den Schwachstellen Teil 5
Beschreibung
Entdecken Sie die letzten fünf Einträge in der Mitre CWE Top 25 Code Bugs Serie, in der wir uns mit Schwachstellen beschäftigen, die zu Exploits führen.
Autor
Name des Herausgebers
TuxCare
Logo des Herausgebers

Möchten Sie das Patchen von Sicherheitslücken ohne Kernel-Neustart, Systemausfallzeiten oder geplante Wartungsfenster automatisieren?

Erfahren Sie mehr über Live-Patching mit TuxCare

Werden Sie ein TuxCare-Gastautor

Los geht's

E-Mail

Beitreten

4,500

Linux & Open Source
Fachleute!

Abonnieren Sie
unseren Newsletter