概要
今回はネットワークに関する問題です。CTFでのネットワーク問題はおもに通信データを解析する問題が出題されます。
具体的にはパケットを記録したファイルが渡され、それを解析するのですが対象となるパケットの種類は多岐にわたります。
問題
seccon_q1_pcap.pcap というファイルが与えられます。
fileコマンドでみるとこのように表示させます。

パケットキャプチャツールによって取得された通信データであるとわかります。
今回はWireSharkを使って中身を確認しましょう。
Fileタブから先ほどのファイルを開きます。

このようになりました。

ICMPのプロトコルであるpingリクエストとその返答であるとわかります。
ICMPには用途に応じて様々な機能がTypeとして存在しています。
そのうち今回の
Echo requestはType8,Echo replyはType0に分類されます。
詳細は以下のRFC792という技術文書にあります。
このままでは見づらいので。Wiresharkの機能を使ってデータの全体を把握します。
staticタブからProtocol Hierarchyを開きます。

すると以下のようになりました。

ここからわかることは、パケットは全部で141あり、そのすべてがICMPであるということです。
続いてStatics→Conversationsを開いて、通信先と通信元の情報を確認します。

ウィンドウが表示されたら、IPv4タブを開きます。

ここからわかることは、この通信では192.168.88.129と192.168.88.128のみが登場するというです。
解法
ここからは実際にFlagを取得したいと思いますが、先ほど調べたところ特に怪しいところもなかったのでもう少し詳細に調査していきます。
一番上から順番に中身を確認していくと、41行目にこのようデータが見つかります。

なぜかpingに Get /kagi.ong HTTP /1,1... というHTTPリクエストヘッダが現れました。
なぜpingなのにWebサイト観覧時のデータがと疑問に思いますが、それは後ほど解説します。
とりあえず今はFlagを取得したいと思いますが、不審なHTTPリクエストにkagi.pngという名前から十中八九kagi.pngがflagに関係していると予想できます。
ではさっそくkagi.pngを取り出してみましょう。
そのためにはICMPパケットの構成を最低限理解しておくと便利です。
まずICMPはTCP/IPのインターネット(IP)層に位置します
TCP/IPの4つの階層は上から順に以下の通りです。
- アプリケーション層
- トランスポート層
- インターネット層
- ネットワークインターフェイス層
先ほどのHierarchyで階層のネットワークインターフェイス層の入れ子になっていたのもIP層が上位層にあたるからです。
そのためICMPパケット構成も以下の通りになっています。
| Ethernetヘッダ | IPヘッダ | ICMPヘッダ | ICMPデータ |
|---|
今回の問題ではICMPデータにHTTPリクエストとそのレスポンスであるkagi.pngが入っています。
44行目のレスポンスをコピーしてechoなどでhexからsring抜き出すと以下のようになります。
echo <hex> | xxd -r -p
補足するとxxdはバイナリを16進数に変換するコマンドで、-rオプションで逆のことつまりhexからバイナリに変えていて -pでplainTextとみなしています。
Content-TypeのしたにあるPNGから実際のkaigi.pngのデータです。これを抜き出します。
注意してほしいのが、HTTPの前に文字化けと8などがありますが、これらの謎のデータが28バイトあるのでそれを考慮してスクリプトを作成します。
#coding: utf-8
from scapy.all import *
#read pacets
packets = rdpcap('seccon_q1_pcap.pcap')
icmpdata = b""
#from 44 index pacets
for i in range (43,48):
p = packets[i]['Raw'].load
icmpdata = icmpdata + p[28:] #exept first 28byts
# find by signature
index = icmpdata.find(b'\x89\x50\x4e\x47\x0d\x0a\x1a\x0a')
key = icmpdata[index:]
f = open('kaigi.png','wb')
f.write(key)
f.close()
コメントを付けている箇所だけ説明しておきます。
rdpcap('seccon_q1_pcap.pcap')でscapyというライブラリを用いてpcapファイルを読み込んでいます。
また先ほどあった謎の28バイトデータを除いています。
さらにはシグネチャというファイルの種類がわかる先頭バイトを使ってPNGの部分を判別して抜き出します。
中を確認すると、flagを入手できる。
今回はいつものようにSECCON{}の形式ではないことに注意してください。
補足
flagは無事に入手できましたが、まだなぜICMPのデータにHTTPが現れたのかについて触れていないので解説していきます。
まずICMP Echo Messageと Echo Replyの目的を思い出してみると、疎通確認を行うことです。つまり接続が確認できればあとは気にする必要がありません。
なのでICMPデータには任意のフォーマットで値を入れることができます。
これを利用してHTTPのような任意の通信データをEcho Message/Echo Replyに入れる手法をICMPトンネリングといい、プロトコルを偽装してファイアウォールの検知を掻い潜ることに使われたりします。
またそれをツール化したものにPingTunnelというものがあり、そのソースコードを見てみると、ptunnel header(28bytes)とあり、先ほどの謎の28バイトデータの正体はこれでした。
まとめ
今回はHTTPで暗号化されていない通信では画像ファイルも簡単に復元できるという危険性や、ICMPトンネリングを用いたプロトコルの偽装方法について学ぶことができました。
参考文献
中島 明日香『入門セキュリティコンテスト ― CTFを解きながら学ぶ実戦技術』翔泳社, 2023年.


