記錄一個利用資料庫引擎格式化異常sql的思路

国产大熊猫~發表於2024-03-08

這個思路主要解決MySQL 中的科學記數法漏洞使 AWS WAF 客戶端易受 SQL 注入攻擊這篇文章中的問題

目前基本上都使用阿里巴巴的druid並開啟sql防火牆模式以語義層面攔截sql注入,如果極端情況下對sql解析結果不一致還是會產生sql注入

於是嘗試了一下mysql自帶的功能

1)EXPLAIN

2)optimizer_trace

SET optimizer_trace = "enabled=on"; 
EXPLAIN
SELECT GROUP_CONCAT(TABLE_NAME) FROM information_schema.tables WHERE table_schema = DATABASE();
SELECT TRACE
FROM information_schema.OPTIMIZER_TRACE;
SET optimizer_trace = "enabled=off";

EXPLAIN保證sql不會對資料庫造成汙染

optimizer_trace主要保證獲取sql在資料庫中的實際內容

在information_schema的OPTIMIZER_TRACE中

QUERY是執行的sql而TRACE是sql引擎跟蹤後的內容使用json表達

注意,內容非常的長啊!所以我們只擷取我們比較關心的部分

"expanded_query": "/* select#1 */ select group_concat((`mysql`.`tbl`.`name` collate utf8mb3_tolower_ci) separator ',') AS `GROUP_CONCAT(TABLE_NAME)` from <constant table> join ((((((`mysql`.`tables` `tbl` join `mysql`.`schemata` `sch` on((`mysql`.`tbl`.`schema_id` = `mysql`.`sch`.`id`))) join `mysql`.`catalogs` `cat` on((`mysql`.`cat`.`id` = `mysql`.`sch`.`catalog_id`))) left join `mysql`.`collations` `col` on((`mysql`.`tbl`.`collation_id` = `mysql`.`col`.`id`))) left join `mysql`.`tablespaces` `ts` on((`mysql`.`tbl`.`tablespace_id` = `mysql`.`ts`.`id`))) left join `mysql`.`table_stats` `stat` on(((`mysql`.`tbl`.`name` = `mysql`.`stat`.`table_name`) and (`mysql`.`sch`.`name` = `mysql`.`stat`.`schema_name`))))) on(((0 <> can_access_table(`mysql`.`sch`.`name`,`mysql`.`tbl`.`name`)) and (0 <> is_visible_dd_object(`mysql`.`tbl`.`hidden`)))) where ((`mysql`.`sch`.`name` collate utf8mb3_tolower_ci) = database())"

這個思路的好處是:

1)避免sql中介軟體解析sql和實際資料庫產生差異

2)可以充分避免註釋、bug、花式技巧導致的sql注入bypass,因為optimizer_trace追蹤後的輸出都是統一格式化後的sql

例如,1e1的解析:

EXPLAIN
SELECT GROUP_CONCAT(TABLE_NAME),1e1FROM/* 
*/ information_schema.tables WHERE table_schema = DATABASE()
#解析為
"expanded_query": "/* select#1 */ select group_concat((`mysql`.`tbl`.`name` collate utf8mb3_tolower_ci) separator ',') AS `GROUP_CONCAT(TABLE_NAME)`,1e1 AS `1e1` from <constant table> join

相關文章