Verwendung eines Out-of-range-Pointer-Offsets

Beschreibung

Verwendung eines Out-of-range-Pointer-Offsets ist eine Speichersicherheits-Schwachstelle, bei der Software Zeigerarithmetik mit einem Offset durchführt, der über den beabsichtigten Bereich gültiger Speicherorte für den resultierenden Pointer hinauszeigen kann. Obwohl Pointer technisch auf jede Speicheradresse verweisen können, beabsichtigen Programme typischerweise nur den Zugriff auf bestimmte Speicherbereiche wie zusammenhängende Array-Elemente oder Felder innerhalb einer Struktur. Wenn Offsets aus nicht vertrauenswürdigen Quellen stammen, aus falschen Berechnungen resultieren oder auf andere Programmierfehler zurückzuführen sind, kann der berechnete Pointer auf Speicher außerhalb der beabsichtigten Grenzen verweisen, was zu Out-of-bounds-Lese- oder -Schreibzugriffen führt.

Risiko

Diese Schwachstelle ermöglicht Angreifern das Lesen von oder Schreiben auf unbeabsichtigte Speicherorte. Out-of-bounds-Lesezugriffe können sensible Daten wie kryptografische Schlüssel, Passwörter oder Sicherheitstoken preisgeben, die neben dem Zielpuffer gespeichert sind. Out-of-bounds-Schreibzugriffe können kritische Datenstrukturen beschädigen, Funktionszeiger überschreiben oder Rücksprungadressen modifizieren, um beliebige Codeausführung zu erreichen. Selbst ohne Ausnutzung verursacht der Zugriff auf ungültigen Speicher Abstürze, die zu Denial of Service führen. Die Schwachstelle ist besonders gefährlich, wenn der Offset-Wert aus externen Eingaben stammt und Angreifern direkte Kontrolle darüber gibt, auf welchen Speicherort zugegriffen wird.

Lösung

Validieren Sie alle Offset-Werte, bevor Sie sie in Zeigerarithmetik verwenden. Stellen Sie sicher, dass Offsets nicht negativ sind und innerhalb der Grenzen der Zieldatenstruktur liegen. Für Array-Zugriff überprüfen Sie, dass der Index kleiner als die Array-Größe ist. Verwenden Sie sichere APIs, die Grenzprüfung automatisch durchführen. Bevorzugen Sie in C/C++ Container-Klassen mit Grenzprüfung oder verwenden Sie während der Entwicklung Sanitizer. Implementieren Sie Defense-in-Depth mit ASLR, Stack-Canaries und DEP. Wenn Sie strukturierte Daten aus nicht vertrauenswürdigen Quellen verarbeiten, validieren Sie, dass alle Größen- und Offset-Felder mit der Gesamtdatengröße konsistent sind. Erwägen Sie die Verwendung statischer Analysetools zur Erkennung potenzieller Out-of-range-Zeigerarithmetik zur Kompilierzeit.

Häufige Auswirkungen

AuswirkungDetails
VertraulichkeitBereich: Vertraulichkeit

Speicher lesen - Angreifer können möglicherweise sensible Teile des Speichers durch Out-of-bounds-Pointer-Lesezugriffe lesen.
VerfügbarkeitBereich: Verfügbarkeit

DoS: Absturz, Beendigung oder Neustart - Der Zugriff auf ungültige Speicherorte verursacht unerwartete Anwendungsbeendigung.
Integrität, Vertraulichkeit, VerfügbarkeitBereich: Integrität, Vertraulichkeit, Verfügbarkeit

Unerlaubten Code oder Befehle ausführen - Out-of-bounds-Schreibzugriffe können Funktionszeiger oder Rücksprungadressen modifizieren und Codeausführung ermöglichen.

Beispielcode

Anfälliger Code

