Fallos y vulnerabilidades en C/C++ |
![]() « Censeur » 1587783540000
| 6 | ||
C(++) C y C++ son considerados unos de los lenguajes más potentes y eficaces que existen. Son realmente buenos y sirven para una gran cantidad de tareas, desde programas de uso general y videojuegos hasta sistemas operativos y embebidos. Ambos son lenguajes compilados, y estáticos. Aún así, tienen fallos de seguridad y funcionamiento, unos ligeros, otros mucho más graves, los cuales son: » Buffer Overflow Desbordamiento del búfer Esto ocurre cuando tienes una cierta cantidad de memoria reservada e intentas llenar esa memoria con más datos de lo que su capacidad admite. Los datos que sobran, van a espacios de memoria adyacentes. Normalmente un compilador de cualquier otro lenguaje avisaría del error y no permitirá correr el programa, pero esto no ocurre en C, y lo que hace -en algunos casos- es avisar de SEGFAULT (fallo de segmentación) mientras el proceso está ejecutandose. Esto es especialmente peligroso porque, además de manipular datos de otras variables (y en algunos casos, el mismo funcionamiento) en el programa ejecutado, puede interferir en el sistema y corromperlo. Es algo que suele ser usado para esto y para saltarse barreras de seguridad en el sistema. Varias funciones de la biblioteca estándar tiene este defecto, por lo que no se recomienda para nada su uso, las cuales son:
» Formateo de entrada y salida de datos La entrada y salida de datos es muy importante, pero la biblioteca estándar trae un par de funciones algo peligrosas, que puede causar fallos de seguridad, indeterminismo y hasta crashear al programa.
Ejecutas el programa: a dit : Todo bien. Se realiza la conversión de un doble flotante a un entero. ¿Qué tal si introducimos un tipo distinto? a dit : ¿¡Qué está ocurriendo aquí!? Scanf intenta realizar la conversión, pero al no haber ningún número, convierte a nada. El valor de a nunca se define, por lo que la variable tendrá un comportamiento indefinido. El comportamiento indefinido de una función o una variable es peligroso, porque al momento de utilizarla podría no funcionar como uno espera. Podría no ocurrir sólo esto, sino también que el programa se crashee. Esto en otros lenguajes se evita ya que no se ejecuta el código a menos que cada tipo se defina de alguna forma. Scanf verifica en el string con los argumentos formateados, "%d", si en búfer no se encuentra ningún número, pasará de cualquier otro tipo y convertirá a nada, pues el valor a convertir no fue definido. Scanf retorna la cantidad de elementos convertidos satisfactoriamente, con eso sería suficiente, ¿no? Podríamos hacer que no pare de escanear hasta que los argumentos correctos se introduzcan, Code C 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include <stdio.h> a dit : ¡Oh por Glob! ¿Qué pasó? Scanf no fue hecha para leer entrada sino para ESCANEARLA. Scanf nunca leerá algo que no se le ha mandado a escanear. asd no es un número, por lo que ni siquiera será escaneado, por lo que, Scanf irá nuevamente al búfer de entrada y se encontrará con lo mismo, entrando en un bucle infinito de escaneos fallidos. Podríamos limpiar el búfer de entrada con fflush(stdin);... No. Es una terrible práctica, primero porque no todos los sistemas lo harán, y segundo, porque aunque se pueda hacer en algunos, el comportamiento del búfer de entrada quedará indeterminado, algo que ya hace saltar alarmas. Pero... ¿qué pasa si intentamos escanear un string? (reemplaza la "%d" por una "%s") Tenemos una variable de string de 10 de tamaño, introducimos datos y el scanf se encsrga de escanearlo: a dit : a dit : ... El string ha producido un desbordamiento del búfer, bien el programa podría crashear, avisar de un fallo de segmentación o funcionar "correctamente". El comportamiento es indeterminado en el momento en el que el desbordamiento se realiza. Una forma de arreglar esto es determinar en el scanf la cantidad que debe de leer, siendo en vez de "%s", utilizar %Ns", en el que N es la cantidad de caracteres. Si sólo se quiere leer entrada, bien puede usarse fgets y realizar una función propia. Hay varias funciones incorporadas en la biblioteca estándar que permiten la conversión de unos tipos a otros. Scanf es una función que de la forma adecuada, puede llegar a ser bastante poderosa. Hay que saber usarla de la forma correcta. » Dinamismo de tipos Todo dato puede considerarse un entero. Puedes formatear un carácter como de un entero se tratase, realizar conversiones y hasta operaciones aritméticas entre tipos de datos totalmente distintos. Esto es bueno y malo a la vez. Por ejemplo: Code C 1 2 3 4 5 6 int main(void){ Ahora, hago esto: Code C 1 c *= 2; El valor será 110, lo que corresponde al carácter 'n'. No hay un sentido lógico real detrás de esa conversión. ¿Multiplicar un carácter por un número me da otro carácter? Code C 1 2 double d = 0.08; La salida será un '}'. No debo de explicar lo absurdo que es. También se pueden realizar operaciones entre enteros con signo y sin signo entre sí, con float y double, con long long y short. Fuentes: Experiencias propias y un par de artículos de Internet. Dernière modification le 1587783720000 |
![]() « Censeur » 1587784080000
| 1 | ||
Si este Thread llega a dos corazones editaré el hilo con fallos de otros lenguajes |
3 | ||
no leí nada pero le di like porque vi el número 42 y me gusta el número 42 |
![]() « Censeur » 1593817740000
| 0 | ||
Conservador a dit : Perdón por la demora. Mañana hago la pestaña sobre otros lenguajes, me re olvidé de esto. |
1 | ||
No sabía lo de la mala práctica del fflush , tendré que aprender nuevas alternativas porque mi profesor es fanático de Linux si me ve , me putea |
![]() « Censeur » 1593913320000
| 0 | ||
Conservador a dit : Hoy no he podido. Estuve algo ocupado y el poco tiempo libre que tuve para el foro lo dediqué a responderle al tipo de la foto naranja con negro. En fin, creo que me dedicaré a terminar el tema de C/C++ antes que todo. de otros idiomas no conozco mucho asi que tendré que buscar con quién cersiorarme. |