From 7526e80a0fd14a06c0c7919031b0053f3591e93c Mon Sep 17 00:00:00 2001 From: trogers1884 Date: Tue, 3 Jun 2025 18:30:15 -0500 Subject: [PATCH] Fix c77_secure_db_test_security --- .idea/.gitignore | 8 ++ .idea/c77_secure_db.iml | 8 ++ .idea/modules.xml | 8 ++ .idea/php.xml | 19 +++ .idea/vcs.xml | 6 + c77_secure_db--1.0.sql | 278 +++++++++++++++++++++++++++++++++++++--- 6 files changed, 308 insertions(+), 19 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/c77_secure_db.iml create mode 100644 .idea/modules.xml create mode 100644 .idea/php.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/c77_secure_db.iml b/.idea/c77_secure_db.iml new file mode 100644 index 0000000..c956989 --- /dev/null +++ b/.idea/c77_secure_db.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..8ca82bd --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/php.xml b/.idea/php.xml new file mode 100644 index 0000000..f324872 --- /dev/null +++ b/.idea/php.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/c77_secure_db--1.0.sql b/c77_secure_db--1.0.sql index 61035a2..0d46683 100644 --- a/c77_secure_db--1.0.sql +++ b/c77_secure_db--1.0.sql @@ -1468,29 +1468,266 @@ v_test_results := v_test_results || jsonb_build_object( END; -- TEST 5: Test token expiration (simulate expired token) +-- Comprehensive security test suite +CREATE OR REPLACE FUNCTION c77_secure_db_test_security() + RETURNS JSONB + LANGUAGE plpgsql AS $$ +DECLARE + v_test_results JSONB := '{}'; + v_tests_passed INTEGER := 0; + v_tests_failed INTEGER := 0; + v_test_schema TEXT := 'c77_test_' || extract(epoch from now())::bigint; + v_operation_result JSONB; BEGIN --- This test verifies that expired tokens don't work -PERFORM set_config('c77_secure_db.auth_token', gen_random_uuid()::text, true); -EXECUTE format('INSERT INTO %I.test_secure_table (name) VALUES (''token_test'')', v_test_schema); + -- Create test environment + EXECUTE format('CREATE SCHEMA %I', v_test_schema); -v_tests_failed := v_tests_failed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'token_expiration', jsonb_build_object( - 'status', 'FAILED', - 'message', 'Invalid token was accepted - SECURITY FLAW!' - ) - ); -EXCEPTION WHEN insufficient_privilege THEN + -- Create test table + EXECUTE format(' + CREATE TABLE %I.test_secure_table ( + id BIGSERIAL PRIMARY KEY, + name TEXT NOT NULL, + description TEXT, + content_hash TEXT, + hash_version INTEGER DEFAULT 1, + created_at TIMESTAMPTZ DEFAULT NOW(), + updated_at TIMESTAMPTZ DEFAULT NOW(), + deleted_at TIMESTAMPTZ + )', v_test_schema); + + -- Register schema as secure + PERFORM c77_secure_db_manage_secure_schemas('add', v_test_schema); + + -- TEST 1: Verify direct INSERT is blocked + BEGIN + EXECUTE format('INSERT INTO %I.test_secure_table (name) VALUES (''bypass_test'')', v_test_schema); + + v_tests_failed := v_tests_failed + 1; + v_test_results := v_test_results || jsonb_build_object( + 'direct_insert_blocked', jsonb_build_object( + 'status', 'FAILED', + 'message', 'Direct INSERT was allowed - CRITICAL SECURITY FLAW!' + ) + ); + EXCEPTION WHEN insufficient_privilege THEN v_tests_passed := v_tests_passed + 1; -v_test_results := v_test_results || jsonb_build_object( - 'token_expiration', jsonb_build_object( - 'status', 'PASSED', - 'message', 'Invalid token correctly rejected' - ) - ); -FINALLY -PERFORM set_config('c77_secure_db.auth_token', '', true); + v_test_results := v_test_results || jsonb_build_object( + 'direct_insert_blocked', jsonb_build_object( + 'status', 'PASSED', + 'message', 'Direct INSERT correctly blocked' + ) + ); + END; + + -- TEST 2: Verify direct UPDATE is blocked + BEGIN + EXECUTE format('UPDATE %I.test_secure_table SET name = ''hacked'' WHERE id = 1', v_test_schema); + + v_tests_failed := v_tests_failed + 1; + v_test_results := v_test_results || jsonb_build_object( + 'direct_update_blocked', jsonb_build_object( + 'status', 'FAILED', + 'message', 'Direct UPDATE was allowed - CRITICAL SECURITY FLAW!' + ) + ); + EXCEPTION WHEN insufficient_privilege THEN + v_tests_passed := v_tests_passed + 1; + v_test_results := v_test_results || jsonb_build_object( + 'direct_update_blocked', jsonb_build_object( + 'status', 'PASSED', + 'message', 'Direct UPDATE correctly blocked' + ) + ); + END; + + -- TEST 3: Verify direct DELETE is blocked + BEGIN + EXECUTE format('DELETE FROM %I.test_secure_table WHERE id = 1', v_test_schema); + + v_tests_failed := v_tests_failed + 1; + v_test_results := v_test_results || jsonb_build_object( + 'direct_delete_blocked', jsonb_build_object( + 'status', 'FAILED', + 'message', 'Direct DELETE was allowed - CRITICAL SECURITY FLAW!' + ) + ); + EXCEPTION WHEN insufficient_privilege THEN + v_tests_passed := v_tests_passed + 1; + v_test_results := v_test_results || jsonb_build_object( + 'direct_delete_blocked', jsonb_build_object( + 'status', 'PASSED', + 'message', 'Direct DELETE correctly blocked' + ) + ); + END; + + -- TEST 4: Verify legitimate secure operation works + BEGIN + SELECT c77_secure_db_operation(jsonb_build_object( + 'schema_name', v_test_schema, + 'table_name', 'test_secure_table', + 'operation', 'insert', + 'data', jsonb_build_object('name', 'legitimate_test', 'description', 'This should work') + )) INTO v_operation_result; + + IF (v_operation_result->>'success')::boolean THEN + v_tests_passed := v_tests_passed + 1; + v_test_results := v_test_results || jsonb_build_object( + 'legitimate_operation', jsonb_build_object( + 'status', 'PASSED', + 'message', 'Secure operation succeeded', + 'operation_id', v_operation_result->>'operation_id' + ) + ); + ELSE + v_tests_failed := v_tests_failed + 1; + v_test_results := v_test_results || jsonb_build_object( + 'legitimate_operation', jsonb_build_object( + 'status', 'FAILED', + 'message', 'Secure operation failed: ' || (v_operation_result->>'error') + ) + ); + END IF; + EXCEPTION WHEN OTHERS THEN + v_tests_failed := v_tests_failed + 1; + v_test_results := v_test_results || jsonb_build_object( + 'legitimate_operation', jsonb_build_object( + 'status', 'ERROR', + 'message', SQLERRM + ) + ); + END; + + -- TEST 5: Test token expiration (simulate expired token) + BEGIN + -- This test verifies that expired tokens don't work + PERFORM set_config('c77_secure_db.auth_token', gen_random_uuid()::text, true); + EXECUTE format('INSERT INTO %I.test_secure_table (name) VALUES (''token_test'')', v_test_schema); + + v_tests_failed := v_tests_failed + 1; + v_test_results := v_test_results || jsonb_build_object( + 'token_expiration', jsonb_build_object( + 'status', 'FAILED', + 'message', 'Invalid token was accepted - SECURITY FLAW!' + ) + ); + EXCEPTION WHEN insufficient_privilege THEN + v_tests_passed := v_tests_passed + 1; + v_test_results := v_test_results || jsonb_build_object( + 'token_expiration', jsonb_build_object( + 'status', 'PASSED', + 'message', 'Invalid token correctly rejected' + ) + ); + WHEN OTHERS THEN + v_tests_failed := v_tests_failed + 1; + v_test_results := v_test_results || jsonb_build_object( + 'token_expiration', jsonb_build_object( + 'status', 'ERROR', + 'message', SQLERRM + ) + ); + END; + + -- Clean up token after TEST 5 + PERFORM set_config('c77_secure_db.auth_token', '', true); + + -- TEST 6: Test hash calculation and verification + BEGIN + -- Insert a record and verify its hash + SELECT c77_secure_db_operation(jsonb_build_object( + 'schema_name', v_test_schema, + 'table_name', 'test_secure_table', + 'operation', 'insert', + 'data', jsonb_build_object('name', 'hash_test', 'description', 'Test hash calculation') + )) INTO v_operation_result; + + IF (v_operation_result->>'success')::boolean AND (v_operation_result->>'content_hash') IS NOT NULL THEN + -- Now verify the hash + DECLARE + v_freshness_result JSONB; + v_record_data JSONB; + BEGIN + -- Get the inserted record data (simulated) + v_record_data := jsonb_build_object( + 'id', 1, -- Assuming first record + 'name', 'hash_test', + 'description', 'Test hash calculation' + ); + + v_freshness_result := c77_secure_db_check_freshness(v_test_schema, 'test_secure_table', v_record_data); + + IF (v_freshness_result->>'success')::boolean AND (v_freshness_result->>'fresh')::boolean THEN + v_tests_passed := v_tests_passed + 1; + v_test_results := v_test_results || jsonb_build_object( + 'hash_verification', jsonb_build_object( + 'status', 'PASSED', + 'message', 'Hash calculation and verification working correctly' + ) + ); + ELSE + v_tests_failed := v_tests_failed + 1; + v_test_results := v_test_results || jsonb_build_object( + 'hash_verification', jsonb_build_object( + 'status', 'FAILED', + 'message', 'Hash verification failed: ' || (v_freshness_result->>'error') + ) + ); + END IF; + END; + ELSE + v_tests_failed := v_tests_failed + 1; + v_test_results := v_test_results || jsonb_build_object( + 'hash_verification', jsonb_build_object( + 'status', 'FAILED', + 'message', 'Hash was not calculated during insert' + ) + ); + END IF; + EXCEPTION WHEN OTHERS THEN + v_tests_failed := v_tests_failed + 1; + v_test_results := v_test_results || jsonb_build_object( + 'hash_verification', jsonb_build_object( + 'status', 'ERROR', + 'message', SQLERRM + ) + ); + END; + + -- Cleanup test environment + BEGIN + PERFORM c77_secure_db_manage_secure_schemas('remove', v_test_schema); + EXECUTE format('DROP SCHEMA %I CASCADE', v_test_schema); + EXCEPTION WHEN OTHERS THEN + -- Log cleanup failure but don't fail the test + v_test_results := v_test_results || jsonb_build_object( + 'cleanup_warning', 'Failed to cleanup test schema: ' || SQLERRM + ); + END; + + RETURN jsonb_build_object( + 'test_suite', 'c77_secure_db_security', + 'version', '2.0', + 'summary', jsonb_build_object( + 'tests_passed', v_tests_passed, + 'tests_failed', v_tests_failed, + 'total_tests', v_tests_passed + v_tests_failed, + 'success_rate', CASE + WHEN (v_tests_passed + v_tests_failed) > 0 THEN + round((v_tests_passed::numeric / (v_tests_passed + v_tests_failed) * 100), 2) + ELSE 0 + END + ), + 'overall_status', CASE + WHEN v_tests_failed = 0 THEN 'ALL_TESTS_PASSED' + ELSE 'SECURITY_ISSUES_DETECTED' + END, + 'test_results', v_test_results, + 'test_schema_used', v_test_schema, + 'timestamp', now() + ); END; +$$; -- TEST 6: Test hash calculation and verification BEGIN @@ -1589,6 +1826,9 @@ RETURN jsonb_build_object( END; $$; + + + -- Test RBAC integration CREATE OR REPLACE FUNCTION c77_secure_db_test_rbac_integration() RETURNS JSONB