首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

C 與 Lua 混合編程實戰:打造高擴展性 MySQL 協議分析與 SQL 注入檢測系統

     編輯:MySQL 資料庫相關知識

專案背景與動機

  • MySQL Proxy 功能強大但需串聯在應用鏈路,風險高、單點故障影響大。
  • 需求:並聯部署(旁路鏡像流量)、單一職責(SQL 審計/注入檢測)、高擴展性(規則熱載入、無需重編譯)。
  • 技術選型:C 語言處理高效能封包捕獲與協議解析,Lua 處理業務邏輯與規則引擎。

系統架構三層設計


┌─────────────────────────────────────┐
│  Layer 3: Lua Script Engine         │  ← 業務規則:SQL 白名單、注入特徵、風險評分
│  - 註冊 C 函數/變數到 Lua 狀態機    │
│  - 熱載入 .lua 腳本,無需重啟主程序  │
└─────────────▲───────────────────────┘
              │ API 呼叫 / 事件回調
┌─────────────┴───────────────────────┐
│  Layer 2: Protocol Parser & Queue   │  ← MySQL 協議解析、Command 識別、SQL 還原
│  - 連結佇列緩衝 Sniffer 原始封包    │
│  - 有限狀態機解析 Handshake/Query   │
│  - 提取:Command Code、SQL 文本、DB名、用戶 │
└─────────────▲───────────────────────┘
              │ 原始封包餵入
┌─────────────┴───────────────────────┐
│  Layer 1: Packet Capture (libpcap)  │  ← 高效能抓包、BPF 過濾 Port 3306
│  - pcap_loop / pcap_dispatch        │
│  - 零拷貝傳遞給解析層               │
└─────────────────────────────────────┘

核心 C 代碼骨架


// 1. 佇列節點
typedef struct pkt_node {
  u_char *data; int len; struct timeval ts;
  struct pkt_node *next;
} pkt_node_t;

// 2. 無鎖環形佇列 (生產者-消費者)
pkt_node_t *ring[RING_SIZE];
volatile int head=0, tail=0;

// 3. Lua 狀態機初始化與註冊
lua_State *L = luaL_newstate();
luaL_openlibs(L);
// 註冊 C 函數供 Lua 調用
lua_pushcfunction(L, l_get_sql_text); lua_setglobal(L, "get_sql");
lua_pushcfunction(L, l_get_command); lua_setglobal(L, "get_cmd");
lua_pushcfunction(L, l_get_user);    lua_setglobal(L, "get_user");
lua_pushcfunction(L, l_get_db);      lua_setglobal(L, "get_db");
// 載入腳本
if (luaL_dofile(L, "rules.lua")) { fprintf(stderr, "%s\n", lua_tostring(L, -1)); }

// 4. 消費者主迴圈
while (running) {
  pkt_node_t *node = dequeue();
  if (!node) { usleep(1000); continue; }
  parse_mysql_packet(node->data, node->len);  // 解析填充全域緩衝
  // 呼叫 Lua 入口函數
  lua_getglobal(L, "on_packet");
  if (lua_pcall(L, 0, 1, 0)) { log_error(lua_tostring(L, -1)); }
  int verdict = lua_tointeger(L, -1); lua_pop(L, 1);
  if (verdict == BLOCK) { send_rst_packet(node); }
  free_node(node);
}

Lua 規則腳本範例


-- rules.lua
local sql_inject_patterns = {
  "union%s+select", "or%s+1=1", "sleep%(%d+%)", "benchmark%(%d+,%d+%)",
  "load_file%(", "into%s+outfile", "information_schema",
  "';--", "';#", "';/*"
}

function on_packet()
  local sql = get_sql()
  local cmd = get_cmd()
  local user = get_user()
  local db = get_db()

  -- 僅分析 COM_QUERY (3) 和 COM_STMT_EXECUTE (23)
  if cmd ~= 3 and cmd ~= 23 then return PASS end

  sql = sql:lower()
  for _, pat in ipairs(sql_inject_patterns) do
    if sql:match(pat) then
      log_alert("SQL_INJECTION", user, db, sql)
      return BLOCK  -- 或 ALERT 僅告警
    end
  end

  -- 白名單機制
  if sql_whitelist[sql] then return PASS end

  return PASS
end

MySQL 協議關鍵點(解析層必知)

階段方向關鍵欄位備註
HandshakeS→CProtocol Version, Server Version, Thread ID, Salt, Capabilities驗證握手、取得鹽值
AuthC→SUsername, Auth-Response (scramble), DB Name明文/加密密碼、預設 DB
QueryC→SCOM_QUERY (0x03) + SQL Text核心分析點,明文傳輸
Stmt PrepareC→SCOM_STMT_PREPARE (0x16) + SQL預處理,參數標記 ?
Stmt ExecuteC→SCOM_STMT_EXECUTE (0x17) + Param Values需還原參數化 SQL
ResultsetS→CColumn Count, Column Defs, Rows, EOF可選擇性解析

安全啟示:MySQL 協議明文本質

  • 除登入認證階段(4.1+ 加密),所有 SQL、結果集、DDL、DML、甚至 ALTER USER 密碼修改均為明文。
  • 公網傳輸 必須 SSL/TLS 或 SSH Tunnel,否則等同裸奔。
  • 旁路鏡像流量分析(如本系統)不影響業務效能,適合合規審計、入侵檢測、資料防洩漏 (DLP)。

擴展性實踐:熱載入與沙箱隔離


// 訊號處理:SIGHUP 觸發腳本重載
void sighup_handler(int sig) { reload_lua_script = 1; }

// 主迴圈檢查
if (reload_lua_script) {
  lua_close(L);
  L = luaL_newstate(); luaL_openlibs(L);
  register_c_functions(L);
  if (luaL_dofile(L, "rules.lua")) log_error(...);
  reload_lua_script = 0;
}

生產環境建議:Lua 沙箱(luaL_sandbox 或自定義環境表)限制腳本權限,防止惡意腳本執行 os.execute、io.open 等危險操作。

C 負責「快」,Lua 負責「靈」。協議解析、封包處理、高併發 IO 在 C 層極致優化;業務規則、風險模型、白名單維護在 Lua 層秒級迭代。這就是「高擴展性」的工程化落地。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved