在命令行直接傳遞密碼(如 mysql -p123456)會導致密碼在進程列表(ps -ef)中明文可見,構成嚴重安全風險。本文深度解析 MySQL 官方採用的 argv 重寫技術,並提供完整 C 語言演示代碼。
C 程式啟動時,命令行參數存儲在 argv 字符串數組中,佔用進程用戶空間內存。利用 memset() 將密碼參數對應的內存區塊覆蓋為 x(或任意字符),即可使 ps 讀取到的命令行參數變為掩碼形式,而不影響程式邏輯對原密碼的使用(因密碼通常在覆蓋前已拷貝至私有緩衝區)。
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
int main(int argc, char *argv[]) {
int i = 0;
pid_t mypid = getpid();
if (argc == 1) return 1; // 缺少參數異常退出
printf("argc = %d and arguments are:\n", argc);
for (i = 0; i < argc; i++)
printf("%d = %s\n", i, argv[i]);
printf("Replacing first argument with x... Now run: ps p %d\n", (int)mypid);
fflush(stdout);
// 關鍵:用 'x' 覆蓋 argv[1](密碼參數)
memset(argv[1], 'x', strlen(argv[1]));
getc(stdin); // 阻塞進程,便於另開終端觀察 ps 輸出
return 0;
}
# 切換普通用戶模擬真實場景 su dabu cd ~ # 編譯 gcc -o hide pwhide.c # 運行,傳入模擬密碼 ./hide "my_secret_pwd" # 輸出示例: # argc = 2 and arguments are: # 0 = ./hide # 1 = my_secret_pwd # Replacing first argument with x... Now run: ps p 15585
此時程式阻塞於 getc(stdin),另開終端以 root 執行:
ps p 15585 # 輸出: # PID TTY STAT TIME COMMAND # 15585 pts/0 S+ 0:00 ./hide xxxxxxxxxxxxx # 13 個 x 對應密碼長度
mysql_config_editor 將憑證加密存儲於 .mylogin.cnf,登錄時自動讀取,命令行無密碼export MYSQL_PWD='pwd'(注意:ps e 仍可見,較 argv 略優)--defaults-file=/path/.cnf 指定包含 [client] password=... 的配置文件,權限設為 600mysql -u root -p,回車後提示輸入,進程列表無密碼setproctitle() 系統調用直接修改進程標題prctl(PR_SET_MM, PR_SET_MM_ARG_START, ...) 可更精確控制參數顯示掌握 argv 重寫原理,不僅能理解 MySQL 密碼隱藏機制,更能在開發敏感信息處理程式時,從源頭消除命令行洩露風險。