CREATE OR REPLACE PROCEDURE Disable_Constraint (
P_CONSTRAINT_NAME VARCHAR2,
P_TABLE VARCHAR2
) AUTHID CURRENT_USER AS
P_SCHEMA VARCHAR2(32) := USER;
SQL_STMT VARCHAR2(2000) := 'ALTER TABLE ' || P_SCHEMA || '.' || P_TABLE
|| ' DISABLE CONSTRAINT ' || P_CONSTRAINT_NAME;
BEGIN
EXECUTE IMMEDIATE SQL_STMT;
END;
三大注入點:P_TABLE、P_CONSTRAINT_NAME、P_SCHEMA (USER 可被構造)。
EXECUTE IMMEDIATE ... USING ... (僅適用 DML,不適用 DDL 對象名)| 函數 | 用途 | 適用場景 |
|---|---|---|
| SIMPLE_SQL_NAME | 驗證簡單 SQL 標識符 (無雙引號) | 對象名不含特殊字符 |
| QUALIFIED_SQL_NAME | 驗證帶 Schema 的標識符 | Schema.Object 格式 |
| SCHEMA_NAME | 驗證現有 Schema 名 | 防二次攻擊 (需對象已存在) |
| SQL_OBJECT_NAME | 驗證現有 SQL 對象名 | 同上,含類型檢查 |
| ENQUOTE_NAME | 雙引號包裹標識符,可選大寫轉換 | 通用首選,防注入最強 |
| ENQUOTE_LITERAL | 單引號包裹字面量 | 字符串字面量 |
SIMPLE/QUALIFIED_SQL_NAME:要求輸入含雙引號,但數據字典查出的名稱不帶引號 → **不適用**SCHEMA_NAME/SQL_OBJECT_NAME:要求對象已存在,若攻擊者預先創建惡意對象 → **存在二次注入風險**ENQUOTE_NAME:直接雙引號包裹,若包裹後仍含危險字符則拋異常 → **最通用、最安全**CREATE OR REPLACE PROCEDURE Disable_Constraint (
P_CONSTRAINT_NAME VARCHAR2,
P_TABLE VARCHAR2
) AUTHID CURRENT_USER AS
P_SCHEMA VARCHAR2(32) := SYS.DBMS_ASSERT.ENQUOTE_NAME(USER, FALSE);
SAFE_TABLE VARCHAR2(32);
SAFE_CONSTRAINT VARCHAR2(32);
SQL_STMT VARCHAR2(2000);
BEGIN
SAFE_TABLE := SYS.DBMS_ASSERT.ENQUOTE_NAME(P_TABLE, FALSE);
SAFE_CONSTRAINT := SYS.DBMS_ASSERT.ENQUOTE_NAME(P_CONSTRAINT_NAME, FALSE);
SQL_STMT := 'ALTER TABLE ' || P_SCHEMA || '.' || SAFE_TABLE
|| ' DISABLE CONSTRAINT ' || SAFE_CONSTRAINT;
EXECUTE IMMEDIATE SQL_STMT;
END;
ENQUOTE_NAME(..., FALSE) 保持大小寫敏感,調用方必須傳入精確大小寫對象名EXECUTE IMMEDIATE、DBMS_SQL.PARSE 等動態 SQL 入口