# 網站安全性掃描

URL: https://discuvr.org/security-scan/?hl=zh-hant
Last updated: 2026-11-07
MCP tool: `security_scan`

掃描網域以發現缺失的安全標頭、TLS 問題和暴露的檔案。每項發現都顯示原始證據和用於重現的確切命令。

很多掃描器給你一個字母等級和一串嚇人的詞。這個工具也給等級，但扣掉的每一分都對應一項發現，其中列出它實際收到的回應，以及能讓你拿到同樣回應的一行指令。所以一項發現是你能自己核實的，而不是只能相信的。

## 功能作用

- 檢查 DNS 與 CAA、SPF 與 DMARC、TLS 憑證與 TLS 1.0/1.1、HTTPS 轉址、安全標頭、Cookie 屬性、CORS、版本標示、HTTP 方法、混合內容、23 個敏感路徑、目錄列表、robots.txt、security.txt 以及 12 個服務連接埠。
- 每項發現都附帶原始觀察結果，以及用於重現它的 shell 指令。
- 無法執行的檢查會回報為"未檢查" - 絕不會悄悄算作通過。
- 報告可下載為 Markdown 或 JSON 格式。

## 運作方式

1. 輸入一個你負責的網域。
2. 掃描執行被動探測 - 一般請求，不進行任何利用。
3. 閱讀每項發現及其證據，並核實其中重要的部分。

## 沒有任何發現是憑空捏造的

掃描器不含任何語言模型。每項檢查的嚴重程度、影響和修復方式都是固定的，每項發現都來自一次真實觀察。頁面上的報告以及 Markdown 和 JSON 下載都由同一組發現產生，全程不涉及模型。

## 等級如何計算

分數從 100 開始，每項嚴重發現扣 34 分，高風險扣 13 分，中風險扣 5 分，低風險扣 1.5 分，每個級別的扣分有上限（高風險 45、中風險 22、低風險 9）。資訊類和通過的結果不扣分。90 分以上為 A，75 分起為 B，60 分起為 C，40 分起為 D，更低為 F。只要有一個外洩的 .env 檔案或一個可連線的資料庫連接埠，原本乾淨的網站就會從 100 分降到 66 分，也就是 C；兩項這樣的發現得 32 分，也就是 F。

## 如何避免誤報

在探測 /.git/HEAD 或 /backup.sql 這類路徑之前，掃描器會先請求一個不可能存在的隨機網址，並記錄網站的回應。只有當某個路徑回傳 HTTP 200、與這個找不到的基準不同，而且符合該檔案本身的特徵時，才會被回報為外洩。因此，對任何網址都回傳首頁的網站，不會被一整頁嚴重發現淹沒。

## 乾淨的報告不是一張證書

這些是針對運行中網站的被動檢查。它們不涉及應用程式邏輯、身分驗證、存取控制，或登入之後的任何內容 - 而那些正是真正的入侵通常開始的地方。無法完成的檢查正是因為這個原因被列為未檢查：由失敗連線得出的通過是一種虛假的安心，而沒有發現任何問題的掃描意味著沒有找到問題，並不意味著那裡什麼都沒有。

## 只掃描屬於你自己的目標

只掃描你擁有或已取得書面測試許可的網域。此工具會拒絕解析到私人或內部位址的主機，並按 IP 進行速率限制，但授權仍然是你自己的責任。

## 問題

**這是主動攻擊嗎？**

不是。它只送出一般的 GET、HEAD 和 OPTIONS 請求，進行 TLS 交握（包括嘗試 TLS 1.0 和 1.1），透過 Cloudflare 的 DNS over HTTPS 查詢 DNS，並對 12 個連接埠做簡單的 TCP 連線。不利用任何漏洞，不送出任何表單，也不修改任何內容。

**我可以掃描任何網站嗎？**

只能掃描你擁有或已獲授權測試的網站。未經許可掃描第三方基礎設施，在你所在地可能是違法的。

**為什麼一項檢查顯示"未檢查"？**

因為它無法完成 - 通常是因為該來源沒有任何回應。它會被誠實地回報，而不會被記為通過。

**我可以匯出報告嗎？**

