Nmapの概要 (ESP)

Reading time: 28 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする
nmap -sV -sC -O -n -oA nmapscan 192.168.0.1/24

パラメータ

スキャンする IP

  • <ip>,<net/mask>: IP を直接指定します
  • -iL <ips_file>: IP リストファイル
  • -iR <number>: ランダムな IP の数。--exclude <Ips>--excludefile <file> で除外できます。

機器の検出

デフォルトでは Nmap は次からなる検出フェーズを実行します: -PA80 -PS443 -PE -PP

  • -sL: 非侵入型で、名前解決のために DNS リクエストを行いターゲットを一覧化します。例えば www.prueba.es/24 の全 IP が対象かどうかを知るのに便利です。
  • -Pn: No ping。すべてがアクティブであると分かっている場合に有用です(そうでないと時間を大きく浪費する可能性があり、また非アクティブと誤検出する偽陰性を生むこともあります)。検出フェーズを無効にします。
  • -sn : No port scan。偵察(reconnaissance)フェーズ完了後にポートスキャンを行いません。比較的ステルスで、小規模なネットワーク探索に向きます。権限がある場合は ACK (-PA) を 80 に、SYN(-PS) を 443 に送り、echo と Timestamp リクエストを送ります。権限がない場合は常に接続を完了します。ターゲットがネットワークの場合は ARP(-PR) のみを使用します。他のオプションと併用した場合は、他オプションのパケットだけが送られます。
  • -PR: Ping ARP。自ネットワーク内のホスト解析時にデフォルトで使用され、ping より速いです。ARP パケットを送信したくない場合は --send-ip を使用します。
  • -PS <ports>: SYN パケットを送信し、相手が SYN/ACK で応答したら open(接続を終了させるために RST で応答することが多い)、RST で応答したら closed、応答がなければ unreachable と判断します。権限がない場合はフルコネクションが自動的に使われます。ポート指定がなければデフォルトで 80 に送ります。
  • -PA <ports>: 前述と同様ですが ACK を使います。両方を組み合わせると精度が上がります。
  • -PU <ports>: 逆の目的で、通常閉じていることが期待されるポートへ送ります。一部のファイアウォールは TCP 接続のみをチェックします。closed の場合は port unreachable、別の ICMP で応答されたり無応答であれば destination unreachable とされます。
  • -PE, -PP, -PM : ICMP PING(echo replay, timestamp, addresmask)。ターゲットが生きているかを確認するために送られます。
  • -PY<ports>: デフォルトで 80 に SCTP INIT プローブを送信します。INIT-ACK(open)や ABORT(closed)、無応答や ICMP unreachable(inactive)で応答される可能性があります。
  • -PO <protocols>: ヘッダにプロトコルを指定します。デフォルトは 1(ICMP), 2(IGMP), 4(Encap IP)。ICMP、IGMP、TCP(6)、UDP(17) はプロトコルヘッダを送信し、それ以外は IP ヘッダのみ送ります。ヘッダの不正により Protocol unreachable や同プロトコルの応答が返ることがあり、それで up を判断します。
  • -n: DNS 未使用
  • -R: 常に DNS を使う