// Anfällig: Offset aus nicht vertrauenswürdiger Quelle ohne Validierung
void vulnerable_process_data(char *buffer, size_t buffer_size) {
    int offset;

    // Offset aus Puffer selbst lesen
    memcpy(&offset, buffer, sizeof(offset));

    // Anfällig: Keine Validierung des Offsets
    char *data_ptr = buffer + offset;

    // Könnte außerhalb des Puffers zeigen, wenn Offset zu groß oder negativ ist
    process_string(data_ptr);
}
// Anfällig: Array-Index für Zeigerarithmetik verwendet
struct item {
    char name[32];
    int value;
};

void vulnerable_get_item(struct item *items, int count, int socket) {
    int32_t requested_index;

    recv(socket, &requested_index, sizeof(requested_index), 0);

    // Anfällig: Keine Grenzprüfung
    struct item *selected = items + requested_index;

    // Wenn requested_index < 0 oder >= count, Out-of-bounds-Zugriff
    printf("Name: %s, Wert: %d\n", selected->name, selected->value);
}

Korrigierter Code

// Korrigiert: Offset gegen Puffergrenzen validieren
int fixed_process_data(char *buffer, size_t buffer_size) {
    int offset;

    if (buffer_size < sizeof(offset)) {
        return -1;  // Puffer zu klein für Offset-Feld
    }

    memcpy(&offset, buffer, sizeof(offset));

    // Korrigiert: Offset ist innerhalb des Puffers validieren
    if (offset < 0 || (size_t)offset >= buffer_size) {
        return -1;  // Ungültiger Offset
    }

    char *data_ptr = buffer + offset;

    // Zusätzliche Prüfung: Sicherstellen, dass wir sicher von data_ptr lesen können
    size_t remaining = buffer_size - offset;
    process_string_bounded(data_ptr, remaining);

    return 0;
}
// Korrigiert: Grenzgeprüfter Array-Zugriff
struct item {
    char name[32];
    int value;
};

int fixed_get_item(struct item *items, size_t count, int socket) {
    int32_t requested_index;

    recv(socket, &requested_index, sizeof(requested_index), 0);

    // Korrigiert: Index-Grenzen validieren
    if (requested_index < 0 || (size_t)requested_index >= count) {
        return -1;  // Ungültiger Index
    }

    struct item *selected = items + requested_index;
    printf("Name: %s, Wert: %d\n", selected->name, selected->value);
    return 0;
}
// Sicheres Muster: Sichere Accessor-Funktionen verwenden
#include <stdlib.h>
#include <string.h>

typedef struct {
    int *data;
    size_t size;
} safe_array;

int safe_array_get(safe_array *arr, size_t index, int *out) {
    if (index >= arr->size) {
        return -1;  // Out of bounds
    }
    *out = arr->data[index];
    return 0;
}

int safe_array_set(safe_array *arr, size_t index, int value) {
    if (index >= arr->size) {
        return -1;  // Out of bounds
    }
    arr->data[index] = value;
    return 0;
}

Verwandte CWEs

  • CWE-119: Unzureichende Beschränkung von Operationen innerhalb der Grenzen eines Speicherpuffers (Eltern)
  • CWE-125: Out-of-bounds-Lesezugriff (kann folgen)
  • CWE-787: Out-of-bounds-Schreibzugriff (kann folgen)
  • CWE-129: Unzureichende Validierung von Array-Index (kann vorangehen)
  • CWE-822: Dereferenzierung eines nicht vertrauenswürdigen Zeigers (verwandt)
  • CWE-190: Integer-Überlauf oder Wraparound (kann vorangehen - Offset-Berechnung)

Referenzen

  1. MITRE Corporation. "CWE-823: Use of Out-of-range Pointer Offset." https://cwe.mitre.org/data/definitions/823.html
  2. CERT C Secure Coding Standard. "ARR30-C. Do not form or use out-of-bounds pointers or array subscripts."
  3. Google. "AddressSanitizer." https://github.com/google/sanitizers/wiki/AddressSanitizer