Table of Contents
Exploziile de bule rămân una dintre cele mai persistente și periculoase vulnerabilități de securitate în programarea C. În ciuda faptului că sunt bine documentate de zeci de ani, ele continuă să cauzeze probleme serioase, cum ar fi corupția datelor, prăbușiri de sistem și execuția de cod la distanță. Scrierea codului securizat C necesită o înțelegere profundă a modului în care apar supraîncarcarea tamponului și o abordare disciplinată a prevenirii acestora. Acest articol oferă un ghid cuprinzător pentru scrierea unui cod C robust, rezistent la supraîncărcare, acoperind concepte fundamentale, funcții sigure, tehnici de validare, protecția compilatorului și măsuri defensive moderne.
Înțelegerea fluxurilor de suprasarcină ale balonului
Un tampon de supraîncarcare se întâmplă atunci când un program scrie mai multe date la un bloc contiguu de memorie (un tampon) decât tampon a fost alocat pentru a deține. Deoarece tampons locuiește în stivă sau memorie grămadă, depășind limitele lor suprascrie locațiile de memorie adiacente. Această corupție poate modifica starea programului, introduce un comportament imprevizibil, sau să fie exploatat de către un atacator pentru a injecta și executa codul arbitrar.
Consecinţele depind de ceea ce este suprascris. Suprascrierea unei adrese de returnare pe stiva poate redirecționa executarea către codul controlat de atacator. Pointer-ul poate duce la memorie arbitrară scrie. Chiar şi accidente simple pot fi influenţate pentru negare-de-service atacuri. Înţelegerea mecanicii este primul pas spre prevenire.
Suprafluxuri pe bază de stiva
Variabilele locale, inclusiv tamponele declarate funcţiile interioare, sunt stocate pe stivă. Stackul deţine şi adresa de întoarcere, indicii de cadru salvate şi alte date de control. Când un tampon liniar ca ] este depăşit, datele se varsă în adresa de întoarcere şi dincolo. Explozii clasice precum viermele Morris (1988) au folosit stive de deversate pentru a obţine acces neautorizat.
Suprafluxuri pe bază de heap
Tamponele alocate dinamic (prin, , etc.) se află pe morman. Fluxurile de apă pot corupe metadatele folosite de către alocator, ducând la accidente sau exploatare prin pulverizarea cu grămezi sau prin atacuri fără utilizare. Deversările de apă sunt mai greu de exploatat, dar la fel de periculoase.
Funcţiile vulnerabile comune şi alternativele sigure ale acestora
Biblioteca standard C oferă mai multe funcții care nu efectuează verificarea limitelor. Folosirea acestora este cea mai frecventă cauză a supraîncărcărilor tampon. Înlocuirea lor cu omologi mai sigure este o bună practică fundamentală.
Copiere și concatenare string
- [
- Mai bine încă:
Ieșire și intrare în format
Copiază și mută memoria
- Unele platforme furnizează din anexa K (opțională în C11), dar adoptarea este limitată.
Validarea și gestionarea dimensiunilor
Chiar și cu funcții sigure, trebuie să valideze lungimile de intrare, asigura dimensiuni tampon adecvate, și să se ocupe de trunchiare potențial grațios.
Verificați lungimile de intrare
Înainte de copierea sau procesarea datelor externe (intrarea utilizatorului, datele rețelei, conținutul fișierului), se determină lungimea maximă acceptabilă și se respinge sau se trumcate datele care o depășesc.
#define MAX_INPUT 255
char buffer[MAX_INPUT + 1]; // +1 for null
if (strlen(user_input) > MAX_INPUT) {
// Handle error: reject or truncate
fputs("Input too long", stderr);
return -1;
}
strncpy(buffer, user_input, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';
Utilizați Buffere fixe cu limite cunoscute
Ori de câte ori este posibil, defini tampone cu o dimensiune constantă și aplică-l pe tot codul. Evitați array-uri de lungime variabilă (VLA) care pot provoca supraîncărcări stiva dacă sunt furnizate dimensiuni mari. În schimb, aloca dinamic cu controale de dimensiune explicită.
Manipulează cu precizie Truncation
Functii ca si pot trunchia date. Fiti constienti de valoarea returnarii pentru a detecta trunchiarea si a decide daca datele trunchiate sunt acceptabile sau daca trebuie sa se creasca o eroare. Ignorand trunchiarea, puteti lasa tamponele intr-o stare neasteptata.
Steaguri de securitate ale compilatorului și protecție pe timp de execuție
Compilatorii moderni oferă steaguri care adaugă detectarea și atenuarea de supraîncarcării tamponului fără modificări de cod. Activați-le în sistemul de construire.
- /
Protecţii ale sistemului de operare
Stack canarii sunt doar un singur strat. Tehnologiile de atenuare a exploatării în OS moderne includ:
- Producţia de execuţie a datelor (DEP) / NX bit
- Address Layout Randomization (ASLR)
- Relocare numai citire (RELRO)
Activarea acestor protecţii (de obicei implicit) ridică bara de exploatare, dar nu înlocuieşte codificarea securizată.
Audituri de coduri și analiză statică
Revizuire umană combinată cu analiza statică automată poate prinde probleme de supraîncărcare tampon timpuriu. Integrați aceste în fluxul de lucru de dezvoltare.
- Review de cod manual
- Instrumente de analiză statică
- Fuzzeng
Exemple practice de cod securizat
Copie cu coardă sigură cu controale cu limite
#include <stdio.h>
#include <string.h>
int safe_string_copy(char *dest, size_t dest_size, const char *src) {
if (!dest || !src || dest_size == 0) {
return -1; // Invalid parameters
}
size_t src_len = strlen(src);
if (src_len >= dest_size) {
// Source too large; truncation or error
// Option: copy what fits and null-terminate
strncpy(dest, src, dest_size - 1);
dest[dest_size - 1] = '\0';
return 1; // Truncation occurred
}
strncpy(dest, src, dest_size);
// strncpy fills remaining with null, so dest_size fits; no need to null-terminate if src shorter
return 0; // Success, no truncation
}
Manipularea sigură a Integerului pentru dimensiuni de buffer
Explozia de bule poate rezulta, de asemenea, din supraîncărcări întregi atunci când dimensiunile de calcul. Verificați întotdeauna aritmetica înainte de alocare.
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
void *safe_malloc_array(size_t nmemb, size_t size) {
if (nmemb == 0 || size == 0) {
return NULL; // Or handle zero-size allocation
}
if (nmemb > SIZE_MAX / size) {
// Integer overflow would occur
errno = ENOMEM;
return NULL;
}
return malloc(nmemb * size);
}
Folosind snprintf for Formatted Strings
char log_message[256];
int ret = snprintf(log_message, sizeof(log_message),
"User %s logged in from %s", username, ip_address);
if (ret < 0) {
// Output error
} else if ((size_t)ret >= sizeof(log_message)) {
// Truncation occurred; handle if needed
}
Cele mai bune practici suplimentare
- Inițializează tamponele
- Evitați recursiunea cu adâncimea nelegată
- Utilizați calificativ[
- Preferă -corectitudine
- Managementul erorilor de aplicare
Resurse pentru învăţarea în continuare
- SEI CERT C Coding Standard
- CWE-120: Copie de tastatură fără verificare Dimensiunea de uiar
- [ ]OWASP Buffer Overflow
- GNU C Library Manual: String and Array Utilities
- AdressSanitizer
Concluzie
Prevenirea deversărilor de tampon în C nu este opțională; este o responsabilitate fundamentală a oricărui dezvoltator care lucrează cu limba. Prin înțelegerea mecanismelor de supraîncărcare, înlocuirea funcțiilor periculoase cu alternative mai sigure, validarea riguroasă a intrărilor și a dimensiunilor, permițând protecția compilatorului, și utilizând analiza și testarea statică, puteți reduce dramatic riscul acestor vulnerabilități. Nu este suficientă nicio tehnică unică; apărarea în profunzime