ポートスキャン手法

  • -sS: 接続を完了させないため痕跡が残りにくい(権限が必要)。デフォルトで使用されます。
  • -sT: 接続を完了させるため痕跡が残りますが、権限不要で確実に使えます(デフォルトは権限なし)。
  • -sU: UDP 用で遅め。主に DNS(53), SNMP(161,162), DHCP(67,68) など。応答は open(reply)、closed(port unreachable)、filtered(別の ICMP)、open/filtered(無応答)。open/filtered の場合、-sV が多数のリクエストを送りバージョン検出を試み、真の状態を検出できることがあります。時間が大幅に増えます。
  • -sY: SCTP のスキャン。接続が確立されないためログが残らず、-PY と同様に動作します。
  • -sN,-sX,-sF: Null, Fin, Xmas。いくつかのファイアウォールをすり抜け情報を得られる場合があります。標準準拠のマシンは SYN/RST/ACK のいずれも立っていない要求に対し RST で応答するはず、という点を利用します:open/filtered(無応答)、closed(RST)、filtered(ICMP unreachable)。Windows, Cisco, BSDI, OS/400 では信頼性が低い。Unix 系では有効なことが多いです。
  • -sM: Maimon スキャン。FIN と ACK を送ります。BSD 向けでしたが現在は全て closed を返すことが多いです。
  • -sA, sW: ACK と Window スキャン。ファイアウォールの検出に使い、ポートがフィルタされているかどうかを判定します。-sW は open/closed を区別できます(open は RST で window 値が 0 以外、closed は RST で window = 0、filtered は ICMP unreachable または無応答)。すべてのホストがこの挙動をするわけではないので、すべて closed ならこの手法は機能していない可能性があり、少数 open なら機能していると判断できます。
  • -sI: Idle scan(ゾンビスキャン)。アクティブなファイアウォールがあるが特定の IP にはフィルタされない場合や匿名性を保ちたい場合にゾンビを利用してスキャンします(全ポート対象)。ゾンビ候補の探索には ipidseq スクリプトや exploit auxiliary/scanner/ip/ipidseq が使えます。このスキャンは IPID 値に基づきます。
  • --badsum: チェックサムを不正にして送信します。本来はホストがパケットを破棄しますが、ファイアウォールが何らかの応答を返すことがあり、ファイアウォールの検出に使われます。
  • -sZ: "Weird" な SCTP スキャナー。cookie echo フラグメントでプローブを送ると、open は破棄、closed は ABORT で応答するはずです。INIT が通らないファイアウォールをすり抜けることがありますが、filtered と open を区別できない欠点があります。
  • -sO: IP プロトコルスキャン。不正または空のヘッダを送り、場合によりプロトコルすら判別できないことがあります。ICMP protocol unreachable が来れば closed、port unreachable が来れば open、別のエラーなら filtered、無応答なら open|filtered。
  • -b <server>: FTP bounce。別ホスト経由でスキャンを行うために使用します。別マシンの FTP に接続して、そこからターゲットのポートへファイル送信を指示し、応答から開閉を判断します。[<user>:<password>@]<server>[:<port>] ほとんどの FTP サーバはこの機能を無効にしているため実用性は低いです。

フォーカス(分析)

-p: スキャンするポートを指定します。全 65,535 ポートを選ぶには -p- または -p all。Nmap は人気度に基づく内部分類を持ち、デフォルトでは上位 1000 ポートを使用します。-F(高速スキャン)で上位 100 をスキャンします。--top-ports で上位ポート数を指定できます(1〜65,535)。ポートはランダム順にチェックされます。これを防ぐには -r を使います。特定のポートも選択可能です: 20-30,80,443,1024-(1024 以降を意味)。プロトコルでグループ化も可能: U:53,T:21-25,80,139,S:9。Nmap の popular ports 内の範囲を指定することもできます: -p [-1024] は nmap-services に含まれるポートのうち 1024 までをスキャンします。--port-ratio は 0〜1 の比率で最も一般的なポートのみを解析します。

-sV バージョン検出。強度は 0〜9 で調整可能、デフォルトは 7。

--version-intensity 強度を調整します。値を小さくするともっとも確からしいプローブのみを送るので、UDP スキャン時間を大幅に短縮できます。

-O OS 検出

--osscan-limit ホストごとに正しくスキャンするには少なくとも 1 つの open と 1 つの closed ポートが必要です。この条件が満たされない場合、これを有効にすると OS 予測を試みません(時間節約)。

--osscan-guess OS 検出が確実でないときにより多くの推測を試みます。

スクリプト

--script |||[,...]

デフォルトスクリプトを使うには -sC または --script=default