可以，匯出為 Markdown 或 JSON，有效期一小時：報告在這一小時內保存在伺服器快取中以便下載，之後過期。兩種匯出都不使用模型。使用紀錄只保存發現數量和等級，不保存網域。

**它會檢測哪些檔案和連接埠？**

檔案：23 個固定路徑，包括 /.git/HEAD, /.git/config, /.env, /.env.local, /.env.production, /.aws/credentials, /id_rsa, /backup.zip, /backup.sql, /dump.sql, /wp-config.php.bak, /phpinfo.php, /server-status, /actuator/env；只有當回應與該檔案特有的簽章相符時才會回報。若已發布 /.well-known/security.txt，則計為加分項。連接埠：對 21 FTP, 23 Telnet, 25 SMTP, 3306 MySQL, 5432 PostgreSQL, 6379 Redis, 27017 MongoDB, 9200 Elasticsearch, 3389 RDP, 5900 VNC, 11211 Memcached, 8080 發起一般 TCP 連線，絕不嘗試登入。可從外網存取的資料庫連接埠（MySQL、PostgreSQL、Redis、MongoDB、Elasticsearch）或 Telnet 會被評為嚴重。

**SPF 和 DMARC 檢查會標記哪些問題？**

兩筆記錄都從公共 DNS 讀取，即使網站不寄信也會檢查，因為少了它們，任何人都能寄出冒充你網域的郵件。沒有 SPF 記錄為中風險；含 +all 的 SPF 記錄允許網際網路上任何伺服器寄信，為高風險。_dmarc 下沒有 DMARC 記錄為中風險；p=none（或沒有 p= 標籤）只做監控，為低風險；p=quarantine 或 p=reject 通過。完全不寄信的網域可以發布 v=spf1 -all。

**會檢查哪些安全標頭，什麼值才算通過？**

檢查首頁回應中的六個標頭。缺少時，HSTS 與 Content-Security-Policy 為高風險，X-Content-Type-Options 與 X-Frame-Options 為中風險，Referrer-Policy 與 Permissions-Policy 為低風險。Strict-Transport-Security 的 max-age 至少要 15552000（180 天）：更短為低風險，max-age=0 為中風險。如果 script-src 允許 'unsafe-inline'、政策允許 'unsafe-eval'，或 default-src、script-src 中有單獨的 * 萬用字元，Content-Security-Policy 會被標為已削弱（中風險）。X-Content-Type-Options 必須正好是 nosniff。X-Frame-Options 應為 DENY 或 SAMEORIGIN，如果 CSP 已設定 frame-ancestors 則不需要。Referrer-Policy 只有在 unsafe-url 或 no-referrer-when-downgrade 時才會被標記。Permissions-Policy 只要存在即可。每個缺少或偏弱的標頭都附有一條 curl -sI 指令，方便你自行核對。

**它如何檢查 Cookie 屬性（Secure、HttpOnly、SameSite）？**

它讀取首頁回應中的每個 Set-Cookie 標頭（最多 12 個 Cookie），逐一檢查 Secure、HttpOnly 與 SameSite。缺少 Secure 或 HttpOnly 為中風險；只缺 SameSite 為低風險；SameSite=None 但沒有 Secure 會被單獨指出，因為瀏覽器會拒絕這種 Cookie。三項齊全即通過。常見修正是 Secure; HttpOnly; SameSite=Lax（Django 中為 SESSION_COOKIE_SECURE、SESSION_COOKIE_HTTPONLY 與 SESSION_COOKIE_SAMESITE）。掃描不會登入，所以看不到只在登入後才設定的 Cookie。可以用這條指令自行核對：curl -sI https://your-site/ | grep -i set-cookie

**CORS 檢查如何進行，什麼情況下是嚴重？**

