C++ Sécurité : Protection contre les injections SQL et XSS en 2024

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Quand C++ rencontre le web : pourquoi la sécurité est votre principal casse-tête

\n\n

Avez-vous déjà réfléchi à pourquoi les hackers aiment tant les applications C++ ? Non, pas parce que le code est complexe. Mais parce qu'à la poursuite de la performance, les développeurs oublient souvent la sécurité C++. Et ils en paient le prix avec les données des utilisateurs, leur réputation et de l'argent.

\n\n

Imaginez : vous avez écrit un super serveur en C++ qui traite les requêtes plus vite que l'éclair. Mais une seule entrée non échappée — et un attaquant vide toute la base de données. Ou pire encore, insère un script qui vole les sessions de tous les visiteurs du site. Cela vous semble familier ? Si non — parfait, cela signifie que vous lisez cet article au bon moment.

\n\n

Dans cet article, nous allons analyser les deux attaques les plus dangereuses sur les applications web — les injections SQL et le cross-site scripting (XSS) — et montrer comment s'en protéger spécifiquement en C++. Sans magie, avec des exemples de code réels. C'est parti.

\n\n

Injections SQL : comment les hackers transforment votre requête en arme

\n\n

L'injection SQL se produit lorsqu'un attaquant insère dans un champ de saisie (par exemple, un identifiant ou une requête de recherche) un morceau de code SQL. Si votre application insère aveuglément cette entrée dans la requête, au lieu de rechercher un utilisateur par son nom, la base de données exécutera quelque chose comme DROP TABLE users. Ou, pire encore, divulguera tous les mots de passe.

\n\n

Erreur typique de débutant (et comment l'éviter)

\n\n

Regardez ce code. Il semble inoffensif, mais c'est une bombe à retardement :

\n\n
// DANGEREUX ! Ne faites jamais cela\nstd::string username = getUserInput(); // l'utilisateur a saisi : ' OR '1'='1\nstd::string query = "SELECT * FROM users WHERE username = '" + username + "'";\n// Résultat : SELECT * FROM users WHERE username = '' OR '1'='1'\n// Retourne tous les utilisateurs !
\n\n

Vous voyez le problème ? Si l'utilisateur saisit ' OR '1'='1, la requête retournera toute la table. Et si '; DROP TABLE users; --, alors adieu la base de données.

\n\n

L'approche correcte : les requêtes paramétrées

\n\n

La seule méthode fiable pour se protéger des injections SQL en C++ est d'utiliser des requêtes paramétrées. La base de données elle-même distingue le code des données. Voici comment cela se présente avec la bibliothèque libpqxx (pour PostgreSQL) ou MySQL Connector/C++ :

\n\n
#include <iostream>\n#include <pqxx/pqxx> // libpqxx pour PostgreSQL\n\nvoid safeQuery(const std::string& username) {\n    try {\n        pqxx::connection conn("dbname=mydb user=myuser password=mypass");\n        pqxx::work txn(conn);\n        \n        // Requête paramétrée : $1 est un paramètre\n        std::string query = "SELECT * FROM users WHERE username = $1";\n        pqxx::result result = txn.exec_params(query, username);\n        \n        for (auto row : result) {\n            std::cout << "User: " << row["username"].c_str() << std::endl;\n        }\n        txn.commit();\n    } catch (const std::exception &e) {\n        std::cerr << "Error: " << e.what() << std::endl;\n    }\n}\n\nint main() {\n    std::string input;\n    std::cout << "Enter username: ";\n    std::getline(std::cin, input);\n    safeQuery(input);\n    return 0;\n}
\n\n

Notez bien : nous utilisons txn.exec_params au lieu de la concaténation de chaînes. La base de données échappe elle-même les caractères spéciaux. Même si l'utilisateur saisit ' OR '1'='1, cela sera interprété comme une chaîne de caractères, et non comme une partie de la commande SQL.

\n\n

Que faire si vous utilisez du SQLite brut ?

\n\n

Même avec SQLite, vous pouvez travailler en toute sécurité. Utilisez sqlite3_prepare_v2 et sqlite3_bind_text :

\n\n
#include <sqlite3.h>\n#include <iostream>\n\nvoid safeSQLiteQuery(sqlite3* db, const std::string& username) {\n    sqlite3_stmt* stmt;\n    const char* sql = "SELECT * FROM users WHERE username = ?";\n    \n    if (sqlite3_prepare_v2                

Blogs

Book Recommendations