利用可能なタイプ: auth, broadcast, default, discovery, dos, exploit, external, fuzzer, intrusive, malware, safe, version, vuln

  • Auth: 利用可能な認証スクリプトをすべて実行します
  • Default: 基本的なデフォルトスクリプトを実行します
  • Discovery: ターゲットから情報を取得します
  • External: 外部リソースを利用するスクリプト
  • Intrusive: ターゲットに対して侵襲的と見なされるスクリプトを使用します
  • Malware: マルウェアやバックドアによって開かれた接続をチェックします
  • Safe: 非侵襲的なスクリプトのみを実行します
  • Vuln: よく知られた脆弱性を発見します
  • All: 利用可能な NSE スクリプトをすべて実行します

スクリプト検索:

nmap --script-help="http-*" -> http- で始まるもの

nmap --script-help="not intrusive" -> intrusive を除くすべて

nmap --script-help="default or safe" -> いずれか(または両方)に属するもの

nmap --script-help="default and safe" -> 両方に属するもの

nmap --script-help="(default or safe or intrusive) and not http-*"

--script-args =,={=},={,}

--script-args-file

--script-help ||||all[,...]

--script-trace ---> スクリプトの進行状況に関する情報を提供します

--script-updatedb

スクリプトを使うには: nmap --script Script_Name target と入力します --> スクリプトとスキャナの両方が実行されるため、スキャナオプションも追加可能です。"safe=1" を加えると安全なスクリプトのみを実行します。

時間制御

Nmap は秒、分、ms 単位で時間を指定できます: --host-timeout 引数 900000ms, 900, 900s, および 15m は同じ意味です。

Nmap はスキャン対象ホストをグループ分けしてブロックごとに解析します。1 ブロックの解析が完了するまで次のブロックに進まず、ユーザにはそのブロックが解析されるまで更新が届きません。これにより大きなグループを使う方が効率的です。デフォルトではクラス C で 256 を使用します。

これは --min-hostgroup --max-hostgroup で変更できます(並列スキャンのグループサイズを調整)。

並列スキャナ数は制御できますが、Nmap はネットワーク状態に基づいて自動制御するため、あまり触らない方がよいです: --min-parallelism ; --max-parallelism

RTT タイムアウトを変更できますが通常は不要です: --min-rtt-timeout , --max-rtt-timeout , --initial-rtt-timeout

試行回数を変更できます: --max-retries

ホストあたりのスキャン時間を変更できます: --host-timeout

各テスト間の遅延で速度を落とせます: --scan-delay ; --max-scan-delay

1 秒あたりのパケット数を変更できます: --min-rate ; --max-rate

filtered や closed のポートは応答が遅いことが多いです。open のみに注目したい場合は高速化のために: --defeat-rst-ratelimit

Nmap の侵襲性を定義するには: -T paranoid|sneaky|polite|normal|aggressive|insane

-T (0-1)

-T0 --> 1 ポートずつスキャンし次のポートまで 5 分待機

-T1 と T2 --> 似ていますが、それぞれ 15 秒および 0.4 秒の待機

-T3 --> デフォルト動作、並列スキャンを含む

-T4 --> --max-rtt-timeout 1250ms --min-rtt-timeout 100ms --initial-rtt-timeout 500ms --max-retries 6 --max-scan-delay 10ms

-T5 --> --max-rtt-timeout 300ms --min-rtt-timeout 50ms --initial-rtt-timeout 250ms --max-retries 2 --host-timeout 15m --max-scan-delay 5ms

Firewall/IDS

ポートへのアクセスを阻止したりパケットを解析します。

-f パケットをフラグメント化します。デフォルトではヘッダ後 8 バイトごとに分割します。サイズを指定するには ..mtu を使います(この場合 -f は使わないでください)。オフセットは 8 の倍数でなければなりません。Version scanners と scripts はフラグメンテーションをサポートしません

-D decoy1,decoy2,ME Nmap はスキャン元を他の IP に偽装して送信します。リストに ME を入れると自分の位置をその中に挿入します。完全にマスクするには前に 5~6 個の偽装を置くのが良いです。RND: でランダム IP を生成できます。TCP のバージョン検出(接続を伴わないもの)には動作しないことがあります。内部ネットワークにいる場合はアクティブな IP を使う方がよいです(さもないと唯一のアクティブが自分であることが露見しやすいため)。