它向首頁送出一個帶 Origin: https://scanner-probe.example 的 GET 請求，讀取回應中的 Access-Control-Allow-Origin 與 Access-Control-Allow-Credentials。沒有 Access-Control-Allow-Origin 標頭，或回傳一個不回顯測試來源的固定來源，即通過。回顯測試來源並同時回傳 Access-Control-Allow-Credentials: true 為嚴重，因為已登入使用者造訪的任何網站都能讀取其回應。回顯來源但不帶憑證為中風險。萬用字元 * 為低風險，若同時允許憑證則為中風險（瀏覽器會拒絕這種組合）。只檢測首頁，也不送出 OPTIONS 預檢請求，所以請另外檢測 API 路由：curl -sI -H "Origin: https://scanner-probe.example" https://your-site/api/ | grep -i access-control

**TLS 檢查會測試哪些內容（憑證到期、TLS 1.0 和 1.1）？**

它連線到 443 連接埠，驗證憑證鏈和主機名稱。無法通過驗證的憑證為高風險，已過期的憑證還會額外標為嚴重，剩餘不到 15 天的為中風險；否則會把主體、簽發者、到期日期和 SAN 名稱列為通過項目。協商出的協定必須是 TLS 1.2 或 TLS 1.3，更舊的版本為高風險。接著它分別單獨嘗試一次 TLS 1.0 交握和一次 TLS 1.1 交握：伺服器接受其中任何一個都會得到中風險結果，因為兩者都已被 RFC 8996 淘汰。如果掃描器本身的 OpenSSL 無法提供舊版本，就不回報任何內容，而不是去猜測。nginx 的修正方法是 ssl_protocols TLSv1.2 TLSv1.3; 可以用以下指令自行查看日期：echo | openssl s_client -connect your-site:443 -servername your-site 2>/dev/null | openssl x509 -noout -dates

**它會檢查 HTTP 是否重新導向到 HTTPS 嗎？**

會。它在不跟隨重新導向的情況下請求 http://your-site/。以 301 或 308 導向 https:// 位址即為通過。以 302、303 或 307 導向 HTTPS 為低風險，因為瀏覽器不會記住暫時性重新導向，每次新的造訪都會先送出一個未加密的請求。透過未加密 HTTP 直接提供頁面（2xx 回應）為高風險。如果 80 連接埠完全沒有回應，只是提示資訊，不算失敗。nginx 的修正方法是 server { listen 80; return 301 https://$host$request_uri; }，然後加上 Strict-Transport-Security。可以用以下指令自行檢查：curl -I http://your-site/

**它會標記哪些 HTTP 方法（TRACE、PUT、DELETE）？**

它向你的首頁送出一次 OPTIONS 請求，讀取 Allow 回應標頭；沒有 Allow 時讀取 Access-Control-Allow-Methods。宣告了 TRACE、TRACK、PUT 或 DELETE 為中風險；只有 PATCH 或 CONNECT 為低風險；只有標準讀取方法即為通過。如果伺服器兩個標頭都沒有送出，就不回報任何內容。宣告了某個方法並不能證明它真的可用，所以修改之前先確認。TRACE 可能把請求標頭（包括 Cookie）原樣回傳給呼叫端（Cross-Site Tracing）。nginx 預設拒絕 TRACE；Apache 需設定 TraceEnable Off。把 PUT 和 DELETE 限制在確實需要它們的 API 路由上，並放在身分驗證之後。可以用以下指令自行檢查：curl -X OPTIONS -i https://your-site/

**它如何偵測目錄列表（"Index of /"）？**

它請求 7 個路徑：/, /static/, /assets/, /uploads/, /images/, /files/ 和 /backup/。某個路徑以 HTTP 200 回應、且頁面標題或主標題以 "Index of /" 開頭時，回報為中風險（CWE-548），因為目錄列表會暴露沒有任何連結指向的檔案，例如備份、匯出檔和舊版本。如果都沒有，檢查即為通過；如果無法連上網站，則回報為未執行。nginx 的修正方法是 autoindex off;（這本來就是預設值，所以要找明確寫出的 autoindex on），Apache 是 Options -Indexes，然後把所有敏感檔案移出網站根目錄。可以用以下指令自行檢查：curl -s https://your-site/uploads/ | head -20

**它能發現混合內容和透過 HTTP 送出的表單嗎？**

