サービスの指紋情報(バナー)の取得と特定
ターゲットシステム上のアクティブなポートを特定した後、次の段階はそれらのポートで稼働しているサービスやバージョンを正確に特定することです。これを「フィンガープリンティング」と呼びます。単にポートが開いていることを知るだけでなく、具体的なソフトウェアとバージョンを知ることで、既知の脆弱性を特定し、攻撃の成功率を高めることができます。
Netcatを用いたバナーグラビング
Netcatは汎用的なネットワークユーティリティですが、単純な接続テストだけでなく、サービスバナーの取得にも利用できます。多くの古いサーバーやデフォルト設定のサービスは、接続時にソフトウェア名やバージョン情報を自動的に応答します。
以下のコマンドは、ターゲットの特定ポートに接続し、返ってきた初期応答メッセージを表示します。
nc -vn 192.168.1.10 22
このコマンドを実行すると、SSHサービスであれば「SSH-2.0-OpenSSH_...」といったバナーが表示されます。-vは詳細表示、-nはDNS解決を避けるオプションです。同様にFTPやSMTPなどのポートに対しても実行することで、サービスの種類を特定できます。
Pythonによる自動バナー収集スクリプト
手動で接続するのは非効率なため、Pythonのsocketモジュールを使用して自動化します。以下のスクリプトは、指定したIPアドレスのポート範囲をスキャンし、バナーが取得できる場合にのみ表示します。
#!/usr/bin/env python
import socket
import sys
import select
def scan_banners(target_ip, start_port, end_port):
print(f"[*] Scanning {target_ip} from port {start_port} to {end_port}...")
for port in range(start_port, end_port + 1):
try:
# ソケットの作成とタイムアウト設定
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(1)
s.connect((target_ip, port))
# 読み取り可能なデータがあるか確認
ready = select.select([s], [], [], 1)
if ready[0]:
banner = s.recv(1024).decode().strip()
print(f"[+] Port {port}/tcp OPEN: {banner}")
s.close()
except Exception:
pass
if __name__ == "__main__":
if len(sys.argv) != 4:
print("Usage: ./scan_banners.py [IP] [Start Port] [End Port]")
sys.exit(1)
target = sys.argv[1]
p_start = int(sys.argv[2])
p_end = int(sys.argv[3])
scan_banners(target, p_start, p_end)
Nmapと高度なツールによるサービス検出
単純なバナー取得に加え、Nmapのサービス検出機能(-sV)は、プローブパケットを送信し、その応答をデータベースと照合することで、より正確なバージョン特定を行います。
nmap -sV 192.168.1.10 -p 80,443,22
また、AmapやDmitryのようなツールも同様の目的で使用できます。特にAmapは、アプリケーション層のプロトコルを識別するのに特化しており、バナー取得と組み合わせることで効果を発揮します。
オペレーティングシステムの識別
ターゲットのOSを特定することは、カーネルレベルの脆弱性を特定する上で重要です。主にTCP/IPスタックの実装の違い(TTL値、ウィンドウサイズ、フラグの挙動など)を利用して推測を行います。
Scapyを用いたTTL分析
WindowsとLinuxでは、ICMPパケットのデフォルトのTTL(Time To Live)値が異なります。一般的に、Linux系は64、Windows系は128です。Scapyを使用してICMP Echo Requestを送信し、返ってきたパケットのTTLを確認することで、大まかなOS判別が可能です。
from scapy.all import *
target_ip = "192.168.1.10"
# ICMPパケットを送信し、最初の応答を取得
resp = sr1(IP(dst=target_ip)/ICMP(), timeout=2, verbose=0)
if resp:
ttl_value = resp[IP].ttl
if ttl_value <= 64:
print(f"Target {target_ip} is likely Linux/Unix (TTL: {ttl_value})")
else:
print(f"Target {target_ip} is likely Windows (TTL: {ttl_value})")
else:
print("No response received.")
NmapとxProbe2による能動的OS検出
Nmapの-Oオプションは、複雑なプローブパケットのスイートを使用してOSを特定します。これにより、単なるTTL値以上の精度でOSとバージョンを推測できます。同様に、xProbe2もICMPやTCPの挙動の細かな違いを利用してOSを特定しますが、Nmapほど署名データベースが更新されていない場合があります。
nmap -O 192.168.1.10
p0fによる受動的OS識別
p0fは能動的にパケットを送信せず、ネットワーク上を流れるパケットをキャプチャして分析する「受動的」なツールです。これにより、検知されることなくターゲットのOSを特定できます。通常、ARPスプーフィング(Ettercapなどを使用)と組み合わせ、ターゲットのトラフィックを観察可能な状態にしてから実行します。
SNMP情報の収集と分析
Simple Network Management Protocol (SNMP) は、ネットワーク機器を管理するために使用されますが、デフォルトのコミュニティ文字列(パスワードのようなもの)「public」や「private」が設定されているままのデバイスが多く存在します。これらを悪用すると、デバイスの詳細情報やネットワーク構成を取得できます。
onesixtyoneは、コミュニティ文字列を総当たりで試すツールであり、snmpwalkは正しいコミュニティ文字列が分かった後に、MIBツリーを走査して詳細情報を取得するために使用されます。
# コミュニティ文字列の推測
onesixtyone 192.168.1.1 public
# 情報の取得
snmpwalk -c public -v 2c 192.168.1.1 iso.3.6.1.2.1.1
ファイアウォールとパケットフィルタの検出
ファイアウォールの存在と設定を特定することは、スキャン結果の解釈や回避策の検討に不可欠です。特にステートフルインスペクションを行うファイアウォールは、接続の状態に基づいてパケットをフィルタリングします。
Scapyによるステートフル検出のロジック
通常、接続を開始するSYNパケットをドロップし、既存の接続に関連するACKパケットを受け入れる(またはRSTで応答する)場合、ステートフルなフィルタリングが行われている可能性があります。Scapyを使用して、SYNパケットとACKパケットを個別に送信し、その応答の違いを分析することでこれを検出します。
ロジックの例:
- SYNに応答なし、ACKにRST応答:インバウンド接続はブロックされているが、アウトバウンドは許可されている。
- SYNとACKの両方にRST応答:フィルタリングなし(ポートは閉じている)。
- 両方に応答なし:ステートレスなフィルタリング、またはホストダウン。
NmapのACKスキャン
Nmapの-sAオプション(ACKスキャン)は、ファイアウォールのルールセットを識別するために使用されます。このスキャンはTCP接続を確立しようとしないため、ステートフルファイアウォールを通過しやすく、ポートが「フィルタリングされている」か「非フィルタリング」かを判別するのに役立ちます。
nmap -sA 192.168.1.10
脆弱性スキャンの実践
サービスとOSの特定が完了したら、既知の脆弱性の存在を自動的にスキャンします。これにより、手動での調査時間を大幅に短縮できます。
Nmapスクリプトエンジン(NSE)による脆弱性検出
NSEには、多数の脆弱性検出スクリプトが含まれています。カテゴリが「vuln」であるスクリプトを使用して、ターゲットシステム上の既知の脆弱性(例:MS08-067、Heartbleedなど)をチェックできます。
nmap --script=vuln 192.168.1.10
特定のスクリプトを実行するには、--scriptオプションでスクリプト名を指定します。
Metasploit Frameworkの補助モジュール
Metasploitには、特定のサービスや脆弱性をスキャンするための補助(auxiliary)モジュールが多数用意されています。これらはMSFconsoleから検索して実行します。例えば、SMBの脆弱性をスキャンするモジュールなどがあります。
msfconsole
use auxiliary/scanner/smb/smb_version
set RHOSTS 192.168.1.0/24
run
Nessusによる包括的なスキャン
Nessusは業界標準の脆弱性スキャナです。Webインターフェースからスキャンポリシー(どのチェックを行うか、認証情報を使うかなど)を作成し、ターゲットを指定してスキャンを実行します。また、CUIのnessuscmdを使用して、特定のプラグインIDを指定した単体チェックを行うことも可能です。
/opt/nessus/bin/nessuscmd -i 19506 192.168.1.10
脆弱性の検証:HTTPとICMP
スキャナで脆弱性が検出された場合、実際にエクスプロイト可能かを確認するために、単純な検証を行うことがあります。
HTTPリスナーによる検証
リモートコード実行(RCE)の脆弱性がある場合、ターゲットに対して攻撃コードを実行し、攻撃者のサーバーへHTTPリクエストを送らせることで、実行権限を確認できます。以下のPythonスクリプトは、単純なHTTPサーバーとして機能し、受信したリクエストの送信元IPを記録します。
#!/usr/bin/env python
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("0.0.0.0", 8080))
server.listen(5)
print("[*] Listening on port 8080 for incoming connections...")
while True:
client, addr = server.accept()
print(f"[+] Connection received from: {addr[0]}")
request = client.recv(1024)
client.close()
ICMPによる検証
HTTPがブロックされている環境では、ターゲットに攻撃者のIPアドレスに対してping(ICMP Echo Request)を実行させ、それを受信することで検証します。Scapyを使用して特定のIPからのICMPパケットを監視し、ターゲットからPingが返ってきた場合、コマンド実行が成功したと判断できます。