All Products
Search
Document Center

PolarDB:SQL firewalls

Last Updated:Mar 28, 2026

SQL injection attacks are typically the application developer's responsibility to prevent — but developers are not always the ones accountable when a breach happens. Database administrators have limited control over how applications query the database, yet they bear responsibility for protecting the data. SQL/Protect addresses this gap.

SQL/Protect is a plug-in for PolarDB for Oracle that analyzes incoming query requests and detects SQL injection patterns. When it identifies a suspicious query, it either alerts you or blocks the query, depending on how you configure it.

SQL injection attack types

SQL/Protect detects four types of SQL injection attacks:

Attack typeHow it worksWhy it's dangerous
Unauthorized relationsAttacker accesses tables the application was never meant to touchHard to prevent manually; SQL/Protect learns which tables each user legitimately accesses and flags deviations
Utility commandsAttacker runs DDL statements, such as creating a user-defined function to read restricted dataThese commands rarely appear in normal application workloads, making them straightforward to detect
SQL tautologyAttacker injects a WHERE clause that is always true, such as WHERE password = 'x' OR 'x'='x'This is how attackers typically probe for security weaknesses — the first step before deeper exploitation
Unbounded DML statementsAttacker runs UPDATE or DELETE without a WHERE clauseA single statement can modify or delete every row in a table, enabling denial-of-service (DoS) attacks

Modes

The polar_sql_protect.level parameter controls how SQL/Protect responds to suspicious queries. Three modes are available:

ModeBehaviorWhen to use
learnTracks and records which tables each user accesses. Does not alert or block.Initial setup — run this mode first to build a baseline of legitimate behavior
passiveSends an alert for unauthorized SQL statements but still allows them to runTesting and monitoring — use this when you want visibility without risking blocked queries
activeBlocks all unauthorized SQL statements and records themProduction protection — enables SQL firewalls to intercept attacks during penetration tests and real incidents

The default mode is passive.

Protected roles

A protected role is a database user or group that SQL/Protect monitors. Each protected role can have different protection settings — for example, one role might have relation protection enabled while another allows utility commands.

Constraints:

  • A role with superuser privileges cannot be added as a protected role.

  • If a protected non-superuser role is later granted superuser privileges, SQL/Protect generates an alert for every command that role runs. In active mode, all commands are blocked.

  • When SQL/Protect is running, a protected role that has the superuser privilege is changed to a common role or restored to an unprotected role.

  • Each database supports up to 64 protected roles by default (configurable with max_protected_roles) and up to 1,024 protected tables (configurable with max_protected_relations).

Set up SQL/Protect

This section covers enabling SQL/Protect, adding a protected role, and switching between modes.

Prerequisites

Before you begin, ensure that you have:

  • A PolarDB for Oracle cluster

  • Database administrator access

Enable SQL/Protect and create a protected role

  1. Enable SQL/Protect by setting the following parameters:

    SET polar_sql_protect.enabled = on;   -- Default: off
    SET polar_sql_protect.level = passive; -- Default: passive. Valid values: learn, passive, active
  2. Create a test database and user:

    CREATE DATABASE targetdb;
    CREATE ROLE test;
    GRANT ALL ON DATABASE targetdb TO test;
    ALTER ROLE test LOGIN;
  3. Connect to targetdb, install the extension, and add the protected role:

    CREATE EXTENSION sqlprotect;
    SELECT sqlprotect.protect_role('test');
  4. Verify that the role is protected:

    SELECT * FROM sqlprotect.list_protected_users;
    SELECT * FROM sqlprotect.polar_sql_protect;

Use learn mode to build a baseline

Switch to learn mode before your application starts running queries. SQL/Protect records every table the protected role accesses, building a list of authorized relations.

SET polar_sql_protect.level = learn;

Connect to targetdb as the test user and run your application's typical queries:

CREATE TABLE company(name VARCHAR(100), employee_num INT);
SELECT * FROM company;
INSERT INTO company VALUES('new', 1);
SELECT * FROM company;

After running the queries, check what SQL/Protect learned:

SELECT * FROM sqlprotect.polar_sql_protect_rel;
SELECT * FROM sqlprotect.list_protected_rels;

Switch to passive mode

After the baseline is built, switch to passive mode to start detecting suspicious queries without blocking them.

SET polar_sql_protect.level = passive;

Connect as the test user and run test SQL statements:

SELECT * FROM company WHERE 1 = 1;   -- SQL tautology
DELETE FROM company;                  -- Unbounded DML

SQL/Protect sends an alert for each unauthorized statement but allows execution.

Use passive mode to tune your baseline before enabling enforcement.

Switch to active mode

When you are confident in the baseline, switch to active mode. SQL/Protect blocks unauthorized SQL statements instead of only alerting.

SET polar_sql_protect.level = active;

Connect as the test user and run the same test statements:

SELECT * FROM company WHERE 1 = 1;
DELETE FROM company;

SQL/Protect returns a message that indicates unauthorized SQL statements and prevents execution.

Manage protected roles

Protected roles are stored in the sqlprotect.polar_sql_protect table. As a database administrator, you control which users and groups are protected.

Add a protected role:

SELECT sqlprotect.protect_role('userA');

View protected roles and their learned tables:

SELECT * FROM sqlprotect.list_protected_users;
SELECT * FROM sqlprotect.polar_sql_protect;

Remove a protected role:

SELECT sqlprotect.unprotect_role('userA');

Fine-tune protection per role

The sqlprotect.polar_sql_protect table has four boolean columns that control which attack types SQL/Protect enforces for each role:

targetdb=# \d sqlprotect.polar_sql_protect;
        Table "sqlprotect.polar_sql_protect"
      Column       |  Type   | Collation | Nullable | Default
--------------------+---------+-----------+----------+---------
dbid               | oid     |           | not null |
roleid             | oid     |           | not null |
protect_relations  | boolean |           |          |
allow_utility_cmds | boolean |           |          |
allow_tautology    | boolean |           |          |
allow_empty_dml    | boolean |           |          |
Indexes:
   "polar_sql_protect_pkey" PRIMARY KEY, btree (roleid)

For example, if you execute the following statement to set the allow_utility_cmds parameter to TRUE for a protected role named 16480, SQL/Protect blocks the utility commands run by the protected role 16480:

UPDATE sqlprotect.polar_sql_protect
SET allow_utility_cmds = TRUE
WHERE roleid = 16480;

Monitor SQL injection statistics

SQL/Protect records statistics for every suspicious query a protected role runs. These statistics help you identify attack patterns early — before an attacker escalates from probing to exploitation.

View statistics for all protected roles:

SELECT * FROM sqlprotect.polar_sql_protect_stats;

The polar_sql_protect_stats view breaks down counts by attack type (unauthorized relations, utility commands, tautology, unbounded DML), so you can see which vectors are being attempted and against which roles. Reviewing this data regularly lets you respond proactively — for example, by switching to active mode when you see a spike in tautology attempts.

Clear statistics for a specific user:

SELECT sqlprotect.drop_stats('username');

Disable SQL/Protect

To disable SQL/Protect:

polar_sql_protect.enabled = off
polar_sql_protect.level = passive