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

  1. Desbordament de Memòria (Buffer Overflow)
  2. Validació d'Entrades
  3. Gestió de Memòria Segura
  4. Control d'Accés
  5. Encriptació i Hashing
  6. Gestió d'Errors i Excepcions
  7. Pràctiques de Codificació Segura

  1. 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;
}

  1. 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;
}

  1. 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;
}

  1. 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;
}

  1. 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;
}

  1. 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;
}

  1. 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 de strcpy.
  • 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

Mòdul 2: Tipus de Dades i Variables

Mòdul 3: Flux de Control

Mòdul 4: Funcions

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

Mòdul 10: Temes Avançats

Mòdul 11: Millors Pràctiques i Optimització

Mòdul 12: Projecte i Avaluació Final

© Copyright 2024. Tots els drets reservats