ランダム IP を使う例: nmap -D RND:10 Target_IP

-S IP Nmap があなたの IP を捕捉できない場合に指定します。別のホストがスキャンしているように見せる用途にも使えます。

-e インターフェース選択

多くの管理者は運用上の理由で特定のポートをすべて通すルールを作ることがあります(例: DNS, FTP)。これを悪用するために Nmap は --source-port (-g と同等)を提供します。

--data 16 進データ送信例: --data 0xdeadbeef や --data \xCA\xFE\x09

--data-string 通常文字列送信例: --data-string "Scan conducted by Security Ops, extension 7192"

--data-length Nmap がヘッダのみ送る場合に追加でランダムなバイト数を付加します

IP パケットのオプションを完全に設定するには --ip-options

送信/受信パケットのオプションを見たい場合は --packet-trace を指定します。IP options を使った例については http://seclists.org/nmap-dev/2006/q3/52 を参照してください。

--ttl

--randomize-hosts 攻撃を目立たなくする

--spoof-mac <MAC address, prefix, or vendor name> MAC を変更します。例: Apple, 0, 01:02:03:04:05:06, deadbeefcafe, 0020F2, Cisco

--proxies プロキシを使います。プロキシは Nmap が要求するほど多くの接続を維持できない場合があるため、並列性を調整する必要があるかもしれません: --max-parallelism

-sP ARP による自ネットワーク内ホスト検出

管理者が特定ポート(例: 20,53,67)からのパケットをすべて通すルールを作ることがあります。その場合 Nmap にそのポートを送信元として使わせることができます: nmap --source-port 53 IP

出力

-oN file 通常出力

-oX file XML 出力

-oS file Script kiddies 形式出力

-oG file Greppable 出力

-oA file -oS を除くすべて

-v level 冗長度

-d level デバッグレベル

--reason host と state の理由を表示

--stats-every time 指定時間ごとの進捗報告

--packet-trace 送出パケットを確認、フィルタ指定可(例: --version-trace, --script-trace)

--open open, open|filtered, unfiltered を表示

--resume file サマリを出力して再開

その他

-6 IPv6 を有効にする

-A は -O -sV -sC --traceroute と同等

実行時

Nmap 実行中に次の操作でオプションを変更できます:

v / V 冗長度を上げる / 下げる

d / D デバッグレベルを上げる / 下げる

p / P パケットトレースのオン/オフ

? ランタイムインタラクションのヘルプ表示

Vulscan

Nmap スクリプトで、得られたサービスのバージョン情報をオフライン DB(他の大規模 DB から取得)と照合して既知の脆弱性を返します。

使用する DB:

  1. Scipvuldb.csv | http://www.scip.ch/en/?vuldb
  2. Cve.csv | http://cve.mitre.org
  3. Osvdb.csv | http://www.osvdb.org
  4. Securityfocus.csv | http://www.securityfocus.com/bid/
  5. Securitytracker.csv | http://www.securitytracker.com
  6. Xforce.csv | http://xforce.iss.net
  7. Exploitdb.csv | http://www.exploit-db.com
  8. Openvas.csv | http://www.openvas.org

Nmap フォルダへダウンロードとインストール:

wget http://www.computec.ch/projekte/vulscan/download/nmap_nse_vulscan-2.0.tar.gz && tar -czvf nmap_nse_vulscan-2.0.tar.gz vulscan/ && sudo cp -r vulscan/ /usr/share/nmap/scripts/

さらに DB パッケージをダウンロードして /usr/share/nmap/scripts/vulscan/ に追加する必要があります。

使用例:

すべての DB を使う: sudo nmap -sV --script=vulscan HOST_TO_SCAN

特定 DB を使う: sudo nmap -sV --script=vulscan --script-args vulscandb=cve.csv HOST_TO_SCAN

Nmap サービススキャンを x16 で高速化

