相信有玩 CTF 的玩家或是剛學習滲透測試的人在一開始打靶機的時候一定碰過這個玩意兒
在打靶機的時候有時候起手式八九不離十就是 nmap 開掃,掃出來看到 443、3306 這些熟悉的 Port Number,很容易直覺認為 443 就是 HTTPS、3306 就是 MySQL。
於是決定直接開打、拿到 Flag,帥氣地結束這回合。但是……
我們先來看看 RFC 7605 怎麼看待 port 跟協定這件事?
RFC 7605 的 7.1 Is a port number assignment necessary?
RFC 7605 的 7.4 Support for Security
這些事情直接證明了,服務不一定使用預設 Port,因此不能只依 Port 號碼判斷實際運行的服務。
如果看到 443 就覺得那是 https 的話這個觀念會讓人在往後滲透測試的道路中吃盡苦頭。
要怎麼樣才可以蒐集到服務的資訊呢?我們必須先知道兩個觀念:Server-first 跟 Client-first

TCP 三向交握完成後,連線雙方面臨一個問題:誰先送出第一筆應用層資料?
這取決於協議的設計目的:
下面我用 AI 建立一個簡單的 lab 來說明服務枚舉的內容:
警告:請在合法靶場進行訓練!
| 主機 IP | 說明 |
|---|---|
| 172.16.12.181 | 刺探主機 |
| 172.16.12.182 | 靶機 |
目的:找到靶機上面這 5 個 Port 實際運行的服務
nmap -Pn -p- --min-rate 2000 -oA scan01 172.16.12.182

for p in 80 2222 3306 8080 8443; do
printf "%-6s " $p
timeout 3 bash -c "exec 3<>/dev/tcp/172.16.12.182/$p; IFS= read -r l <&3; echo \"\$l\"" \
2>/dev/null || echo "(沉默)"
done
解釋一下這個腳本的指令意思:
-for p in 80 2222 3306 8080 8443; do
我用一個 for 迴圈來做一個情資的驗證,先把這 5 個 port 的範圍給一個迴圈變數 p
-printf "%-6s " $p
我會讓 port 的號碼顯示出來,並用字串格式寬度為 6 個字元隔開輸出,port 靠左邊對齊
-timeout 3 bash -c
讓 bash -c "某個指令" 執行,但最多只能跑 3 秒。
-exec 3<>/dev/tcp/172.16.12.182/$p;
建立一條 TCP 連線到 172.16.12.182:$p,然後把這條連線綁到 File Descriptor 3。
-IFS= read -r l <&3
透過 read 這個指令將擷取的 banner 寫到變數 l 裡面,IFS= 用來避免 read 依照預設的空白字元規則處理輸入內容,盡可能保留原始資料。
-echo \"\$l\"" 2>/dev/null || echo "(沉默)"
不要顯示錯誤資訊,如果沒資料就輸出(沉默)
以下為輸出結果:
可以看到 2222 port 這邊顯示的結果是 SSH 的版本資訊,這邊可以初步證明大家常用的 port 號不一定是某一個服務。
ssh 這個服務這樣看也可以初步理解它是屬於 Server-first 的類型。
好,剩下四個我們也要揪出來。我們明天再討論找出剩下四個 port 的服務方式