SQL防火牆是資料庫層面的防火牆功能,可以防止惡意SQL注入。可以用來學習一些定義好的SQL規則,並將這些規則儲存在資料庫中作為白名單,學習完成後,可以限制使用者執行這些定義規則之外的風險操作。
前提條件
RDS PostgreSQL執行個體需為以下版本之一:- PostgreSQL 12
- PostgreSQL 11
- PostgreSQL 10
重要 RDS PostgreSQL已不再支援sql_firewall外掛程式,雖然之前已經建立的外掛程式仍可使用,但是由於使用該外掛程式可能導致系統崩潰,我們建議您儘早停止使用,以避免潛在風險。
如果您想要移除sql_firewall外掛程式,可以使用drop extension sql_firewall;
語句卸載此外掛程式,並在shared_preload_libraries參數中移除它,具體修改參數方法,請參見設定執行個體參數。
學習模式、預警模式與防火牆模式
SQL防火牆支援如下三種模式:
- 學習模式:防火牆記錄使用者執行的SQL,並添加到常用SQL白名單。
- 預警模式:防火牆對使用者將執行的SQL進行判斷,如果SQL不在白名單中,仍然會執行該SQL,但是會警示使用者該SQL不在白名單中。
- 防火牆模式:防火牆對使用者將執行的SQL進行判斷,如果SQL不在白名單中,防火牆會拒絕執行該SQL並返回錯誤提示。
SQL防火牆的使用步驟
- 開啟防火牆的學習模式,讓防火牆記錄使用者執行的SQL,並加入白名單。這個過程建議持續一段較長的時間,盡量讓防火牆學習到所有可能執行的SQL。
- 切換防火牆為預警模式,這個過程防火牆會對使用者的一些不在白名單的SQL進行警示,使用者結合自己的業務判斷是否為風險SQL,如果這些SQL確實是使用者需要的業務語句,則記錄這些SQL,之後開啟學習模式進行二次學習。
- 經過前兩步,使用者常用SQL已經被記錄完畢,開啟防火牆模式,此時不在白名單的SQL均會被拒絕執行。
操作說明
- 建立外掛程式
create extension sql_firewall;
- 刪除外掛程式
drop extension sql_firewall;
- 切換模式
在控制台找到sql_firewall.firewall參數,修改參數值並重啟執行個體。詳情請參見設定執行個體參數。
sql_firewall.firewall取值如下:
- disable:關閉SQL防火牆
- learning:學習模式
- permissive:預警模式
- enforcing:防火牆模式
- 功能函數
- sql_firewall_reset()
清空白名單。該函數只有在防火牆關閉模式下,rds_superuser許可權的使用者可執行該函數。
- sql_firewall_stat_reset()
清空統計資訊。該函數只有在防火牆關閉模式下,rds_superuser許可權的使用者可執行該函數。
- sql_firewall_reset()
- 視圖函數
- sql_firewall.sql_firewall_statements
展示目前資料庫中所有的白名單及其被調用的次數。
postgres=# select * from sql_firewall.sql_firewall_statements; userid | queryid | query | calls --------+------------+---------------------------------+------- 10 | 3294787656 | select * from k1 where uid = ?; | 4 (1 row)
- sql_firewall.sql_firewall_stat
展示預警模式下的警告數量(sql_warning)和防火牆模式下的錯誤數量(sql_error)。
postgres=# select * from sql_firewall.sql_firewall_stat; sql_warning | sql_error -------------+----------- 2 | 1 (1 row)
- sql_firewall.sql_firewall_statements
樣本
--預警模式
postgres=# select * from sql_firewall.sql_firewall_statements;
WARNING: Prohibited SQL statement
userid | queryid | query | calls
--------+------------+---------------------------------+-------
10 | 3294787656 | select * from k1 where uid = 1; | 1
(1 row)
postgres=# select * from k1 where uid = 1;
uid | uname
-----+-------------
1 | Park Gyu-ri
(1 row)
postgres=# select * from k1 where uid = 3;
uid | uname
-----+-----------
3 | Goo Ha-ra
(1 row)
postgres=# select * from k1 where uid = 3 or 1 = 1;
WARNING: Prohibited SQL statement
uid | uname
-----+----------------
1 | Park Gyu-ri
2 | Nicole Jung
3 | Goo Ha-ra
4 | Han Seung-yeon
5 | Kang Ji-young
(5 rows)
--防火牆模式
postgres=# select * from k1 where uid = 3;
uid | uname
-----+-----------
3 | Goo Ha-ra
(1 row)
postgres=# select * from k1 where uid = 3 or 1 = 1;
ERROR: Prohibited SQL statement
postgres=#