はじめに
ペネトレーションテストやレッドチーミングにおいて、公開されているサーバーを侵害した際、そこから直接攻撃マシンでは到達できない内部ネットワークへアクセスできることがよくあります。これらの内部システムを攻撃するには、侵害したサーバーを経由してトラフィックをルーティングする手段が必要です。この手法は「ピボット(Pivoting)」と呼ばれます。
ピボットとは、視点を変えることです。元のマシンのネットワーク位置からテストするだけでなく、侵害したホストを新しい観測点およびアクセスポイントとして利用します。
最も強力で一般的なピボット手法の一つに、SSH ダイナミックポートフォワーディングを使用して SOCKS プロキシを作成し、それを proxychains というツールと組み合わせる方法があります。この組み合わせにより、Nmap、Nikto、Metasploit などのほぼすべての外部ネットワークツールを、侵害したホスト経由でシームレスにルーティングできるようになります。
この実験では、Docker コンテナ上で実行されている専用のピボットホストへの SSH アクセス権があるシナリオをシミュレートします。同じプライベート Docker ネットワーク上の別のコンテナが、隠れた内部 Web サービスをホストしています。このサービスは LabEx VM に直接公開されていないため、SSH ピボットホストを経由してアクセスする必要があります。SSH ダイナミックポートフォワーディングの設定方法、proxychains の構成方法、そしてそれを使用してピボットホスト経由で隠れたサービスにアクセスする方法を学びます。
SSH ダイナミックポートフォワーディング (-D) の設定
このステップでは、コンテナ化されたピボットホストへの SSH 接続を確立し、ローカル SOCKS プロキシを作成します。
ダイナミックポートフォワーディングを使用すると、攻撃マシン上のローカルポートを指定できます。SSH クライアントはこのポートでリッスンし、アプリケーションが接続すると、その接続は安全な SSH チャネル経由で SSH サーバーに転送されます。SSH サーバーはプロキシとして機能し、トラフィックを最終的な宛先に転送します。
これは、SOCKS プロキシが単一のトンネルを通じて多くの異なる宛先リクエストを運ぶことができるため、単一ポートフォワーディングよりも柔軟です。
これを設定するには、SSH コマンドで -D フラグを使用します。また、接続をバックグラウンドでスムーズに実行するために、他のいくつかのフラグも使用します。
この環境では、~/project/pivot_key に秘密鍵が作成されており、ピボットホストの SSH サービスがローカルポート 2222 に公開されています。ターミナルで以下のコマンドを実行し、ローカルポート 9050 で SOCKS プロキシを作成します。
ssh -f -D 9050 -q -C -N \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-i ~/project/pivot_key -p 2222 pivot@127.0.0.1
このコマンドで使用されているフラグを解説します。-D 9050 フラグはダイナミックポートフォワーディングを指定し、ローカルのリッスンポートを 9050 に設定します。-q フラグはクワイエットモードで、警告や診断メッセージを抑制します。-C フラグはすべてのデータの圧縮を要求し、接続を高速化します。-N フラグは SSH に対してリモートコマンドを実行しないよう指示するもので、ポート転送のみを行う場合に便利です。-f フラグは認証後に SSH クライアントをバックグラウンドに送るため、同じターミナルセッションを使い続けることができます。-o StrictHostKeyChecking=no および -o UserKnownHostsFile=/dev/null オプションは、初回接続時のホストキー確認プロンプトが実験のワークフローを中断するのを防ぎます。-i フラグは使用する秘密鍵を指定し、-p 2222 は LabEx VM のデフォルト SSH サービスではなく、ピボットホストコンテナに接続するよう指示します。
コマンド実行後、ss コマンドを使用してポートが開いてリッスンしていることを確認できます。
ss -tuln | grep 9050
以下のような出力が表示されれば、マシンがポート 9050 でリッスンしていることがわかります。
tcp LISTEN 0 128 127.0.0.1:9050 0.0.0.0:*
tcp LISTEN 0 128 [::1]:9050 [::]:*
Proxychains の設定 (/etc/proxychains.conf)
このステップでは、proxychains の設定を確認します。
ポート 9050 で SOCKS プロキシが実行されていますが、Nmap などのほとんどのコマンドラインツールは、トラフィックを SOCKS プロキシ経由でルーティングする方法をネイティブには知りません。ここで proxychains の出番です。これは、特定のアプリケーションが行う TCP 接続を強制的にプロキシ経由にするツールです。
実際には、proxychains は単一の手動テストから、多くのツールにわたる再利用可能なオペレーターワークフローへとトンネルを拡張する役割を果たします。
proxychains の設定ファイルは /etc/proxychains4.conf にあります。この実験では、プロキシエントリは 127.0.0.1 ポート 9050 の SOCKS5 プロキシを指す必要があり、これは先ほど作成した SSH ダイナミックポートフォワーディングと一致します。
設定ファイルの末尾を表示して、この設定を確認しましょう。tail コマンドを使用してファイルの最後の 10 行を表示します。
tail -n 10 /etc/proxychains4.conf
以下のような出力が表示されるはずです。
[ProxyList]
## add proxy here ...
## meanwile
## defaults set to "tor"
socks5 127.0.0.1 9050
[ProxyList] セクションでプロキシが定義されます。socks5 127.0.0.1 9050 という行は、proxychains に対してトラフィックをローカルポート 9050 経由でルーティングするよう指示しています。SSH の -D コマンドでこのポートにプロキシを作成したため、プロトコルタイプを更新した後は追加の設定は不要です。
別のポートや別の種類のプロキシを使用する必要がある場合は、nano などのテキストエディタを使用してこのファイルを編集します。
SOCKS プロキシのテスト
このステップでは、隠れた内部 Web サービスにアクセスして、プロキシ設定が正しく機能しているかテストします。
172.30.0.20:80 の隠れた内部コンテナで Web サービスが実行されていることを思い出してください。現実のシナリオでは、これは外部インターネットから直接アクセスできない内部イントラネットサイトを表しています。
proxychains を使用するには、実行したいツールの前に proxychains4 コマンドを付けるだけです。curl を使用して Web ページを取得してみましょう。
以下のコマンドを実行します。
proxychains4 curl http://172.30.0.20
これを実行すると、proxychains は curl によるネットワークリクエストをインターセプトし、ポート 9050 の SSH SOCKS プロキシ経由でトンネリングします。その後、ピボットホストが内部 Docker ネットワーク上の 172.30.0.20:80 に対してリクエストを行い、結果を返します。
以下のような出力が表示されるはずです。
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.14
[proxychains] Strict chain ... 127.0.0.1:9050 ... 172.30.0.20:80 ... OK
Secret Internal Data: You have successfully pivoted
OK メッセージはプロキシ接続が成功したことを示しており、最後の行には内部 Web サーバーからの秘密データが表示されています。
ピボット経由での外部ツールの実行
最後のステップでは、より高度な外部ツールである Nmap を使用して、確立したピボット経由で内部ネットワークをスキャンします。
proxychains を Nmap と一緒に使用する場合、理解しておくべき重要な技術的制限があります。SOCKS プロキシは完全な TCP 接続のみをサポートしており、ICMP (ping) やハーフオープン SYN スキャン (sudo で実行した際に Nmap がデフォルトで使用するもの) はサポートしていません。
そのため、proxychains 経由で Nmap を実行する場合は、強制的に完全な TCP Connect スキャンを使用させ、ping によるホスト検出を無効にする必要があります。
以下の Nmap コマンドを実行して、ポート 80 の内部 Web サービスをスキャンします。
proxychains4 nmap -sT -Pn -p 80 172.30.0.20
ここで使用されている Nmap フラグを解説します。-sT フラグは TCP Connect スキャンを強制します。SOCKS プロキシは生のパケットや SYN スキャンを処理できないため、これは必須です。-Pn フラグはホスト検出 (ping) を無効にします。SOCKS プロキシは ICMP エコーリクエストをルーティングできないため、このフラグを省略すると Nmap はホストがダウンしていると誤判定してしまいます。最後に、-p 80 フラグはスキャンするポートを指定します。
proxychains が接続試行をログに記録し、その後に Nmap のスキャン結果が表示されます。
[proxychains] config file found: /etc/proxychains4.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.14
Starting Nmap 7.91 ( https://nmap.org ) at 2024-01-01 12:00 UTC
[proxychains] Strict chain ... 127.0.0.1:9050 ... 172.30.0.20:80 ... OK
Nmap scan report for 172.30.0.20
Host is up (0.0020s latency).
PORT STATE SERVICE
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 0.10 seconds
これにより、侵害されたホストを経由して複雑なセキュリティツールをルーティングし、内部ネットワークセグメントと対話できることが確認できました。
まとめ
おめでとうございます!「Proxychains を使用したダイナミックポートフォワーディング」の実験を無事に完了しました。
この実験では、SSH ダイナミックポートフォワーディング (-D) を使用してローカル SOCKS プロキシを作成する方法を学びました。また、proxychains の設定を理解し、確認する方法も学びました。さらに、プロキシ経由で基本的な HTTP リクエストをルーティングし、隠れた内部サービスにアクセスすることに成功しました。最後に、TCP Connect スキャン (-sT) を使用し、ping 検出 (-Pn) を無効にすることで、Nmap のような高度なスキャンツールを SOCKS プロキシ経由で動作させる方法を習得しました。
これらのピボット技術は、ペネトレーションテストやセキュリティ評価において、複雑なネットワーク環境をナビゲートするための必須スキルです。



