Seguridad en C++: Protección contra Inyecciones SQL y XSS en 2024

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Cuando C++ se encuentra con la web: por qué la seguridad es su mayor dolor de cabeza

\n\n

¿Alguna vez se ha preguntado por qué los hackers aman tanto las aplicaciones C++? No, no porque el código sea complejo. Sino porque en la búsqueda del rendimiento, los desarrolladores a menudo se olvidan de la seguridad en C++. Y lo pagan con los datos de los usuarios, su reputación y su dinero.

\n\n

Imagínese: escribió un servidor increíble en C++ que procesa solicitudes más rápido que un rayo. Pero una sola entrada sin escapar — y un atacante extrae toda la base de datos. O, peor aún, inserta un script que roba las sesiones de todos los visitantes del sitio. ¿Le suena familiar? Si no — perfecto, significa que está leyendo este artículo a tiempo.

\n\n

En este material, analizaremos los dos ataques más peligrosos a aplicaciones web — inyecciones SQL y Cross-Site Scripting (XSS) — y mostraremos cómo protegerse de ellos específicamente en C++. Sin magia, con ejemplos de código reales. Comencemos.

\n\n

Inyecciones SQL: cómo los hackers convierten su consulta en un arma

\n\n

Una inyección SQL ocurre cuando un atacante inserta en un campo de entrada (por ejemplo, un nombre de usuario o una consulta de búsqueda) un fragmento de código SQL. Si su aplicación inserta ciegamente esta entrada en la consulta, en lugar de buscar un usuario por nombre, la base de datos ejecutará algo como DROP TABLE users. O, peor aún, devolverá todas las contraseñas.

\n\n

El error típico de un principiante (y cómo evitarlo)

\n\n

Mire este código. Parece inofensivo, pero es una bomba de tiempo:

\n\n
// ¡PELIGROSO! Nunca haga esto\nstd::string username = getUserInput(); // el usuario ingresó: ' OR '1'='1\nstd::string query = "SELECT * FROM users WHERE username = '" + username + "'";\n// Resultado: SELECT * FROM users WHERE username = '' OR '1'='1'\n// ¡Devolverá todos los usuarios!
\n\n

¿Ve el problema? Si el usuario ingresa ' OR '1'='1, la consulta devolverá toda la tabla. Y si ingresa '; DROP TABLE users; --, entonces adiós, base de datos.

\n\n

El enfoque correcto: consultas parametrizadas

\n\n

La única forma confiable de protegerse contra inyecciones SQL en C++ es usar consultas parametrizadas. La base de datos misma distingue el código de los datos. Así es como se ve con la biblioteca libpqxx (para PostgreSQL) o MySQL Connector/C++:

\n\n
#include <iostream>\n#include <pqxx/pqxx> // libpqxx para 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        // Consulta parametrizada: $1 es el parámetro\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

Observe: usamos txn.exec_params en lugar de concatenación de cadenas. La base de datos misma escapa los caracteres especiales. Incluso si el usuario ingresa ' OR '1'='1, esto se interpretará como una cadena, no como parte de un comando SQL.

\n\n

¿Qué hacer si usa SQLite puro?

\n\n

Incluso con SQLite se puede trabajar de forma segura. Use sqlite3_prepare_v2 y 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