:從配置文件到內(nèi)存的密碼搜索指南)
1. 從一次真實的內(nèi)部安全演練說起上個月我們團隊進行了一次內(nèi)部紅藍對抗演練。我作為藍隊成員負責防守幾臺關(guān)鍵的Linux應(yīng)用服務(wù)器。演練開始沒多久監(jiān)控告警就響了——有一臺測試機的SSH登錄日志出現(xiàn)了異常。我立刻登錄上去排查在/var/log/auth.log里看到了大量來自內(nèi)網(wǎng)未知IP的失敗嘗試。這顯然是紅隊在嘗試橫向移動。我當時的第一個念頭不是去封IP而是立刻檢查這臺服務(wù)器上有沒有“遺留”的敏感文件。因為經(jīng)驗告訴我攻擊者一旦通過某種方式比如利用一個脆弱的Web應(yīng)用拿到了一個低權(quán)限的shell他們的首要目標絕不是立刻提權(quán)而是翻箱倒柜尋找能讓他們通往其他系統(tǒng)的“鑰匙”——也就是各種配置文件、腳本、備份文件里明文存儲的賬號密碼。果然我在一個用于部署的deploy.sh腳本里發(fā)現(xiàn)了硬編碼的數(shù)據(jù)庫密碼在一個~/.bash_history文件里看到了帶-p參數(shù)的mysql命令記錄甚至在一個臨時日志文件里找到了某次調(diào)試時打印出的完整連接字符串。如果紅隊成員先我一步找到這些他們就能輕松登錄數(shù)據(jù)庫竊取數(shù)據(jù)甚至以此為跳板攻擊網(wǎng)絡(luò)中的其他機器。這次經(jīng)歷再次印證了一個老生常談卻又極易忽視的真理在Linux系統(tǒng)上敏感信息的泄露往往不是由于高深的技術(shù)漏洞而是源于運維中的不良習慣和疏忽。無論是內(nèi)網(wǎng)滲透測試中的攻擊方還是日常運維中的防守方掌握一套系統(tǒng)性的敏感文件查找方法都至關(guān)重要。對于安全研究人員和運維工程師而言在Linux環(huán)境下定位潛在的賬號密碼泄露點是一項基礎(chǔ)且核心的技能。這不僅僅是“找密碼”更是理解應(yīng)用程序行為、梳理配置脈絡(luò)、進行安全審計的過程。本文將從實戰(zhàn)角度出發(fā)拋開那些華而不實的自動化工具依賴深入講解如何基于Linux系統(tǒng)本身的特點用手工結(jié)合命令的方式高效、精準地完成這項任務(wù)。我們會從常見存儲位置、針對性搜索命令、歷史痕跡分析、到內(nèi)存與進程中的密碼抓取形成一個完整的排查鏈路。無論你是想加固自己的服務(wù)器還是在授權(quán)范圍內(nèi)進行安全評估這些方法都能提供直接的幫助。2. 理解敏感信息的常見藏身之處在開始“翻找”之前我們必須先知道去哪里找。Linux系統(tǒng)中的密碼和密鑰并不會像Windows的LSA Secrets那樣有一個統(tǒng)一的保險庫。它們往往分散在以下幾個地方其存在通常都有合理的業(yè)務(wù)原因但也因此成為安全隱患。2.1 配置文件密碼的重災(zāi)區(qū)這是最直接、最普遍的存儲位置。許多應(yīng)用程序為了自動化運行會將連接憑證寫入配置文件。用戶級配置在用戶家目錄下以點號.開頭的隱藏文件是首要目標。例如~/.ssh/包含id_rsa私鑰、known_hosts曾連接過的主機密鑰有時甚至會有config文件里明文寫有連接密碼雖然不推薦。~/.aws/credentials和config文件可能包含AWS的訪問密鑰和密鑰。~/.docker/config.json可能包含容器倉庫的登錄憑證。~/.git-credentialsGit的憑據(jù)緩存文件。~/.bashrc,~/.bash_profile,~/.zshrc等這些shell初始化文件里有時會為了方便而直接導出環(huán)境變量如export DB_PASSWORD123456這是極其危險的做法。~/.mysql_history,~/.psql_history等數(shù)據(jù)庫客戶端的命令歷史如果執(zhí)行過帶密碼的連接命令就會被記錄在此。系統(tǒng)級與應(yīng)用級配置位于/etc目錄下或應(yīng)用安裝目錄中。/etc目錄這是核心區(qū)域。像/etc/passwd和/etc/shadow需root權(quán)限存儲著系統(tǒng)用戶哈希但我們的目標更多是應(yīng)用配置。例如/etc/mysql/my.cnf或/etc/mysql/debian.cnf中可能有數(shù)據(jù)庫密碼舊的FTP服務(wù)器配置/etc/vsftpd.confWeb應(yīng)用的配置文件如/etc/apache2/sites-available/下的某些conf文件可能包含數(shù)據(jù)庫連接信息。應(yīng)用目錄例如一個Web應(yīng)用根目錄下的config.php、application.yml、.env文件。特別是.env文件在框架如Laravel、Django中常用它本意是隔離環(huán)境變量但若權(quán)限設(shè)置不當或誤提交到代碼庫就會導致密碼泄露。查找命令如find /var/www -name *.env -o -name *config*.php -o -name application*.yml 2/dev/null。注意直接搜索/etc下的所有文件包含“password”字符串可能會返回大量結(jié)果其中很多是注釋或示例。更有效的方法是結(jié)合對服務(wù)如mysql,postgresql,redis的了解定位其標準配置文件路徑。2.2 腳本文件自動化背后的隱患Shell腳本、Python腳本、SQL腳本等是自動化運維的利器也常常是密碼的“陳列館”。為了在腳本中直接連接數(shù)據(jù)庫、調(diào)用API或遠程執(zhí)行命令開發(fā)者常常圖省事將密碼以明文形式寫在腳本里。部署腳本(deploy.sh,update.sh)可能包含SCP、SSH、Ansible或數(shù)據(jù)庫的明文密碼。備份腳本(backup.sh)為了自動備份數(shù)據(jù)庫到遠程常出現(xiàn)mysqldump -u root -ppassword這樣的命令。定時任務(wù)腳本(cron job)在/etc/cron.*/目錄下或用戶crontab -l列出的任務(wù)中調(diào)用的腳本需要仔細檢查。查找技巧使用grep時不要只搜索password還要搜索pwd、pass、secret、key、token等常見變量名并且使用-r進行遞歸-i進行忽略大小寫。例如grep -r -i pass\|pwd\|secret /opt/scripts/ 2/dev/null。2.3 日志文件被遺忘的泄露現(xiàn)場日志的本意是記錄但常常記錄了不該記錄的東西。應(yīng)用程序在調(diào)試或報錯時可能會將完整的連接字符串、請求參數(shù)包括密碼打印到日志中。Web服務(wù)器日志/var/log/apache2/access.log或/var/log/nginx/access.log中如果采用GET方式傳遞密碼極其錯誤會在URL中明文顯示。錯誤日志(error.log)中也可能包含配置信息或堆棧跟蹤里的敏感數(shù)據(jù)。應(yīng)用日志在/var/log/下或應(yīng)用自定義目錄中如/var/log/tomcat/、/home/app/logs/。查找最近修改過的、較大的日志文件。命令歷史之前提到的.bash_history是最典型的例子。但要注意如果用戶設(shè)置了HISTCONTROLignorespace并在命令前加空格該命令就不會被記錄。此外還可以檢查~/.sh_history,~/.zsh_history等。2.4 內(nèi)存與進程運行時密碼的提取這是進階技術(shù)通常需要root權(quán)限。有些密碼永遠不會落盤只存在于進程的內(nèi)存空間里。例如一個啟動了的MySQL服務(wù)進程其內(nèi)存中必然持有連接數(shù)據(jù)庫的密碼或哈希一個通過ssh-agent緩存的私鑰密碼也存在于內(nèi)存中。進程命令行參數(shù)使用ps auxfww或ps -ef命令查看進程啟動時的完整命令行。有時密碼會通過-p參數(shù)直接傳遞。例如一個過時的mysqld啟動命令/usr/sbin/mysqld --usermysql --passwordMySuperSecretPass。進程內(nèi)存轉(zhuǎn)儲使用gdbGNU調(diào)試器或/proc/$PID/mem接口可以附加到進程并嘗試從其內(nèi)存空間中搜索字符串。這是一個更復雜、對系統(tǒng)有侵入性的操作必須在授權(quán)范圍內(nèi)謹慎進行。一個相對簡單的命令是使用strings工具處理進程的內(nèi)存映射strings /proc/$PID/mem | grep -i pass。但更常見和專業(yè)的做法是使用像gcore生成核心轉(zhuǎn)儲文件然后用strings分析。3. 手工排查構(gòu)建你的搜索命令組合拳了解了目標在哪下一步就是組織有效的搜索。完全依賴單一自動化腳本可能會遺漏上下文或產(chǎn)生大量誤報。手工排查的核心思路是由面到點層層遞進。3.1 初始偵察快速定位可疑文件首先獲得一個shell后無論什么權(quán)限先對環(huán)境有個整體了解。當前用戶與權(quán)限idwhoamisudo -l查看當前用戶能以root身份運行哪些命令這本身可能就是個突破口。系統(tǒng)信息uname -acat /etc/*-release了解系統(tǒng)版本。運行的服務(wù)netstat -tulpn或ss -tulpn查看開放端口和對應(yīng)進程這能告訴你系統(tǒng)上跑了什么服務(wù)MySQL? Redis? PostgreSQL?從而明確重點搜索方向。查找有特殊權(quán)限或最近修改的文件find / -perm -4000 -type f 2/dev/null查找SUID文件提權(quán)可能。find / -perm -2000 -type f 2/dev/null查找SGID文件。find / -type f -mtime -7 2/dev/null查找最近7天內(nèi)修改過的文件。攻擊者上傳的工具或修改的配置可能在其中。find / -type f -name “*.bak” -o -name “*.old” -o -name “*.temp” 2/dev/null。備份文件、舊配置文件往往包含原始的、未加密的密碼。3.2 核心搜索基于內(nèi)容的精準挖掘這是最關(guān)鍵的步驟。我們將使用find、grep、awk等命令的組合。基礎(chǔ)關(guān)鍵字搜索從根目錄開始搜索包含常見密碼關(guān)鍵詞的文件。注意這會比較慢且可能觸發(fā)大量權(quán)限錯誤所以我們將錯誤輸出重定向到/dev/null。# 搜索包含password, pass, pwd等關(guān)鍵詞的文件并顯示匹配行的前后幾行內(nèi)容 grep -r -n -i -B2 -A2 passw\|pwd\|secret\|key\|token /etc /home /opt /var 2/dev/null | head -100-B2 -A2參數(shù)可以顯示匹配行前后各2行的內(nèi)容這對于理解密碼的上下文比如是哪個變量、在哪個配置文件里非常有幫助。針對特定格式的搜索密碼有時會以特定格式出現(xiàn)。連接字符串搜索mysql://postgresql://jdbc:://user:pass。grep -r ://[^:]*:[^]* /home /opt 2/dev/nullBase64編碼看起來像亂碼的長字符串可能是編碼后的密碼。可以搜索結(jié)尾的字符串或者用grep -E匹配Base64字符集。grep -r -E ([A-Za-z0-9/]{4})*([A-Za-z0-9/]{3}|[A-Za-z0-9/]{2})? /path/to/search 2/dev/null | head -20JSON或YAML格式搜索password:password:。grep -r -i \password\\s*: /path/to/search 2/dev/null檢查歷史與內(nèi)存命令歷史立即查看當前shell的歷史以及所有可讀用戶的.bash_history。history # 當前shell歷史 cat ~/.bash_history for user in $(ls /home); do echo History for $user ; cat /home/$user/.bash_history 2/dev/null | tail -50; done進程信息ps auxfww | grep -E “(mysql|redis|postgres|ssh)” # 查看相關(guān)進程的命令行 # 如果有root權(quán)限可以嘗試從進程內(nèi)存中搜索字符串 # 例如找到MySQL的PID PID$(pgrep mysqld) if [ ! -z $PID ]; then strings /proc/$PID/environ | grep -i pass fi3.3 權(quán)限提升與深度搜索如果當前用戶權(quán)限較低很多文件無法讀取。那么搜索的第一步可能變成了權(quán)限提升。利用找到的數(shù)據(jù)庫密碼嘗試登錄數(shù)據(jù)庫也許能在數(shù)據(jù)庫里找到其他系統(tǒng)的密碼例如某些應(yīng)用將配置存在數(shù)據(jù)庫里。或者利用找到的SSH私鑰嘗試連接其他服務(wù)器。這就是所謂的“橫向移動”。在獲得更高權(quán)限尤其是root后搜索范圍將豁然開朗讀取所有用戶的家目錄grep -r -i “pass” /home/* 2/dev/null。檢查/etc/shadow雖然密碼是哈希值但弱密碼可以通過哈希碰撞或彩虹表破解。可以使用unshadow工具結(jié)合john或hashcat進行破解測試僅限授權(quán)測試。檢查內(nèi)存中的敏感信息使用/proc文件系統(tǒng)或工具如linpeas、LinEnum這些是自動化腳本但原理是手工命令的集合進行更全面的信息收集。4. 從攻擊者視角看防御如何讓你的密碼“隱身”了解了攻擊者如何尋找密碼我們就能更好地進行防御。這不僅僅是安全人員的職責更是每一位系統(tǒng)管理員和開發(fā)者的必修課。4.1 配置管理杜絕明文存儲使用配置管理工具與密鑰庫將密碼、API密鑰等敏感信息從配置文件中徹底移除。使用如HashiCorp Vault、AWS Secrets Manager、Azure Key Vault等密鑰管理服務(wù)。在應(yīng)用啟動時從這些服務(wù)動態(tài)拉取憑據(jù)。環(huán)境變量對于簡單場景可以使用環(huán)境變量。但要注意環(huán)境變量在ps命令中可能被看到通過/proc/$PID/environ且可能在日志中泄露。確保不將敏感信息打印到日志。配置文件權(quán)限如果必須使用配置文件將其權(quán)限設(shè)置為僅所有者可讀chmod 600 config.properties。并確保其所屬用戶和組正確。4.2 開發(fā)與運維規(guī)范代碼審查將“硬編碼密碼/密鑰”作為代碼審查的高危項。使用預(yù)提交鉤子pre-commit hook掃描代碼中是否含有密碼模式。清理歷史記錄定期清理或妥善管理命令歷史。對于包含敏感信息的命令可以在其前面加空格如果HISTCONTROL設(shè)置了ignorespace或者直接unset HISTFILE再執(zhí)行命令但更好的做法是根本不在命令行中直接輸入密碼。最小權(quán)限原則運行服務(wù)的賬戶如mysqlwww-data不應(yīng)該有讀取其他用戶家目錄或無關(guān)配置文件的權(quán)限。通過嚴格的用戶和文件權(quán)限控制即使某個服務(wù)被攻破也能將影響范圍限制在最小。4.3 日志與監(jiān)控日志脫敏確保應(yīng)用程序和中間件的日志配置中啟用了脫敏功能避免將密碼、令牌、身份證號等敏感信息寫入日志。文件完整性監(jiān)控使用工具如AIDE、Tripwire或Osquery監(jiān)控關(guān)鍵配置文件如/etc/passwd/etc/shadow Web應(yīng)用配置文件的變更并在發(fā)生未授權(quán)修改時告警。進程監(jiān)控監(jiān)控異常進程的創(chuàng)建特別是那些嘗試讀取/etc/shadow或大量掃描文件系統(tǒng)的進程。5. 實戰(zhàn)案例一次完整的內(nèi)部排查模擬假設(shè)我們作為內(nèi)部安全員接到通知某臺Web服務(wù)器(192.168.1.10)可能因一個過時的Web框架版本存在漏洞而被初步入侵。我們需要登錄該服務(wù)器檢查是否存在敏感信息泄露并評估風險。步驟1初始連接與環(huán)境評估通過SSH使用已有賬號登錄。首先檢查當前權(quán)限(id)發(fā)現(xiàn)是普通用戶webadmin。運行sudo -l發(fā)現(xiàn)該用戶被允許以root身份運行/usr/bin/systemctl restart apache2這是一個有價值的點但暫時用不上。先看看系統(tǒng)跑著什么ss -tulpn顯示有80Apache、3306MySQL、22SSH端口開放。步驟2針對性搜索Web相關(guān)配置既然有Apache和MySQL重點搜索相關(guān)配置和代碼。# 查找網(wǎng)站根目錄通常Apache默認在/var/www/html find /var/www -type f -name “*.php” -o -name “*.env” -o -name “config*.php” -o -name “*.yml” -o -name “*.yaml” 2/dev/null | head -20發(fā)現(xiàn)路徑/var/www/html/wordpress/wp-config.php。這是WordPress的配置文件經(jīng)典的存在數(shù)據(jù)庫密碼的地方。cat /var/www/html/wordpress/wp-config.php | grep -A2 -B2 “DB_PASSWORD”果然找到了define(DB_PASSWORD, Wpss123456);。步驟3利用找到的密碼進行橫向試探嘗試用這個密碼連接本機的MySQL。mysql -u wordpressuser -pWpss123456 -h 127.0.0.1成功登錄。在MySQL中可以查看是否有其他數(shù)據(jù)庫或表存儲了更多信息。執(zhí)行show databases;發(fā)現(xiàn)除了wordpress庫還有一個app_config庫。進入該庫發(fā)現(xiàn)一張表service_credentials里面竟然明文存儲了訪問內(nèi)網(wǎng)另一臺Redis緩存服務(wù)器(192.168.1.20)和一臺文件服務(wù)器(192.168.1.30)的密碼。步驟4擴大搜索范圍退出MySQL。現(xiàn)在有了新的目標。同時繼續(xù)在本地搜索。# 檢查webadmin用戶的歷史和文件 cat ~/.bash_history ls -la ~/.ssh/ cat ~/.ssh/config 2/dev/null # 搜索備份腳本 find / -type f -name “*.sh” -exec grep -l “pass\|pwd” {} \; 2/dev/null在/opt/scripts/backup_db.sh中發(fā)現(xiàn)使用了mysqldump -u root -pRootDBPass!#的命令。這又是一個高權(quán)限的數(shù)據(jù)庫密碼。步驟5評估與報告至此我們發(fā)現(xiàn)了至少三處嚴重的明文密碼泄露WordPress配置文件中的數(shù)據(jù)庫密碼已導致可訪問app_config庫。app_config庫中存儲的其他內(nèi)網(wǎng)服務(wù)密碼導致內(nèi)網(wǎng)橫向移動風險劇增。備份腳本中的MySQL root密碼導致數(shù)據(jù)庫完全失控。根本原因開發(fā)人員將生產(chǎn)數(shù)據(jù)庫密碼硬編碼在配置文件中另一個應(yīng)用將多個服務(wù)的憑證以明文形式存在業(yè)務(wù)數(shù)據(jù)庫里運維人員在腳本中直接使用root密碼。防御措施完全缺失。建議立即更改所有涉及的服務(wù)密碼。將WordPress的wp-config.php文件權(quán)限設(shè)置為640所有者設(shè)為root組設(shè)為Web服務(wù)器用戶。廢除備份腳本中的明文密碼改用mysql_config_editor設(shè)置登錄路徑或從安全存儲中獲取。徹底改造app_config庫移除明文密碼引入統(tǒng)一的密鑰管理服務(wù)。對所有服務(wù)器進行一輪類似的敏感信息掃描。通過這個模擬案例你可以看到一次簡單的查找如何像剝洋蔥一樣層層深入地揭示出整個系統(tǒng)中脆弱的安全實踐。它遠不止是執(zhí)行幾條grep命令而是一個結(jié)合了系統(tǒng)知識、應(yīng)用理解、邏輯推理和持續(xù)驗證的過程。無論是攻擊還是防御對這套流程的熟練掌握都價值連城。