🚀 Nuova versione beta disponibile! Feedback o problemi? Contattaci

Sanitizzazione dell'Input in C

Codegrind TeamAug 23 2024

La sanitizzazione dell’input è una pratica cruciale nello sviluppo del software per prevenire vulnerabilità come buffer overflow, injection attacks, e altre forme di exploit. Nel linguaggio C, dove la gestione della memoria è manuale, è particolarmente importante garantire che tutti gli input siano accuratamente validati e puliti prima di essere utilizzati. In questa guida, esploreremo le tecniche e le best practice per la sanitizzazione dell’input in C, al fine di garantire la sicurezza e la robustezza del tuo software.

Perché è Importante la Sanitizzazione dell’Input?

Il codice C è noto per essere potente, ma anche pericoloso quando si tratta di gestione della memoria. Un input non validato può portare a una serie di problemi di sicurezza, come:

  • Buffer Overflow: Un input che eccede la dimensione prevista di un buffer può sovrascrivere altre parti della memoria.
  • Injection Attacks: Gli input non sanitizzati possono contenere comandi malevoli che vengono eseguiti dal programma.
  • Crash e Comportamento Imprevedibile: Input imprevisti o malformati possono causare crash o comportamenti anomali.

Tecniche di Sanitizzazione dell’Input

1. Validazione della Lunghezza dell’Input

Uno dei primi passi nella sanitizzazione dell’input è la verifica della lunghezza dell’input rispetto alla capacità del buffer che lo riceve.

Esempio di Validazione della Lunghezza dell’Input

#include <stdio.h>
#include <string.h>

void leggi_input(char *buffer, size_t dimensione) {
    printf("Inserisci una stringa: ");
    fgets(buffer, dimensione, stdin);

    // Rimuovere il newline finale se presente
    buffer[strcspn(buffer, "\n")] = '\0';
}

int main() {
    char buffer[20];
    leggi_input(buffer, sizeof(buffer));
    printf("Hai inserito: %s\n", buffer);
    return 0;
}

In questo esempio, fgets viene utilizzato al posto di gets per evitare il rischio di buffer overflow, poiché fgets limita la lunghezza dell’input.

2. Escaping dei Caratteri Speciali

Quando l’input può includere caratteri che devono essere trattati in modo speciale (come ;, ', ", \, ecc.), è necessario applicare l’escaping o la rimozione di questi caratteri per prevenire injection attacks.

Esempio di Escaping dei Caratteri

#include <stdio.h>
#include <string.h>

void escape_caratteri(char *input, char *output, size_t dimensione) {
    size_t j = 0;
    for (size_t i = 0; i < strlen(input) && j < dimensione - 1; i++) {
        if (input[i] == '\'' || input[i] == '\"' || input[i] == '\\') {
            output[j++] = '\\';
        }
        output[j++] = input[i];
    }
    output[j] = '\0';
}

int main() {
    char input[50];
    char output[100];
    printf("Inserisci una stringa: ");
    fgets(input, sizeof(input), stdin);

    // Rimuovere il newline finale se presente
    input[strcspn(input, "\n")] = '\0';

    escape_caratteri(input, output, sizeof(output));
    printf("Stringa sanitizzata: %s\n", output);
    return 0;
}

In questo esempio, la funzione escape_caratteri aggiunge un carattere di escape (\) davanti ai caratteri speciali, riducendo il rischio di injection attacks.

3. Uso di Funzioni di Libreria Sicure

Molte delle funzioni standard della libreria C, come gets, strcpy, e sprintf, sono note per essere insicure in quanto non verificano la dimensione del buffer di destinazione. È preferibile utilizzare le versioni sicure di queste funzioni, come fgets, strncpy, e snprintf.

Esempio di Uso di Funzioni Sicure

#include <stdio.h>

int main() {
    char buffer[100];
    int valore = 42;

    snprintf(buffer, sizeof(buffer), "Il valore è: %d", valore);
    printf("%s\n", buffer);
    return 0;
}

4. Convalida del Tipo e del Formato dell’Input

Oltre alla lunghezza e ai caratteri speciali, è importante convalidare che l’input rispetti il tipo e il formato attesi. Ad esempio, se ci si aspetta un numero intero, è necessario verificare che l’input contenga solo cifre.

Esempio di Convalida del Tipo

#include <stdio.h>
#include <ctype.h>

int leggi_intero() {
    char buffer[10];
    printf("Inserisci un numero intero: ");
    fgets(buffer, sizeof(buffer), stdin);

    for (int i = 0; buffer[i] != '\0'; i++) {
        if (!isdigit(buffer[i]) && buffer[i] != '\n') {
            printf("Input non valido.\n");
            return -1;
        }
    }

    return atoi(buffer);
}

int main() {
    int numero = leggi_intero();
    if (numero != -1) {
        printf("Hai inserito: %d\n", numero);
    }
    return 0;
}

In questo esempio, la funzione leggi_intero verifica che l’input contenga solo cifre prima di convertirlo in un intero.

5. Sanity Checks

I sanity checks sono controlli aggiuntivi che verificano la plausibilità dell’input rispetto al contesto del programma. Ad esempio, se l’input rappresenta un’età, deve essere compreso in un intervallo realistico.

Esempio di Sanity Check

#include <stdio.h>

int leggi_eta() {
    int eta;
    printf("Inserisci la tua età: ");
    scanf("%d", &eta);

    if (eta < 0 || eta > 120) {
        printf("Età non valida.\n");
        return -1;
    }

    return eta;
}

int main() {
    int eta = leggi_eta();
    if (eta != -1) {
        printf("Hai inserito: %d\n", eta);
    }
    return 0;
}

6. Rimozione degli Input Pericolosi

In alcuni casi, può essere necessario rimuovere completamente o sostituire parti di input che potrebbero essere pericolosi, come script HTML o comandi di shell.

Esempio di Rimozione di Script HTML

#include <stdio.h>
#include <string.h>

void rimuovi_html(char *input, char *output, size_t dimensione) {
    size_t j = 0;
    for (size_t i = 0; i < strlen(input) && j < dimensione - 1; i++) {
        if (input[i] == '<') {
            while (input[i] != '>' && input[i] != '\0') i++;
        } else {
            output[j++] = input[i];
        }
    }
    output[j] = '\0';
}

int main() {
    char input[100];
    char output[100];
    printf("Inserisci una stringa con HTML: ");
    fgets(input, sizeof(input), stdin);

    rimuovi_html(input, output, sizeof(output));
    printf("Stringa senza HTML: %s\n", output);
    return 0;
}

In questo esempio, la funzione rimuovi_html elimina qualsiasi tag HTML dall’input.

Conclusioni

La sanitizzazione dell’input in C è essenziale per prevenire vulnerabilità di sicurezza e garantire che il software funzioni in modo affidabile. Implementando le tecniche descritte in questa guida, puoi proteggere il tuo codice da buffer overflow, injection attacks e altri problemi comuni che possono derivare da input non validati. Scrivere codice sicuro richiede attenzione e disciplina, ma è un investimento necessario per evitare potenziali exploit e malfunzionamenti nel software.