to this post によると、/usr/share/nmap/nmap-service-probes 内のすべての totalwaitms 値を 300 に、tcpwrappedms200 に変更すると nmap のサービス解析を高速化できます。

さらに、特定のプローブに servicewaitms が定義されていない場合はデフォルトで 5000 が使われます。したがって、各プローブに値を追加するか、nmap を自分でコンパイルして service_scan.h 内のデフォルト値を変更することができます。

/usr/share/nmap/nmap-service-probes 内の totalwaitmstcpwrappedms の値をまったく変更したくない場合は、parsing code を編集してこれらの値を無視するようにできます。

制限環境向けに静的リンクされた Nmap をビルド

ハード化された環境や最小限の Linux(コンテナ、アプライアンス)では、動的リンクされた Nmap バイナリがランタイムローダや共有ライブラリ(例: /lib64/ld-linux-x86-64.so.2, libc.so)不足で動作しないことがあります。静的リンクされた Nmap をビルドし、NSE データをバイナリに同梱すれば、システムパッケージをインストールせずに実行できます。

概略手順

  • Docker でクリーンな amd64 Ubuntu ビルダーを使う
  • OpenSSL と PCRE2 を静的ライブラリとしてビルドする
  • libpcap/libdnet を同梱して動的依存を避け、Nmap を静的リンクでビルドする
  • NSE スクリプトとデータディレクトリをバイナリに同梱する

ターゲットアーキテクチャの確認(例)

bash
uname -a
# If building from macOS/ARM/etc., pin the builder arch:
docker run --rm --platform=linux/amd64 -v "$(pwd)":/out -w /tmp ubuntu:22.04 bash -lc 'echo ok'

ステップ1 — ツールチェーンを準備する

bash
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
apt-get update && apt-get install -y --no-install-recommends \
build-essential ca-certificates curl bzip2 xz-utils pkg-config perl python3 file git \
automake autoconf libtool m4 zlib1g-dev

ステップ 2 — OpenSSL (1.1.1w) を静的にビルド

bash
OSSL="1.1.1w"
curl -fsSLO "https://www.openssl.org/source/openssl-$OSSL.tar.gz"
tar xzf "openssl-$OSSL.tar.gz" && cd "openssl-$OSSL"
./Configure no-shared no-zlib linux-x86_64 -static --prefix=/opt/ossl
make -j"$(nproc)" && make install_sw
cd /tmp

ステップ3 — 静的 PCRE2 (10.43) のビルド

bash
PCRE2=10.43
curl -fsSLO "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-$PCRE2/pcre2-$PCRE2.tar.bz2"
tar xjf "pcre2-$PCRE2.tar.bz2" && cd "pcre2-$PCRE2"
./configure --disable-shared --enable-static --prefix=/opt/pcre2
make -j"$(nproc)" && make install
cd /tmp

ステップ 4 — 静的な Nmap をビルドする (7.98)

bash
NMAP=7.98
curl -fsSLO "https://nmap.org/dist/nmap-$NMAP.tar.bz2"
tar xjf "nmap-$NMAP.tar.bz2" && cd "nmap-$NMAP"
export CPPFLAGS="-I/opt/ossl/include -I/opt/pcre2/include"
export LDFLAGS="-L/opt/ossl/lib -L/opt/pcre2/lib -static -static-libstdc++ -static-libgcc"
export LIBS="-lpcre2-8 -ldl -lpthread -lz"
./configure \
--with-openssl=/opt/ossl \
--with-libpcre=/opt/pcre2 \
--with-libpcap=included \
--with-libdnet=included \
--without-zenmap --without-ndiff --without-nmap-update
# Avoid building shared libpcap by accident
sed -i -e "s/^shared: /shared: #/" libpcap/Makefile || true
make -j1 V=1 nmap
strip nmap

要点

  • -static, -static-libstdc++, -static-libgcc は静的リンクを強制します。
  • --with-libpcap=included/--with-libdnet=included を使うとシステム共有ライブラリの使用を避けられます。
  • sed の調整は、存在する場合に共有 libpcap ターゲットを無効化します。

