iptablesでいこう(1. ステルスと戦え)

iptablesでステルスと戦え

痕跡を残さないスキャンの手法を「ステルススキャン」とか言います。別に難しいわけじゃなくって、ツールに標準で装備されているのでサルでも使えますが、よくわかってないで使っているサルが多いのも事実だったりします。もちろんハッカーならきっちり使いこなしてるわけですが、踏み台も複数段あることですし、当然ステルスじゃないほうが情報は多く得られるのも事実で、だからなのか何なのか「すてるす?そんなもんぜーんぜん使わんよ、わし」というような常連が私んとこのログにはいっぱいいます。すべて諸外国の方々ですけど。文化の違いなんでしょうかねえ。 まあ、そういった人々もいますが、それはそれとして、「ステルススキャン」についてちょっと考えていこうというのが今回の趣向です。基本的には実用は考えていません、特に困ってはいませんから(^^。今のところ、遊びではじめます、今後に期待しましょう。 で、ここでの話はUNIXに限るものとします。WindowsはなーんとRFCに逆らう動きをするので、ここでの説明に当てはまらない部分があるのですね。


■ まずはちょー基本 ■


基本1(完全無防備)

念のため基本から押さえていきます。なーんにもフィルタリングしない場合、ポー トスキャンされるとどうなるか。ポートスキャンには特に断らない限り nmap を使っていきます。

ポートスキャンの例
稼動サービス(ポート) telnet(23) xinetd より起動
Tcp_Wrappers no
フィルタリングルール - - -
まずフィルタリングされてるかどうか調べる。

nmap -v -sA -p 23 XXX.XXX.XXX.XXX

の結果

The ACK scan took 0 seconds to scan 1 ports.
The 1 scanned port on hogehoge (XXX.XXX.XXX.XXX) is: UNfiltered

つーことで、フィルタリングされてないことがわかる。このタイプの
スキャンでは通常、相手ホストにログが残らない。続いて、ポートが
開いているか(サーバーが待っているか)調べる。

nmap -v -sT -p 23 XXX.XXX.XXX.XXX

の結果

The TCP connect scan took 0 seconds to scan 1 ports.
Interesting ports on hogehoge (XXX.XXX.XXX.XXX):
Port       State       Service
23/tcp     open        telnet                  

これだと相手ホストでは場合によっては /var/log/messages /var/log/secure
あたりにログが残るかも、だからこういったフルコネクトのスキャンは
フツーしないだろ、とか考えるけど、そうでもない。どうせ踏み台から
だっつーことなのか堂々とくるのも多い。

nmap -v -sF -p 23 XXX.XXX.XXX.XXX

とかを使うと

The UDP or stealth FIN/NULL/XMAS scan took 0 seconds to scan 1 ports.
Interesting ports on hogehoge (XXX.XXX.XXX.XXX):
Port       State       Service
23/tcp     open        telnet                  

で結果は同じ。ログは残らない。


というわけで、23 番がおまちかね、という事実と、フィルタリングしていないという事実が明らかになるというわけです。そして、ステルス系のポートスキャンをくらった場合はそれをされたことにも気がつきません。おおらかですねえ。



基本2(フィルタリングなし + Tcp_Wrappers)

では少し気が効いていて、Tcp_Wrappers でアクセス制限している場合。

ポートスキャンの例
サービス(ポート) portmap(111)
Tcp_Wrappers yes
フィルタリングルール - - -
さっきとおんなじ

nmap -v -sA -p 111 XXX.XXX.XXX.XXX

の結果

The ACK scan took 0 seconds to scan 1 ports.
The 1 scanned port on hogehoge (XXX.XXX.XXX.XXX) is: UNfiltered

で、

nmap -v -sF -p 111 XXX.XXX.XXX.XXX

の結果

The UDP or stealth FIN/NULL/XMAS scan took 1 second to scan 1 ports.
Interesting ports on hogehoge (XXX.XXX.XXX.XXX):
Port       State       Service
111/tcp    open        sunrpc                  

ちなみに

rpcinfo -p XXX.XXX.XXX.XXX

では情報は得られないで、相手ホストではさすがに /var/log/messages にログが残る


Tcp_Wrappers というのは、ポートスキャンに関しては無いも同然なんだとわかってもらえたらよいです。たまに万能だとカン違いしてるヒトがいるので、念のため。役割が全然違うわけですね。



■ 実践 ■

実践1(ローカル鯖もバレバレ?)

単純なパケットフィルタリングしかできないルーター(安いブロードバンドルーターとか)では、クライアントになれるように、発信元ポートが 21, 25, 80...ならとにかく全部許可!と豪快なことをしていることも多いのであるけど、その場合、発信元ポートを調整したパケットを送れば簡単にフィルタリングを逃れられるわけですな。nmap などのスキャニングツールにはごく当然のようにそのオプションがあるので、スキャンされると同時に、そんな豪快なことをしてることもバレるので、「こりゃイタダキかも」とかいうことにも...。

ところが立派なルーターを使ってる場合も知識が乏しいために、そういったルールにしてることも少なくないのですな、うっしっし(黒)。せめてPCでルーターやファイアウォールブリッジを構築するならそんなことはしないようにしないとね。

と、いうのはフィルタリングで守ってるつもりでも、鯖の存在はバレバレということもあるのですねえ。例えばローカルだけで使いたいFTP鯖があったとして、21番ポートへの外部からのアクセスを遮断すれば問題ないように思うでしょう?でも実はこの存在は隠せないんだな(T_T)

ポートスキャンの例と対策
サービス(ポート) ftp(21)
フィルタリングルール
悪い例
メールからネットサーフィンまで何でもやるデスクトップ機なんだけど、
なんだか嬉しいので、FTP鯖が稼動している。
でもちょっと仕入れた知識で「インターネットは怖い」と思っている。
そこで、ちょっと仕入れた知識でフィルタリングなどしてみている。
とりあえず外部からFTP鯖のポートめがけて飛んでくるパケットは破棄している。

なーんていうネット直結のデスクトップ機は結構ありそうでしょ。これを例にしましょう。

まず

nmap -v -sA -p 21 XXX.XXX.XXX.XXX

とりあえずフィルタリングされてるか調べたわけです。

The ACK scan took 2 seconds to scan 1 ports.
Interesting ports on hogehoge (XXX.XXX.XXX.XXX):
Port       State       Service
21/tcp     filtered    ftp                     

お、フィルタリングしてるねー、ふーん、ということになります。
フィルタリングされてる場合は注意します(ハッカー入門みたいになってるけど
そういうわけじゃないのでよろしく)

nmap -v -sF -p 21 -g 80 XXX.XXX.XXX.XXX

のように忘れずに -g オプションをつける。外部の80番を許可してることが多いので
そうしている。ファイアウォールから見れば、まるで web 鯖使ってポートスキャン
してるように見えて異様だけど、アホルーターではご丁寧に奥へご案内するわけですなあ。
この例の場合 -g 53 とか -g 110 とかしてもよいわけだけどね。

The UDP or stealth FIN/NULL/XMAS scan took 1 second to scan 1 ports.
Interesting ports on hogehoge (XXX.XXX.XXX.XXX):
Port       State       Service
21/tcp     open        ftp                     

ちなみに -g オプションをつけないと、きっちりフィルタリングされてる場合、
なんでもかんでも open となるので信用できない(※1)。
たとえば空いてない65535番に向けて

nmap -v -sF -p 65535 XXX.XXX.XXX.XXX

としても

The UDP or stealth FIN/NULL/XMAS scan took 1 second to scan 1 ports.
Interesting ports on hogehoge (XXX.XXX.XXX.XXX):
Port       State       Service
65535/tcp     open        unknown                     

ね。ちなみに -g オプションつきでは

nmap -v -sF -p 65535 -g 80 XXX.XXX.XXX.XXX

The UDP or stealth FIN/NULL/XMAS scan took 0 seconds to scan 1 ports.
The 1 scanned port on hogehoge (XXX.XXX.XXX.XXX) is: closed

となる。

※1
これはステルス系スキャンの仕組みに関係している。

RFCでは、いきなり ACK が飛んでくるなどの異常なリクエスト
に対しては対象サービスが稼動している場合は無視、稼動していない場合は
OS(カーネル)が RST で応える、とされている(先にも書いたが Windows は
これに従っていない、イイ気なもんです)。

つうことで、返答がない場合は稼動している、つまり open とnmap は判断するわけ。
ところが、 RST を返そうにもフィルタリングされてて応えられなかったり、
それ以前に最初の ACK がフィルタリングされてて、なーんにもおこらないと、
やっぱり open と誤判断してしまうのである。

なので、パケットがフィルタリングされない穴を確保するために -g オプション
あるいは場合によっては -D オプションを用いるのですね。

------------------------------------------------------------

さて、つーわけで結局どーすれば隠せるのか?さしあたってこの方法を避けるには
さっきも書いたように 「web 鯖使ってポートスキャンしてるように見える異様なパケット」 などを通さなきゃよいのです。 iptables -A INPUT -p tcp --sport 80 -j ACCEPT なんて豪快なのはやめて、せめて iptables -A INPUT -p tcp --sport 80 --dport 1024: -j ACCEPT とする。でも、結局 open してるものは open になるわけで、 根本的な解決になっていないんじゃないか?というあなたの言い分も正しい(T_T) まあ、相手が惑えばよいとしてください。 iptables -A INPUT -p tcp --sport 20,21,25,80,110 --dport 20,21,25,80,110 -j DROP のようなのを入れてログをとるとか、というのもありですかね。 どーしても全部 close で応えてやりたい というお気持ちもわかりますが、ステルススキャンを検知して(後述)、こちらが偽造 パケットで応えるとか、大がかりになりそうな...。それに、よけい興味をもたれます、 その挙動は Windows と間違われますから(笑)。



実践2(ステルススキャンをチェック)

ステルス系スキャンを検知するのはふつう Snort などにスニッファに任せるけど(自分もそうしてる)、iptables でなんかできないかなーと考えてる人もいるでしょう。パケットの操作が容易だし、そうするメリットも充分にあるので、検討してもよいでしょうねえ。

稼動サービス(ポート) ftp(21)
サービスは正常に稼動しつつ、ポートスキャンに反応しないようにできないか

というのを考えてみましょう。かなり無茶ですが(笑)

正しいTCPプロトコルのいわゆる 3WAY ハンドシェイクでは、
まず SYN パケットという特定のビットを立てたパケットを
クライアントから鯖に送ることによって新たな接続が開始される。

ではこれを守らないとどうするかっつーのも決められてて、
その挙動を判断材料として調査するのがいわゆるFin, Null, Xmas Tree スキャン
などのステルススキャンでございます(※2)。
作法を守らないから正しいTCP接続とされないので
セッションのログなどに残らないから「ステルス」というわけ。
この手法では SYN パケットでない、つまり

「 SYN 以外のビットを立てたパケットをいきなり送りつける」

という点で共通であるのね。iptables だとこのスキャン作業自体を捉えるのは
ちょっと面倒そう。でも、nmap に関して言えば、実際にスキャンをする前に
予めホスト自体生きてるかどうか調べるためにパケットを飛ばすんだけど、
それもこそっと行うために、この手法を用いる。icmp を用いるやり方もあって、
自由に選択できるんだけど、この時点でホストから何も返さないようにすることは可能。

ということで

iptables -A INPUT -p icmp -j DROP
iptables -A OUTPUT -p icmp -j DROP
iptables -A INPUT -m state --state NEW -p tcp ! --syn -j LOG --log-level info --log-prefix "STEALTH SCAN"
iptables -A INPUT -m state --state NEW -p tcp ! --syn -j DROP

こんなカンジ。実際には icmp をこんな目にあわせてよいのか、という問題があるが、
他人には我慢してもらうとして、調査用に限られたホストからだけ通すとかすれば
なおいいでしょう。

この場合スキャニングには icmp と、いきなりの ACK が使えなくなる。
これらは nmap でのデフォルトとなっているので、明示的に 
SYN パケットによってホストの生存調査を行うか、省略せざるを得ない
( -P0 オプションなど)。他の手段で既にこのホストが生きていることが知られて
いなければ、こういったイレギュラーな設定はわりと有効かもね。無差別にIPアドレスを
自動でスイープしてくようなスキャンには引っかからないようにできるかもねえ。

もちろん特別に狙われてるのでなければの話。

※2
SYN パケットのみを送って応答を拾い、確認を送らないというタイプの
ステルススキャンもあるです(ハーフコネクトスキャン)。






トップページ