
本地想練手Web安全繞不開一個東西——DVWA。我身邊不少剛?cè)腴T的朋友問得最多的就是DVWA下載安裝到底怎么搞踩坑最多的也是這一步下下來丟進(jìn)網(wǎng)站根目錄打開一片空白或者登錄頁轉(zhuǎn)圈、數(shù)據(jù)庫連不上。其實這套東西本身一點都不復(fù)雜它就是一個用PHP寫的、故意留了破綻的Web應(yīng)用跑在你自己的機器上讓你在一個合法的、可控的環(huán)境里去理解Web應(yīng)用的各種典型缺陷是怎么產(chǎn)生的、防御手段又是怎么起作用的。它最適合兩類人一類是剛接觸Web安全、想找個能動手的環(huán)境把書本概念落地的初學(xué)者另一類是做開發(fā)或者運維想直觀感受一下自己寫的代碼在防御不當(dāng)時會呈現(xiàn)什么狀態(tài)。今天我就把自己反復(fù)裝過好幾遍的流程、參數(shù)配置和那些坑盡量一次講透。1. DVWA到底是什么值不值得本地搭一套1.1 從能動手的環(huán)境說起很多人第一次接觸DVWA是在各種教程里看到的截圖一個樸素的登錄框進(jìn)去之后左邊一列菜單列著十來個功能模塊。這些模塊覆蓋了Web應(yīng)用里最常見的幾類問題比如輸入校驗不嚴(yán)、身份驗證邏輯薄弱、文件處理不當(dāng)、請求偽造等等。它的價值不在于功能多強而在于它是一個靶場——專門給你打的靶子附帶不同難度的防御檔位讓你能對比同一個功能在低防御和高防御下表現(xiàn)有什么不同。打個比方學(xué)開車你不會直接上高速而是先在教練場里練。DVWA就是Web安全領(lǐng)域的教練場場地是封閉的出不了事但地形足夠豐富。你可以在里面反復(fù)試、反復(fù)錯不用擔(dān)心影響任何人。必須強調(diào)一點DVWA只應(yīng)該跑在你自己的電腦或者完全隔離的內(nèi)網(wǎng)實驗環(huán)境里。它的設(shè)計目的就是易受攻擊一旦掛到公網(wǎng)等于把一扇沒鎖的門擺在馬路上。這是我見過最多的低級失誤也是所有注意事項里排第一位的。1.2 搭建前必須想清楚的三件事第一件事是你打算用什么系統(tǒng)。Windows、Linux、macOS都能跑區(qū)別只在于PHP和數(shù)據(jù)庫怎么裝。如果你只是想快點看到界面Windows下一體化集成環(huán)境最省事如果你想順便練練Linux命令那就用虛擬機裝個Linux發(fā)行版手工配一遍LAMP收獲更大。第二件事是PHP版本。DVWA的經(jīng)典穩(wěn)定版1.9、1.10這兩個版本號大家見得最多對PHP版本比較挑。1.9時代的東西在PHP 5.4到7.x上跑得比較順到了PHP 8環(huán)境部分老模塊會因為語法或函數(shù)行為變化而報錯。如果你用的是一體化集成環(huán)境里自帶的高版本PHP遇到報錯先別懷疑自己裝錯了很可能就是版本不匹配。第三件事是要不要用容器。Docker路線是現(xiàn)在最干凈的方案一條命令拉鏡像、起容器環(huán)境隔離刪掉不留垃圾。代價是你得先有Docker環(huán)境而且對里面到底發(fā)生了什么的理解會淺一些。我個人建議第一遍手工裝把配置搞明白之后要反復(fù)折騰就換Docker。提示無論選哪條路線都請確認(rèn)這臺機器不在公網(wǎng)可達(dá)的位置。實驗完畢及時關(guān)閉服務(wù)或者干脆用一次性虛擬機。2. 環(huán)境準(zhǔn)備三條主流路線的取舍2.1 路線一一體化集成環(huán)境最省事Windows下最常見的做法是用一體化集成環(huán)境它把Apache、PHP、MySQL打包好裝完就能用圖形界面點點鼠標(biāo)就能啟停服務(wù)。這一步的核心操作只有兩個把服務(wù)全部啟動然后把DVWA的源碼目錄整個放進(jìn)網(wǎng)站根目錄。以常見的集成環(huán)境為例網(wǎng)站根目錄一般在安裝目錄下的WWW或者h(yuǎn)tdocs文件夾。把解壓出來的DVWA文件夾整個復(fù)制進(jìn)去路徑類似這樣D:\phpstudy_pro\WWW\dvwa C:\xampp\htdocs\dvwa放好之后瀏覽器訪問http://127.0.0.1/dvwa/如果能看到頁面哪怕是報錯頁說明Web服務(wù)器已經(jīng)正確識別到目錄了。這條路線的好處是五分鐘能跑起來壞處是你不太清楚PHP的配置文件在哪、改了什么生效了什么沒生效。我建議即使用這條路線也順手找到php.ini的位置后面調(diào)參數(shù)要用。2.2 路線二Linux手工搭LAMP練手價值最高如果你用虛擬機裝了個Linux發(fā)行版流程大致是裝Web服務(wù)器、裝PHP及相關(guān)擴(kuò)展、裝數(shù)據(jù)庫然后放代碼、配權(quán)限。以Debian系為例裝完基礎(chǔ)組件后Web根目錄通常是/var/www/html。這里有一個比Windows麻煩得多、但必須處理的問題文件權(quán)限和目錄歸屬。Linux下Web服務(wù)進(jìn)程通常以www-data這個身份運行如果你的代碼目錄歸root所有且權(quán)限是755那么DVWA在初始化數(shù)據(jù)庫、寫入上傳目錄時就會失敗。正確做法是sudo chown -R www-data:www-data /var/www/html/dvwa sudo find /var/www/html/dvwa -type d -exec chmod 755 {} \; sudo find /var/www/html/dvwa -type f -exec chmod 644 {} \;另外還有SELinux這個隱形殺手。如果你的發(fā)行版默認(rèn)開啟了強制模式即使權(quán)限全對Web進(jìn)程依然寫不進(jìn)去。排查時可以先臨時把它設(shè)為寬松模式驗證一下是不是它的問題確認(rèn)后再針對性調(diào)整策略而不是一直關(guān)著。2.3 路線三Docker環(huán)境隔離最干凈容器路線的邏輯很簡單鏡像里已經(jīng)把Apache、PHP、數(shù)據(jù)庫和DVWA源碼全部配好了你只需要把容器的端口映射到你本機的一個空閑端口。典型命令形態(tài)是docker run -d --name dvwa -p 8080:80 vulnerables/web-dvwa起起來之后訪問http://127.0.0.1:8080。注意我這里故意把宿主端口寫成8080而不是80因為80端口太容易被本機其他服務(wù)占用映射到高位端口能避開一堆沖突。容器里數(shù)據(jù)庫已經(jīng)初始化過進(jìn)去直接登錄即可。容器路線的坑主要集中在兩點一是數(shù)據(jù)不持久化docker rm之后配置全丟想保留就掛載卷二是容器內(nèi)的時間、編碼設(shè)置可能和宿主機不同遇到中文亂碼之類的問題需要進(jìn)容器調(diào)整。2.4 三條路線怎么選對比維度一體化集成環(huán)境Linux手工LAMPDocker容器首次上手耗時約10分鐘約40分鐘約5分鐘對原理的理解深度淺深中環(huán)境隔離性差容易污染本機好在虛擬機內(nèi)最好出問題時排查難度中高低刪了重建適合人群想快速看效果想系統(tǒng)練Linux反復(fù)重建環(huán)境的人我的建議是按順序來先用集成環(huán)境跑通一遍消除我裝不上的焦慮然后換Linux手工裝一遍把權(quán)限、擴(kuò)展、配置文件這些核心環(huán)節(jié)吃透后面需要頻繁重裝的時候直接上Docker。這三遍走下來你對一個Web應(yīng)用從源碼到能訪問的完整鏈路理解會比看十篇教程都深。3. 下載與部署實操全流程3.1 源碼從哪來才靠譜DVWA是開源項目源碼托管在公開的代碼倉庫上官方發(fā)布過多個正式版本。獲取方式有兩個一是從倉庫的發(fā)布頁面下載打包好的壓縮包二是直接用版本控制工具把整個倉庫拉下來。前者更穩(wěn)后者能拿到最新開發(fā)分支的代碼。這里有個經(jīng)驗優(yōu)先選正式發(fā)布的版本包。開發(fā)分支的代碼雖然在跟進(jìn)新環(huán)境適配但沒經(jīng)過完整驗證可能出現(xiàn)你今天裝好了、明天更新一下就報錯的情況。版本包下載下來通常是一個zip或tar.gz解壓后目錄名可能帶版本后綴比如DVWA-1.10之類建議手動改名為dvwa路徑短、看著清爽也避免后面配置時路徑寫錯。如果用的是版本控制工具拉取注意拉完之后倉庫里會多一個版本控制目錄雖然不影響運行但整潔起見可以刪掉。3.2 目錄放置與訪問路徑確認(rèn)解壓出來的目錄結(jié)構(gòu)大致是這樣頂層有一些說明文檔和許可證文件然后是config目錄存放配置模板dvwa目錄存放核心代碼還有vulnerabilities、hackable等目錄分別對應(yīng)各個功能模塊和上傳文件的存放位置。放置原則只有一條整個dvwa目錄必須完整放進(jìn)Web服務(wù)器能訪問到的根目錄下面不能只放其中一部分。很多人出錯就是因為只把dvwa子目錄拷出來了結(jié)果缺少配置文件模板打開就報錯。放好之后訪問時注意路徑結(jié)尾的斜杠。http://127.0.0.1/dvwa和http://127.0.0.1/dvwa/在多數(shù)環(huán)境下行為一致但個別配置會把不帶斜杠的請求重定向多繞一次就可能出問題。養(yǎng)成帶斜杠的習(xí)慣。3.3 配置文件詳解與數(shù)據(jù)庫綁定這是整個安裝過程里最關(guān)鍵、也最容易卡住的一步。DVWA目錄里有一個配置模板文件通常叫config.inc.php.dist.dist后綴表示分發(fā)模板需要你復(fù)制一份、去掉后綴變成config.inc.php才會被程序讀取。打開這個文件你會看到幾組關(guān)鍵參數(shù)我按重要程度逐個說$_DVWA[ db_server ] 127.0.0.1; $_DVWA[ db_database ] dvwa; $_DVWA[ db_user ] root; $_DVWA[ db_password ] pssw0rd; $_DVWA[ db_port ] 3306;db_server建議寫成127.0.0.1而不是localhost。原因在于當(dāng)PHP把localhost解釋到本地套接字時可能會繞過TCP端口配置導(dǎo)致你明明改了端口號卻不生效。寫IP地址能強制走TCP行為更好預(yù)測。db_database是數(shù)據(jù)庫名默認(rèn)叫dvwa。注意這個庫需要你提前創(chuàng)建DVWA的安裝腳本會往里建表但它通常不會替你創(chuàng)建庫本身部分版本會自動建取決于數(shù)據(jù)庫用戶權(quán)限。db_user和db_password是最容易出錯的地方。默認(rèn)配置里寫的是root加一個示例密碼你的實際數(shù)據(jù)庫密碼肯定不是這個。這里有兩個選擇直接填root賬號的真實密碼。省事但不推薦權(quán)限太大。新建一個只對dvwa庫有權(quán)限的專用賬號。這是更規(guī)范的做法。專用賬號的創(chuàng)建語句大致是CREATE DATABASE dvwa DEFAULT CHARACTER SET utf8mb4; CREATE USER dvwa_userlocalhost IDENTIFIED BY StrongPass123!; GRANT ALL PRIVILEGES ON dvwa.* TO dvwa_userlocalhost; FLUSH PRIVILEGES;注意字符集。用utf8mb4而不是老的utf8能避免后面遇到中文內(nèi)容時的存儲問題。還有一個坑新版數(shù)據(jù)庫的默認(rèn)認(rèn)證插件可能和老版本PHP的數(shù)據(jù)庫擴(kuò)展不兼容表現(xiàn)為密碼明明對就是連接被拒絕。遇到這種情況需要把該用戶的認(rèn)證方式調(diào)整為兼容模式。這是版本組合問題不是你的配置寫錯了。提示改完配置文件記得保存時不要帶上BOM頭某些編輯器會悄悄加導(dǎo)致頁面頂部出現(xiàn)空白行甚至報錯。用UTF-8無BOM格式保存。3.4 初始化數(shù)據(jù)庫與首次登錄配置文件就位之后訪問安裝入口頁面通常是站點根下的setup.php。這個頁面會做幾件事檢查環(huán)境PHP版本、擴(kuò)展、目錄權(quán)限然后提供一個按鈕讓你創(chuàng)建或重置數(shù)據(jù)庫。如果環(huán)境檢查一片綠直接點按鈕稍等幾秒會提示創(chuàng)建成功。如果出現(xiàn)紅色告警頁面會告訴你哪一項不滿足逐條解決就行。常見的告警項包括PHP版本不符合要求、缺少某個數(shù)據(jù)庫擴(kuò)展、配置文件不存在或不可寫。初始化成功后用默認(rèn)賬號登錄默認(rèn)用戶名和密碼在官方文檔里寫著登錄后第一件事就是改密碼——雖然是本地環(huán)境但養(yǎng)成習(xí)慣沒壞處。進(jìn)去之后還有一個必做操作設(shè)置安全等級。DVWA提供幾檔難度從幾乎不設(shè)防到嚴(yán)格防御。等級是存在數(shù)據(jù)庫里的所以重置數(shù)據(jù)庫會把它恢復(fù)成默認(rèn)值。我通常的做法是先把默認(rèn)等級調(diào)成最低檔確認(rèn)所有功能都能正常打開、不報錯然后再逐檔往上調(diào)觀察同一功能的表現(xiàn)差異。這個對比過程才是DVWA真正的價值所在。4. 高頻報錯排查實錄4.1 數(shù)據(jù)庫相關(guān)連不上、建不了庫癥狀一頁面提示無法連接數(shù)據(jù)庫。排查順序是數(shù)據(jù)庫服務(wù)是否在跑 → 端口是否對 → 賬號密碼是否正確 → 該賬號是否允許從當(dāng)前來源連接。很多人忽略了最后一條數(shù)據(jù)庫用戶是按用戶來源主機來區(qū)分的dvwa_userlocalhost和dvwa_user127.0.0.1在數(shù)據(jù)庫看來是兩個不同的賬號。如果你的連接走的是TCP也就是配置里寫了127.0.0.1那授權(quán)就必須給dvwa_user127.0.0.1或者用通配來源。癥狀二初始化時提示無法創(chuàng)建表。這通常是權(quán)限不足。檢查該用戶是否擁有對dvwa庫的完整權(quán)限而不只是查詢權(quán)限。癥狀三密碼正確但認(rèn)證失敗。前面提到的認(rèn)證插件兼容問題。確認(rèn)數(shù)據(jù)庫版本必要時調(diào)整用戶的認(rèn)證方式。4.2 頁面相關(guān)空白、404、403白屏是最常見的。白屏意味著PHP腳本執(zhí)行出錯了但錯誤信息沒顯示出來。解決思路是先把錯誤顯示打開。找到php.ini把這兩個參數(shù)調(diào)整好display_errors On error_reporting E_ALL改完重啟Web服務(wù)再訪問具體的錯誤行號和原因就會打在頁面上比對著白屏猜快一百倍。404是路徑問題。說明Web服務(wù)器沒找到對應(yīng)文件。檢查三件事目錄是不是真的放進(jìn)了根目錄、訪問路徑大小寫是否一致Linux下大小寫敏感DVWA和dvwa是兩個不同的目錄、服務(wù)器是否配置了正確的根目錄指向。403是權(quán)限問題。Web服務(wù)器找到了文件但拒絕提供。Linux下檢查目錄的執(zhí)行權(quán)限和文件的讀權(quán)限以及SELinux狀態(tài)。Windows下檢查文件夾的安全屬性是否給了Web服務(wù)進(jìn)程讀取權(quán)限。4.3 功能模塊相關(guān)部分頁面報錯有時候主頁面能進(jìn)但點某個具體功能模塊就報錯。這類問題十有八九和PHP擴(kuò)展有關(guān)。比如涉及URL加載的模塊需要開啟allow_url_fopen涉及遠(yuǎn)程包含的模塊需要開啟allow_url_include。這兩個開關(guān)默認(rèn)是關(guān)閉的需要在php.ini中顯式打開。allow_url_fopen On allow_url_include On改完重啟服務(wù)。這是為了在隔離環(huán)境里完整呈現(xiàn)功能行為只在本地實驗環(huán)境這么做生產(chǎn)服務(wù)器上這兩個開關(guān)的處置方式完全不同。另外上傳類模塊要求上傳目錄可寫。檢查hackable/uploads這個目錄的權(quán)限Linux下確保Web進(jìn)程用戶對它有寫權(quán)限。4.4 常見問題速查表現(xiàn)象最可能的原因處理方向整頁空白PHP錯誤未顯示打開display_errors看具體報錯提示連不上數(shù)據(jù)庫賬號/來源主機不匹配核對用戶授權(quán)中的來源標(biāo)識數(shù)據(jù)庫初始化失敗用戶權(quán)限不足或庫不存在手動建庫并授權(quán)訪問404目錄未放對或大小寫不符核對實際路徑與訪問路徑訪問403文件權(quán)限或安全策略攔截調(diào)整目錄權(quán)限檢查安全模塊某模塊單獨報錯相關(guān)PHP擴(kuò)展未開啟在php.ini中開啟對應(yīng)開關(guān)中文顯示亂碼字符集不一致庫、表、頁面統(tǒng)一用utf8mb4改了配置不生效服務(wù)未重啟或配置未生效重啟Web服務(wù)后清緩存重試5. 漢化、版本選擇與長期維護(hù)5.1 界面漢化的正確姿勢英文界面看久了確實累社區(qū)里有漢化包。使用方式一般是把漢化文件覆蓋到對應(yīng)的語言目錄下然后在配置里把默認(rèn)語言改成中文。這里有兩個注意點一是漢化文件的版本要和DVWA版本對應(yīng)跨版本覆蓋很容易出現(xiàn)菜單錯位、部分文字缺失甚至頁面報錯二是覆蓋之前先備份原文件出問題能退回去。如果漢化后發(fā)現(xiàn)某個頁面異常最快的定位方法就是把語言改回英文看是否恢復(fù)正常。如果英文下正常、中文下異常那問題就鎖定在語言文件上檢查是不是編碼不是UTF-8無BOM。5.2 版本選擇的一點經(jīng)驗DVWA的版本迭代不算快但不同版本對運行環(huán)境的要求差別不小。選版本的原則很簡單跟著你的PHP版本走。老版本PHP就配老版本DVWA新版本PHP就找明確聲明支持新版本的發(fā)行版。強行混搭的典型后果就是打開一片紅字報錯然后你花兩小時排查配置最后發(fā)現(xiàn)是版本不兼容白忙一場。我個人習(xí)慣是環(huán)境定下來之后先用一個已知能跑的版本組合把流程走通把配置參數(shù)記在筆記里。以后再裝直接照著筆記復(fù)現(xiàn)效率高得多。5.3 環(huán)境備份與快速復(fù)現(xiàn)DVWA本身沒什么好備份的代碼隨時能重新下數(shù)據(jù)庫隨時能重建。真正值得備份的是你的環(huán)境配置記錄。我自己的筆記里固定記這幾項PHP版本、數(shù)據(jù)庫版本、php.ini里改動過的參數(shù)、數(shù)據(jù)庫賬號和授權(quán)語句、DVWA的版本號。有這五項換臺機器半小時內(nèi)就能完全復(fù)現(xiàn)。如果用虛擬機更省事的做法是在環(huán)境配置完成后打一個快照。之后無論把環(huán)境折騰成什么樣回滾快照就是幾秒鐘的事。這個習(xí)慣在做各種實驗時特別有用——畢竟靶場的意義就是讓你隨便折騰折騰壞了能一鍵還原心理負(fù)擔(dān)會小很多。注意定期檢查實驗環(huán)境是否還在監(jiān)聽對外端口。用一次性虛擬機做實驗時實驗結(jié)束直接關(guān)機用本機環(huán)境時用完停掉服務(wù)。6. 我在反復(fù)安裝中踩過的那些坑第一個坑是目錄權(quán)限只在Linux上才想起來檢查。Windows下安裝包自動給了權(quán)限一路順暢換到Linux就各種寫不進(jìn)去。后來我養(yǎng)成了習(xí)慣代碼放好之后第一步就是統(tǒng)一調(diào)整歸屬和權(quán)限而不是等報錯再回頭找。第二個坑是配置文件的后綴。.dist這個后綴的存在感太低了我第一次裝的時候盯著目錄看了半天心想配置文件明明在啊結(jié)果就是沒去掉后綴。這件事現(xiàn)在聽著好笑但新手十有八九會遇上。第三個坑是localhost和127.0.0.1的區(qū)別。這東西平時看不出來一旦你把數(shù)據(jù)庫端口從默認(rèn)值改了問題就冒出來了。統(tǒng)一寫IP地址能省掉這類玄學(xué)問題。第四個坑是忘了重啟服務(wù)。改了php.ini不重啟改一百遍也沒用?,F(xiàn)在我的動作固定成一套改配置 → 重啟服務(wù) → 刷新頁面 → 驗證效果中間不跳步。第五個坑是把環(huán)境留在了不該留的地方。有次做完實驗忘了關(guān)服務(wù)那臺機器又恰好在局域網(wǎng)里能被別人訪問到。雖然沒造成什么后果但從那以后我給自己定了條規(guī)矩實驗環(huán)境的服務(wù)用完就停長期用的一定放在隔離的虛擬機里。最后分享一個提高效率的小技巧把整個安裝流程寫成一份自己的檢查清單從下載、解壓、放置、復(fù)制配置、建庫授權(quán)、初始化、登錄、設(shè)等級一共八步每步后面標(biāo)注驗證方法。下次重裝的時候照著清單走不回頭、不遺漏一次成功率能提到九成以上。這套環(huán)境搭起來之后你能做的事情遠(yuǎn)不止打開看看。真正有價值的是把它當(dāng)成一個可以反復(fù)對照的實驗臺同一個功能在不同防御檔位下表現(xiàn)有何差異為什么會有這種差異加上什么樣的防護(hù)能改變結(jié)果。這些問題的答案在你自己動手驗證過一遍之后會比任何文檔都記得牢。而這一切的起點就是今天這篇東西里講的下載安裝這幾步——把它走順了后面才有得玩。