萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

Linux 下 MySQL 命令列隱藏密碼原理與 C 語言實作:argv 覆寫技術深度解析

問題背景

在 Shell 執行 mysql -u root -pSecret123 時,密碼會出現在:

  • 進程表:ps -ef、ps aux
  • /proc//cmdline
  • Shell 歷史紀錄 ~/.bash_history

MySQL 客戶端啟動後會嘗試用 0 覆寫 argv 密碼段,但存在競態條件,且背景執行時更明顯。

核心原理:覆寫 argv[1] 記憶體區

C 程式啟動時,main(int argc, char *argv[]) 接收命令列參數指針陣列。argv[1] 指向密碼字串在進程記憶體中的位置。直接修改該記憶體區內容,ps 讀取 /proc/PID/cmdline 時即顯示修改後的值。

完整 C 實作(教學用)

/* hide_pass.c - 編譯:gcc -o hide_pass hide_pass.c */
#include 
#include 
#include 
#include 

int main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(stderr, "Usage: %s \n", argv[0]);
        return 1;
    }

    pid_t pid = getpid();
    printf("argc = %d, PID = %d\n", argc, pid);
    for (int i = 0; i < argc; i++) {
        printf("argv[%d] = %s\n", i, argv[i]);
    }

    printf("覆寫 argv[1] 中... 在另一終端執行: ps -p %d -o cmd\n", pid);
    fflush(stdout);

    /* 關鍵:用 'x' 覆蓋密碼每個字元 */
    memset(argv[1], 'x', strlen(argv[1]));

    /* 保持進程存活以便觀察 */
    getchar(); 

    return 0;
}

測試步驟

# 終端 1:編譯執行
$ gcc -o hide_pass hide_pass.c
$ ./hide_pass MySecretPassword123
argc = 2, PID = 12345
argv[0] = ./hide_pass
argv[1] = MySecretPassword123
覆寫 argv[1] 中... 在另一終端執行: ps -p 12345 -o cmd

# 終端 2:觀察
$ ps -p 12345 -o cmd
CMD
./hide_pass xxxxxxxxxxxxxxxx  # 密碼已被 x 覆蓋

MySQL 客戶端實際做法

原始碼 client/mysql.cc 中 init_common_variables():

/* 簡化版邏輯 */
for (int i = 1; i < argc; i++) {
    if (strcmp(argv[i], "-p") == 0 || strncmp(argv[i], "-p", 2) == 0) {
        char *pass = (argv[i][2] ? &argv[i][2] : argv[++i]);
        /* 立即複製密碼到內部緩衝區 */
        strncpy(internal_password_buffer, pass, sizeof(internal_password_buffer)-1);
        /* 覆寫 argv 記憶體 */
        memset(pass, 'x', strlen(pass));
        break;
    }
}

局限性與現代替代方案

方案原理優點缺點
argv 覆寫修改進程參數記憶體無依賴、通用競態窗口、不支援所有 Unix、無法隱藏環境變數
setproctitle()BSD/System V 系統調用修改進程標題標準化、可設定任意標題非 POSIX 標準、Linux 需 prctl
PR_SET_MM_ARG_STARTLinux prctl 修改參數區域Linux 專用、精確控制需 CAP_SYS_RESOURCE、複雜
配置檔 .my.cnf從檔案讀取密碼,不經命令列最安全、生產標準需檔案權限管控
Docker/K8s Secrets容器編排層注入密碼不落盤、RBAC 控制、輪換友好需容器環境

安全建議總結

  1. 生產環境嚴禁命令列傳密碼,統一使用 --defaults-extra-file 指向 600 權限配置檔
  2. 容器環境使用 Secrets 掛載
  3. 自行開發工具時,參考 argv 覆寫技術,但優先避免密碼進入 argv
  4. 定期稽核 ps、/proc、Shell 歷史,確保無洩露

結語

argv 覆寫是 C 語言底層記憶體操作的經典教學案例,展示了進程參數在記憶體中的佈局。但在現代基礎設施下,**「不讓密碼進入命令列」才是正解**,而非「命令列裡藏著密碼再想辦法藏起來」。

copyright © 萬盛學電腦網 all rights reserved