Step 5 — バイナリとNSEデータをバンドルする

bash
mkdir -p /out/nmap-bundle/nmap-data
cp nmap /out/nmap-bundle/nmap-linux-amd64-static
cp -r scripts nselib /out/nmap-bundle/nmap-data/
cp nse_main.lua nmap-services nmap-protocols nmap-service-probes \
nmap-mac-prefixes nmap-os-db nmap-payloads nmap-rpc \
/out/nmap-bundle/nmap-data/ 2>/dev/null || true

tar -C /out -czf /out/nmap-linux-amd64-static-bundle.tar.gz nmap-bundle

検証および運用ノート

  • アーティファクトに対してfileを使い、静的にリンクされていることを確認する。
  • Nmapがインストールされていないホストでもスクリプトの互換性を保つため、NSEデータをbinaryと一緒に保持する。
  • 静的なbinaryであっても、AppArmor/seccomp/SELinuxによって実行がブロックされる可能性がある。DNSやegressは引き続き機能する必要がある。
  • Deterministic buildsは、不透明な“static” binariesをダウンロードするよりもサプライチェーンのリスクを低減する。

One-liner (Dockerized)

ビルド、バンドル、アーティファクト情報を出力する
bash
docker run --rm --platform=linux/amd64 -v "$(pwd)":/out -w /tmp ubuntu:22.04 bash -lc '
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
apt-get update && apt-get install -y --no-install-recommends \
build-essential ca-certificates curl bzip2 xz-utils pkg-config perl python3 file git \
automake autoconf libtool m4 zlib1g-dev

OSSL="1.1.1w"; curl -fsSLO "https://www.openssl.org/source/openssl-$OSSL.tar.gz" \
&& tar xzf "openssl-$OSSL.tar.gz" && cd "openssl-$OSSL" \
&& ./Configure no-shared no-zlib linux-x86_64 -static --prefix=/opt/ossl \
&& make -j"$(nproc)" && make install_sw && cd /tmp

PCRE2=10.43; curl -fsSLO "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-$PCRE2/pcre2-$PCRE2.tar.bz2" \
&& tar xjf "pcre2-$PCRE2.tar.bz2" && cd "pcre2-$PCRE2" \
&& ./configure --disable-shared --enable-static --prefix=/opt/pcre2 \
&& make -j"$(nproc)" && make install && cd /tmp

NMAP=7.98; curl -fsSLO "https://nmap.org/dist/nmap-$NMAP.tar.bz2" \
&& tar xjf "nmap-$NMAP.tar.bz2" && cd "nmap-$NMAP" \
&& export CPPFLAGS="-I/opt/ossl/include -I/opt/pcre2/include" \
&& export LDFLAGS="-L/opt/ossl/lib -L/opt/pcre2/lib -static -static-libstdc++ -static-libgcc" \
&& export LIBS="-lpcre2-8 -ldl -lpthread -lz" \
&& ./configure --with-openssl=/opt/ossl --with-libpcre=/opt/pcre2 --with-libpcap=included --with-libdnet=included --without-zenmap --without-ndiff --without-nmap-update \
&& sed -i -e "s/^shared: /shared: #/" libpcap/Makefile || true \
&& make -j1 V=1 nmap && strip nmap

mkdir -p /out/nmap-bundle/nmap-data \
&& cp nmap /out/nmap-bundle/nmap-linux-amd64-static \
&& cp -r scripts nselib /out/nmap-bundle/nmap-data/ \
&& cp nse_main.lua nmap-services nmap-protocols nmap-service-probes nmap-mac-prefixes nmap-os-db nmap-payloads nmap-rpc /out/nmap-bundle/nmap-data/ 2>/dev/null || true \
&& tar -C /out -czf /out/nmap-linux-amd64-static-bundle.tar.gz nmap-bundle \
&& echo "===== OUTPUT ====="; ls -lah /out; echo "===== FILE TYPE ====="; file /out/nmap-bundle/nmap-linux-amd64-static || true
'

参考資料

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする