💡 幹嘛要做 Banner Grabbing?
在偵查的時候,知道某個 Port 有沒有開還不夠,通常還會去看背後是什麼服務、版本是多少。
Banner Grabbing 就是透過連線到該服務,讀取它回傳的第一段訊息(Banner),來識別服務跟版本。
常見的一些應用:
- 判斷 HTTP Server 是 Apache、Nginx 還是其他
- 確認 FTP、SMTP 等服務的版本
- 收集後續滲透所需的目標環境資訊
🎯 大綱
- 用 Ruby 連線後嘗試讀取服務回應
- 設定讀取 Timeout,避免卡住
- 搭配多執行緒加速
📚 知識點
socket = TCPSocket.new(ip, port)— 建立 TCP 連線socket.recv(1024)— 讀取 1024 bytes 回應socket.close— 關閉連線rescue捕捉例外(拒絕、逾時)Timeout.timeout(sec) { … }— 限制等待時間
💻 實作
require 'socket'
require 'timeout'
ip = '127.0.0.1'
ports = [21, 22, 25, 80, 443] # 常見有 Banner 的服務
ports.each do |port|
begin
Timeout.timeout(2) do
socket = TCPSocket.new(ip, port)
banner = socket.recv(1024) # 嘗試讀取回應
puts "Port #{port} is open - Banner: #{banner.strip}"
socket.close
end
rescue Errno::ECONNREFUSED
puts "Port #{port} is closed"
rescue Errno::ETIMEDOUT, Timeout::Error
puts "Port #{port} connection timed out"
rescue => e
puts "Error on port #{port}: #{e.class} - #{e.message}"
end
end
🚀 指令
- 建立檔案
banner_grabber.rb - 貼上程式碼
- 執行:
ruby banner_grabber.rb
- 如果目標在某個 Port 有服務,會看到類似:
Port 80 is open - Banner: HTTP/1.1 400 Bad Request
Server: nginx/1.18.0 (Ubuntu)
⚙️ 補充:多執行緒 Banner Grabbing
require 'socket'
require 'timeout'
ip = '127.0.0.1'
ports = (1..1024).to_a
threads = ports.map do |port|
Thread.new(port) do |p|
begin
Timeout.timeout(2) do
socket = TCPSocket.new(ip, p)
banner = socket.recv(1024)
puts "[+] Port #{p} is open - Banner: #{banner.strip}" unless banner.empty?
socket.close
end
rescue Errno::ECONNREFUSED
# 關閉的 Port 不輸出,避免刷屏
rescue Timeout::Error, Errno::ETIMEDOUT
# 超時忽略
end
end
end
threads.each(&:join)
這樣可以同時抓取多個 Port 的 Banner,速度會比單執行緒快很多。
這邊用一台HackTheBox的機器來實作:
