14#include <gtest/gtest.h>
33 std::unique_ptr<sqlite_backend>
db_;
36 db_ = std::make_unique<sqlite_backend>();
42 " id INTEGER PRIMARY KEY,"
48 auto r1 =
db_->execute_query(
49 "INSERT INTO users (id, name, email, password_hash) "
50 "VALUES (1, 'Alice', 'alice@test.com', 'hash123')"
53 auto r2 =
db_->execute_query(
54 "INSERT INTO users (id, name, email, password_hash) "
55 "VALUES (2, 'Bob', 'bob@test.com', 'hash456')"
59 GTEST_SKIP() <<
"SQLite not available";
64 if (
db_ &&
db_->is_initialized()) {
83 std::string malicious_input =
"' OR '1'='1";
89 .
where(
"name",
"=", malicious_input)
92 auto query_result = db_->select_query(query);
96 if (query_result.is_ok()) {
97 EXPECT_LE(query_result.value().size(), 1u)
98 <<
"Possible SQL injection vulnerability: query returned multiple rows";
101 GTEST_SKIP() <<
"SQLite not available";
114 std::string malicious_input =
"admin'--";
120 .
where(
"name",
"=", malicious_input)
123 auto query_result = db_->select_query(query);
126 if (query_result.is_ok()) {
127 EXPECT_EQ(query_result.value().size(), 0u);
130 GTEST_SKIP() <<
"SQLite not available";
143 std::string malicious_input =
"'; DROP TABLE users; --";
149 .
where(
"name",
"=", malicious_input)
153 db_->select_query(query);
156 auto check = db_->select_query(
"SELECT COUNT(*) as cnt FROM users");
157 EXPECT_TRUE(check.is_ok() && !check.value().empty())
158 <<
"CRITICAL: Table appears to have been dropped!";
160 GTEST_SKIP() <<
"SQLite not available";
179 "CREATE TABLE sensitive_data (secret TEXT)"
182 "INSERT INTO sensitive_data VALUES ('top_secret_value')"
185 std::string malicious_input =
"' UNION SELECT secret, secret, secret, secret FROM sensitive_data --";
191 .
where(
"name",
"=", malicious_input)
194 auto query_result = db_->select_query(query);
197 bool found_secret =
false;
198 if (query_result.is_ok()) {
199 for (
const auto& row : query_result.value()) {
200 for (
const auto& [key, value] : row) {
201 if (std::holds_alternative<std::string>(value)) {
202 if (std::get<std::string>(value).find(
"top_secret") != std::string::npos) {
209 EXPECT_FALSE(found_secret)
210 <<
"CRITICAL: Sensitive data leaked through UNION injection!";
212 GTEST_SKIP() <<
"SQLite not available";
230 auto insert_result = db_->execute_query(
231 "INSERT INTO users (id, name, email, password_hash) "
232 "VALUES (3, 'O''Brien', 'obrien@test.com', 'hash789')"
242 .
where(
"name",
"=", safe_value)
247 bool properly_escaped =
248 (query.find(
"O''Brien") != std::string::npos) ||
249 (query.find(
"O\\'Brien") != std::string::npos) ||
250 (query.find(
"O'Brien") != std::string::npos);
252 EXPECT_TRUE(properly_escaped)
253 <<
"Query should handle apostrophe safely. Built query: " << query;
255 GTEST_SKIP() <<
"SQLite not available";
265 std::vector<std::string> special_inputs = {
275 for (
const auto& input : special_inputs) {
280 .
where(
"name",
"=", input)
284 EXPECT_FALSE(query.empty())
285 <<
"Failed to build query with special input: " << input;
289 db_->select_query(query);
290 }) <<
"Query execution failed with special input: " << input;
293 GTEST_SKIP() <<
"SQLite not available";
314 .
where(
"id",
"=", numeric_value)
318 EXPECT_TRUE(query.find(
"id = 1") != std::string::npos ||
319 query.find(
"[id] = 1") != std::string::npos)
320 <<
"Numeric value should not be quoted. Query: " << query;
322 GTEST_SKIP() <<
"SQLite not available";
338 .
where(
"id",
">", bool_value)
342 EXPECT_TRUE(query.find(
"TRUE") != std::string::npos ||
343 query.find(
"1") != std::string::npos)
344 <<
"Boolean value handling issue. Query: " << query;
346 GTEST_SKIP() <<
"SQLite not available";
360 std::vector<core::database_value> params = {std::string(
"Alice")};
361 auto result = db_->select_prepared(
362 "SELECT * FROM users WHERE name = ?", params);
367 const auto& row = result.value()[0];
368 auto it = row.find(
"email");
369 ASSERT_NE(it, row.end());
370 EXPECT_EQ(std::get<std::string>(it->second),
"alice@test.com");
372 GTEST_SKIP() <<
"SQLite not available";
382 std::string malicious =
"' OR '1'='1";
383 std::vector<core::database_value> params = {malicious};
384 auto result = db_->select_prepared(
385 "SELECT * FROM users WHERE name = ?", params);
388 EXPECT_EQ(result.value().size(), 0u)
389 <<
"Prepared statement should treat malicious input as literal string";
391 GTEST_SKIP() <<
"SQLite not available";
401 std::vector<core::database_value> params = {
403 std::string(
"Charlie"),
404 std::string(
"charlie@test.com"),
405 std::string(
"hash_prep")
407 auto exec_result = db_->execute_prepared(
408 "INSERT INTO users (id, name, email, password_hash) VALUES (?, ?, ?, ?)",
413 std::vector<core::database_value> select_params = {int64_t(10)};
414 auto select_result = db_->select_prepared(
415 "SELECT name FROM users WHERE id = ?", select_params);
417 ASSERT_EQ(select_result.value().size(), 1u);
418 EXPECT_EQ(std::get<std::string>(select_result.value()[0].at(
"name")),
"Charlie");
420 GTEST_SKIP() <<
"SQLite not available";
430 std::string malicious =
"'; DROP TABLE users; --";
431 std::vector<core::database_value> params = {malicious};
432 db_->select_prepared(
"SELECT * FROM users WHERE name = ?", params);
435 auto check = db_->select_query(
"SELECT COUNT(*) as cnt FROM users");
437 EXPECT_FALSE(check.value().empty())
438 <<
"CRITICAL: Table dropped via prepared statement injection!";
440 GTEST_SKIP() <<
"SQLite not available";
450 std::vector<core::database_value> params = {
nullptr};
451 auto result = db_->select_prepared(
452 "SELECT * FROM users WHERE name = ?", params);
455 EXPECT_EQ(result.value().size(), 0u)
456 <<
"NULL comparison should match no rows (NULL != NULL in SQL)";
458 GTEST_SKIP() <<
"SQLite not available";
477 .
where(
"email",
"=", std::string(
"admin@secret.com"));
487 EXPECT_TRUE(query.find(
"admin@secret") == std::string::npos)
488 <<
"Previous query data leaked after reset! Query: " << query;
489 EXPECT_TRUE(query.find(
"users") == std::string::npos)
490 <<
"Previous table leaked after reset! Query: " << query;
504 std::vector<std::string> unicode_attacks = {
510 for (
const auto& attack : unicode_attacks) {
515 .
where(
"name",
"=", attack)
520 db_->select_query(query);
521 }) <<
"Query failed with unicode attack: [binary data]";
524 GTEST_SKIP() <<
"SQLite not available";
Test fixture for SQL injection prevention tests.
std::unique_ptr< sqlite_backend > db_
Universal query builder that adapts to different database types.
query_builder & select(const std::vector< std::string > &columns)
std::string build() const
query_builder & where(const std::string &field, const std::string &op, const core::database_value &value)
Abstract interface for database backends.
std::variant< std::string, int64_t, double, bool, std::nullptr_t > database_value
TEST_F(SQLInjectionTest, BasicInjectionAttempt)
Tests that basic OR injection is properly escaped.
SQLite database backend plugin implementation.
Configuration for database connection.
#define ASSERT_EQ(expected, actual, message)
#define ASSERT_TRUE(condition, message)