La seguretat en la programació és un aspecte crucial que sovint es passa per alt fins que es produeix un problema. En aquest tema, explorarem les pràctiques de seguretat que hauríem de seguir quan programem en C per evitar vulnerabilitats i assegurar-nos que el nostre codi sigui robust i segur.
Conceptes Clau
- Desbordament de Memòria (Buffer Overflow)
- Validació d'Entrades
- Gestió de Memòria Segura
- Control d'Accés
- Encriptació i Hashing
- Gestió d'Errors i Excepcions
- Pràctiques de Codificació Segura
- Desbordament de Memòria (Buffer Overflow)
El desbordament de memòria és una de les vulnerabilitats més comunes en C. Es produeix quan un programa escriu més dades en un buffer del que aquest pot contenir, sobreescrivint així la memòria adjacent.
Exemple de Desbordament de Memòria
#include <stdio.h> #include <string.h> void unsafeFunction(char *input) { char buffer[10]; strcpy(buffer, input); // Potencial desbordament de memòria printf("Buffer: %s\n", buffer); } int main() { char input[20] = "This is too long!"; unsafeFunction(input); return 0; }
Solució
Utilitzar funcions segures com strncpy
en lloc de strcpy
.
#include <stdio.h> #include <string.h> void safeFunction(char *input) { char buffer[10]; strncpy(buffer, input, sizeof(buffer) - 1); buffer[sizeof(buffer) - 1] = '\0'; // Assegurar que el buffer està nul-terminat printf("Buffer: %s\n", buffer); } int main() { char input[20] = "This is too long!"; safeFunction(input); return 0; }
- Validació d'Entrades
Sempre hem de validar les entrades de l'usuari per evitar injeccions de codi i altres tipus d'atacs.
Exemple de Validació d'Entrades
#include <stdio.h> #include <stdlib.h> int main() { char input[10]; printf("Enter a number: "); fgets(input, sizeof(input), stdin); int number = atoi(input); if (number == 0 && input[0] != '0') { printf("Invalid input!\n"); } else { printf("You entered: %d\n", number); } return 0; }
- Gestió de Memòria Segura
Gestionar la memòria de manera segura és essencial per evitar fuites de memòria i altres problemes.
Exemple de Gestió de Memòria
#include <stdio.h> #include <stdlib.h> int main() { int *array = (int *)malloc(10 * sizeof(int)); if (array == NULL) { fprintf(stderr, "Memory allocation failed\n"); return 1; } // Utilitzar l'array free(array); // Alliberar la memòria return 0; }
- Control d'Accés
Assegurar-nos que només els usuaris autoritzats poden accedir a certes parts del codi o dades.
Exemple de Control d'Accés
#include <stdio.h> #include <string.h> void authenticate(char *password) { char correctPassword[] = "securepassword"; if (strcmp(password, correctPassword) == 0) { printf("Access granted\n"); } else { printf("Access denied\n"); } } int main() { char input[20]; printf("Enter password: "); fgets(input, sizeof(input), stdin); input[strcspn(input, "\n")] = '\0'; // Eliminar el salt de línia authenticate(input); return 0; }
- Encriptació i Hashing
Utilitzar tècniques d'encriptació i hashing per protegir dades sensibles.
Exemple d'Hashing
#include <stdio.h> #include <string.h> #include <openssl/sha.h> void hashPassword(char *password) { unsigned char hash[SHA256_DIGEST_LENGTH]; SHA256((unsigned char *)password, strlen(password), hash); printf("Hashed password: "); for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { printf("%02x", hash[i]); } printf("\n"); } int main() { char password[20]; printf("Enter password: "); fgets(password, sizeof(password), stdin); password[strcspn(password, "\n")] = '\0'; // Eliminar el salt de línia hashPassword(password); return 0; }
- Gestió d'Errors i Excepcions
Gestionar els errors de manera adequada per evitar que el programa es comporti de manera inesperada.
Exemple de Gestió d'Errors
#include <stdio.h> #include <stdlib.h> int main() { FILE *file = fopen("nonexistent.txt", "r"); if (file == NULL) { perror("Error opening file"); return 1; } // Llegir i processar el fitxer fclose(file); return 0; }
- Pràctiques de Codificació Segura
Seguir pràctiques de codificació segura per minimitzar les vulnerabilitats.
Consells de Codificació Segura
- Evitar l'ús de funcions insegures: Utilitzar alternatives segures com
strncpy
en lloc destrcpy
. - Validar totes les entrades: No confiar mai en les dades d'entrada sense validar-les.
- Gestionar la memòria amb cura: Assegurar-se de que tota la memòria assignada es desallibera.
- Utilitzar tècniques d'encriptació: Protegir dades sensibles amb encriptació i hashing.
- Controlar els accessos: Implementar mecanismes d'autenticació i autorització.
Resum
En aquest tema, hem explorat diverses consideracions de seguretat que hauríem de tenir en compte quan programem en C. Hem vist exemples pràctics de com evitar desbordaments de memòria, validar entrades, gestionar la memòria de manera segura, controlar l'accés, utilitzar encriptació i hashing, gestionar errors i seguir pràctiques de codificació segura. Seguir aquestes pràctiques ens ajudarà a escriure codi més segur i robust.
En el següent tema, explorarem les directrius del projecte final, on podreu aplicar tots els coneixements adquirits durant el curs.
Curs de Programació en C
Mòdul 1: Introducció al C
- Introducció a la Programació
- Configuració de l'Entorn de Desenvolupament
- Programa Hello World
- Sintaxi i Estructura Bàsiques
Mòdul 2: Tipus de Dades i Variables
Mòdul 3: Flux de Control
Mòdul 4: Funcions
- Introducció a les Funcions
- Arguments de Funció i Valors de Retorn
- Àmbit i Durada de les Variables
- Funcions Recursives
Mòdul 5: Arrays i Strings
Mòdul 6: Punteres
Mòdul 7: Estructures i Unions
Mòdul 8: Assignació Dinàmica de Memòria
Mòdul 9: Gestió d'Arxius
- Introducció a la Gestió d'Arxius
- Lectura i Escriptura d'Arxius
- Posicionament d'Arxius
- Gestió d'Errors en Operacions d'Arxius
Mòdul 10: Temes Avançats
- Directives del Preprocessador
- Arguments de Línia de Comandes
- Llistes d'Arguments Variables
- Multifil en C
Mòdul 11: Millors Pràctiques i Optimització
- Llegibilitat del Codi i Documentació
- Tècniques de Depuració
- Optimització del Rendiment
- Consideracions de Seguretat