Programa no seguro C que acepta entradas de cadena maliciosas

2

Tengo una pregunta relacionada con este programa de C insegura.

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);
}

A partir de este código, podemos ver que printf(text) es potencialmente inseguro ya que un usuario malintencionado puede ingresar una cadena maliciosa en él. Tomemos, por ejemplo, a un usuario que ingrese %s como su entrada, lo que resultará en que %s se almacene en otra ubicación de memoria que se definirá en la pila. Por ejemplo, supongamos que %s se almacena en la dirección de memoria 5054 en la que el número 5054 se almacenaría en la pila para permitir que el procesador sepa dónde se encuentra %s .

Ahora, cuando un compilador ejecuta printf("%s", text) , buscará en la pila y se dirigirá a la dirección 5054. Sin embargo, ¿qué pasa con printf(text) ? ¿Cómo accede a la dirección de 5054 para imprimir %s que después de imprimir podría dar como resultado un error de segmentación?

    
pregunta weejing 21.04.2016 - 04:17
fuente

1 respuesta

4
  

Ahora, cuando un compilador ejecuta printf ("% s", texto); buscará en la pila e irá a la dirección 5054. Sin embargo, ¿qué pasa con printf (texto)? ¿Cómo accede a la dirección de 5054 para imprimir "% s" que después de imprimir puede dar como resultado un error de segmentación?

No lo hace. En el caso de que el usuario ingrese "% s" como entrada, habrá dos cadenas en diferentes ubicaciones, ambas con "% s": la constante de la cadena del segundo printf y la text char array que contiene la entrada del usuario.

Esto es lo que está pasando con más detalle:

printf("%s", text);

En este caso, el primer argumento es una constante de cadena. Entonces, el compilador crea una cadena que contiene "% s" y la agrega a una tabla de constantes de cadena en algún lugar de la memoria (digamos en la dirección 5054). Cuando se llama a este printf , la dirección de la constante de cadena (5054) se coloca en la pila, junto con la dirección de la matriz text . (El orden en que se colocan en la pila depende del orden de empuje del argumento, pero generalmente es de derecha a izquierda). Luego, la dirección de ejecución actual se coloca en la pila o en un registro especial (para que la CPU pueda regresar de la función) y la CPU salta a la dirección de la función printf . La función printf evalúa la cadena de formato y, cuando encuentra% s, busca en la pila el segundo argumento (la dirección de la cadena text ) y lo imprime.

printf(text);

En este ejemplo, solo la dirección del argumento de texto se inserta en la pila. Luego, la dirección de ejecución se guarda y la CPU salta a la dirección de la función printf , como antes. La dirección de la constante de cadena (5054) no se coloca en la pila, porque no hay una constante de cadena en la lista de argumentos de la función.

En este caso, la función printf evalúa la cadena de formato, y cuando encuentra el% s que ingresó el usuario, busca en la pila el segundo argumento, pero no hay uno, así que todo lo que estaba en la pila se leerá, se tratará como la dirección de una cadena, se quitará la referencia para imprimirla y probablemente se produzca un fallo de segmentación.

printf es una función Variadic , lo que significa que puede tomar un número variable de argumentos. Se basa en el análisis en tiempo de ejecución de la cadena de formato para determinar cuántos argumentos se le deben pasar. Esto es lo que lo hace vulnerable a los datos maliciosos: el contenido de la cadena de formato no coincide con el número de argumentos que se pasaron realmente.

    
respondido por el samgak 21.04.2016 - 06:11
fuente

Lea otras preguntas en las etiquetas