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
| Auswirkung | Details |
|---|---|
| Vertraulichkeit | Bereich: Vertraulichkeit Speicher lesen - Angreifer können möglicherweise sensible Teile des Speichers durch Out-of-bounds-Pointer-Lesezugriffe lesen. |
| Verfügbarkeit | Bereich: Verfügbarkeit DoS: Absturz, Beendigung oder Neustart - Der Zugriff auf ungültige Speicherorte verursacht unerwartete Anwendungsbeendigung. |
| Integrität, Vertraulichkeit, Verfügbarkeit | Bereich: 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
- MITRE Corporation. "CWE-823: Use of Out-of-range Pointer Offset." https://cwe.mitre.org/data/definitions/823.html
- CERT C Secure Coding Standard. "ARR30-C. Do not form or use out-of-bounds pointers or array subscripts."
- Google. "AddressSanitizer." https://github.com/google/sanitizers/wiki/AddressSanitizer