Programma C non sicuro che accetta input di stringa dannosi

2

Ho una domanda riguardante questo programma C non sicuro.

int main(int argc, char **argv)
{
    char text[32];
    static int some_value = -72;
    strcpy(text, argv[1]); /* copy the parameter into the array "text" */
    printf("This is how you print correctly:\n");
    printf("%s", text);
    printf("This is how not to print:\n");
    printf(text);
    printf("some_value @ 0x%08x = %d [0x%08x]", &some_value, some_value, some_value);
    return(0);
}

Da questo codice possiamo vedere che printf(text) è potenzialmente pericoloso poiché un utente malintenzionato può inserire una stringa dannosa in esso. Prendiamo ad esempio un utente che immette %s come suo input che risulterà in %s memorizzato in un'altra posizione di memoria che verrebbe definita nello stack. Ad esempio, supponiamo che %s sia memorizzato nell'indirizzo di memoria 5054 in cui il numero 5054 verrebbe memorizzato nello stack per consentire al processore di sapere dove si trova %s .

Ora, quando un compilatore esegue printf("%s", text) , cercherebbe nello stack e andrà all'indirizzo 5054. Tuttavia, che dire di printf(text) ? Come accede all'indirizzo 5054 per stampare %s che dopo la stampa potrebbe causare un errore di segmentazione?

    
posta weejing 21.04.2016 - 04:17
fonte

1 risposta

4

Now when a compiler runs printf("%s", text);, it would look into the stack and go to the address 5054. However what about printf(text)? How does it access the address of 5054 to print "%s" which after printing might result to a segmentation fault?

Non è così. Nel caso in cui l'utente immetta "% s" come input, ci saranno due stringhe in posizioni diverse, entrambe contenenti "% s": la costante di stringa dal secondo printf , e text array di caratteri contenenti l'input dell'utente.

Ecco cosa sta succedendo in modo più dettagliato:

printf("%s", text);

In questo caso, il primo argomento è una costante di stringa. Quindi, il compilatore crea una stringa contenente "% s" e la aggiunge a una tabella di costanti di stringa da qualche parte in memoria (diciamo all'indirizzo 5054). Quando viene chiamato questo printf , l'indirizzo della costante di stringa (5054) viene posizionato nello stack, insieme all'indirizzo della matrice text . (L'ordine in cui vengono inseriti nello stack dipende dall'ordine push dell'argomento, ma di solito è da destra a sinistra). Quindi l'indirizzo di esecuzione corrente viene posto nello stack o in un registro speciale (in modo che la CPU possa tornare dalla funzione) e la CPU salta all'indirizzo della funzione printf . La funzione printf valuta la stringa di formattazione e quando trova% s, appare sullo stack per il secondo argomento (l'indirizzo della stringa text ) e lo stampa.

printf(text);

In questo esempio, solo l'indirizzo dell'argomento di testo viene inserito nello stack. Quindi l'indirizzo di esecuzione viene salvato e la CPU salta all'indirizzo della funzione printf , come prima. L'indirizzo della costante di stringa (5054) non è posizionato sullo stack, perché non c'è una costante di stringa nell'elenco di argomenti della funzione.

In questo caso, la funzione printf valuta la stringa di formattazione, e quando trova% s che l'utente ha inserito, cerca lo stack per il secondo argomento, ma non ce n'è uno, quindi qualsiasi cosa fosse attiva lo stack verrà letto, trattato come l'indirizzo di una stringa, de-referenziato per stamparlo e probabilmente si verificherà un errore di segmentazione.

printf è una funzione Variadic , il che significa che può richiedere un numero variabile di argomenti. Si basa sull'analisi di runtime della stringa di formattazione per determinare quanti argomenti (dovrebbero) sono stati passati ad esso. Questo è ciò che rende vulnerabile ai dati dannosi: il contenuto della stringa di formattazione non corrisponde al numero di argomenti effettivamente passati.

    
risposta data 21.04.2016 - 06:11
fonte

Leggi altre domande sui tag