能，針對首頁。它依伺服器回傳的原樣讀取 HTML（不執行 JavaScript），列出 src 或 href 以 http:// 開頭的每個 script、link、iframe 或 img 標籤。只要其中有 .js 或 .css 檔案，結果就是中風險，因為在傳輸途中被替換的指令碼或樣式表會在你的 HTTPS 頁面裡執行；只有圖片和框架為低風險；一個都沒有則通過（CWE-311）。action 以 http:// 開頭的表單回報為高風險（CWE-319），因為在其中輸入的一切，包括密碼，都以明文傳送。修正方法是把這些 URL 改為 https:// 或改成相對路徑，並加上 Content-Security-Policy: upgrade-insecure-requests 回應標頭作為保險。自己檢查：curl -s https://your-site/ | grep -Eo "(src|href|action)=.http://[^ >]*"

**它在 robots.txt 和 security.txt 中檢查什麼？**

robots.txt：它取得 /robots.txt，若回傳 HTTP 200 且為文字檔，就讀取前 8000 個字元中的 Disallow 行。包含 admin, internal, private, backup, config, staging, test, api, secret, dev 等字的 Disallow 路徑回報為低風險（CWE-200）：robots.txt 是公開的，只是請守規矩的爬蟲不要造訪，列出這些路徑等於替它們打廣告。請用登入保護它們，並用 noindex 讓頁面不進入搜尋結果。security.txt：它請求 RFC 9116 規定的位置 /.well-known/security.txt，檔案中有 Contact: 行時計為加分。沒有該檔案不扣分。RFC 9116 也要求 Expires: 欄位，掃描不檢查它，所以兩者都要發布，例如 Contact: mailto:security@your-site, Expires: 2027-06-30T23:00:00Z。自己檢查：curl -s https://your-site/.well-known/security.txt

**CAA 檢查看什麼？如何新增 CAA 記錄？**

它透過 Cloudflare 的 DNS-over-HTTPS 查詢你輸入的主機名稱的 CAA 記錄（RFC 8659）。找到記錄則檢查通過，證據中最多顯示 5 筆；一筆都沒有則回報 "No CAA record"，嚴重程度為低，因為此時任何公開憑證授權單位都能為該名稱簽發憑證。CAA 記錄列出你實際使用的 CA，例如 your-site. IN CAA 0 issue "letsencrypt.org"，再加上 0 iodef "mailto:security@your-site" 以接收回報。每個使用的 CA 加一行 issue；若萬用字元憑證要由另一家 CA 簽發，再加一行 issuewild。自行確認：dig CAA your-site

**為什麼掃描 www 或子網域時顯示沒有 CAA、SPF 或 DMARC？**

每項 DNS 檢查都針對你輸入的確切名稱，所以 www.example.com 以 www.example.com 查詢，而不是 example.com，而這三種記錄的繼承方式各不相同。CAA：憑證授權單位在 www.example.com 找不到 CAA 記錄時，會往上查到 example.com 並使用那裡的記錄（RFC 8659 第 3 節），因此子網域上的 "No CAA record" 可能是誤報。DMARC：收件端會改用組織網域的政策，該政策可以用 sp= 為子網域另行設定（RFC 9989，已取代 RFC 7489），因此 _dmarc.www.example.com 沒有記錄時，通常已由 _dmarc.example.com 涵蓋。SPF：沒有繼承（RFC 7208），所以 "No SPF record" 對該名稱是正確的；不寄信的主機名稱可以發布 v=spf1 -all。DNS 查詢失敗也會顯示為沒有記錄。請一併掃描不含 www 的主網域，或用 dig CAA example.com 和 dig TXT _dmarc.example.com 確認

## 更多隱私與安全

- [圖片清除](https://discuvr.org/image-scrub/?hl=zh-hant)

## 常一起使用

- [我的 IP 是什麼](https://discuvr.org/what-is-my-ip/?hl=zh-hant)
- [密碼產生器](https://discuvr.org/password-generator/?hl=zh-hant)

---

Part of Discuvr (https://discuvr.org/): Discuvr is a collection of free, focused tools for day-to-day professional work - office and data utilities, legal and compliance helpers, privacy and security checks, and developer formatters. Every tool has its own page, and most can also be called from ChatGPT or Claude over MCP.
