[Cuckoo Sandbox] サンドボックス検出ツール「sems」を使って軽く耐耐解析機能を実現してみる

sems とは

sems は、Cuckoo Sandbox や仮想マシン内で実行されていることを検知しレポートするソフトウェア。
あゆむ氏 (@AES256bit) に存在を教えてもらった。

semsは、以下のような様々なサンドボックス検出機能を持つ。

などなど・・・数が多いので詳しくは下記ソースを参照。
https://github.com/AlicanAkyol/sems/tree/master/cuckoo_detection
(一部どう考えても被害妄想だろとツッコんでしまうようなものがあったりして面白い)

この記事では、Cuckoo Sandbox & Virtualbox仮想マシンのインストール時に標準で検知された以下の2つの項目において、
Cuckoo Sandbox の設定やソースコードを少しいじってsemsに検知されないよう耐耐解析機能を実現する。

  • resultserverのポート番号の検知
  • python.exeプロセスの検知


なお、semsによって検知されたかどうかの確認は、起動中の標準出力を確認する方法以外にも、
semsは検知した各項目ごとにカレントディレクトリにテキストファイルを生成してくれるので、
Cuckoo Sandbox の挙動解析結果の NtCreateFile() の呼び出しから確認できる。

また、当然のことながら Virtualbox の Guest Addition はインストールしていない。semsは当然検知する。

resultserverのポート番号の検知

解析結果を送信するサーバのポート番号は2042/tcpであり、それを検知する。
そのため、20042/tcpに変更する。

~/.cuckoo/conf/cuckoo.confの修正

port = 20042

python.exeプロセスの検知

これはちょっと被害妄想な気もするけど・・・。
python.exe 以外のファイル名に変更すればいい。

ゲストOSのpythonパス変更

python27は標準でC:¥python27 に python.exe および pythonw.exe を作成する。
そこで以下のパスに変更。

C:¥DELL¥SUServer.exe
C:¥DELL¥SUServerw.exe

core/guest.pyの修正

我が家の環境では、フルパスは「/usr/local/lib/python2.7/dist-packages/cuckoo/core/guest.py」。

Cuckoo Sandbox は python が C:¥ 直下にインストールされることを期待するので、上記と同時に修正を行う必要がある。
また、 analyzer.py の配置は C:¥tmp[random] フォルダに行うため、sems では検知されないが耐解析機能を持ったマルウェアに検知される可能性がある。
そのため、ついでに analyzer.py の配置先を C:¥DELL_UPDATE¥tmp[random] フォルダに行うように修正。

361d360
<         systemdrive = systemdrive + "DELL_UPDATE/"
514,515c513
<                 #"command": "C:\\Python27\\pythonw.exe %s\\analyzer.py" % self.analyzer_path,
<                 "command": "C:\\DELL\\SUServicew.exe %s\\analyzer.py" % self.analyzer_path,
---
>                 "command": "C:\\Python27\\pythonw.exe %s\\analyzer.py" % self.analyzer_path,

SUService.exe はレノボのソフトウェアらしいが、名前さえ変えれば問題ないので適当に付けた。


以上、修正後semsで検知しなくなったので満足。

[Cuckoo Sandbox] プロキシ経由通信時の解析結果のURL表記の崩れの修正

Cuckooはmitmproxyに対応しているが、レポートのURL記載周りにおいてはURLにパスのみが含まれている前提になっている。

結果、パスが「http://〜」から始まるプロキシサーバ宛の通信の記載は以下のようになる。

  • Performs some HTTP requests(3 events)

request GET http://www.msftncsi.comhttp://www.msftncsi.com/ncsi.txt

  • Network Analysis

GET => 200 http://www.msftncsi.comhttp://www.msftncsi.com/ncsi.txt

ここで原因となった情報を分解してみる。

key value
protocol http
host www.msftncsi.com
uri http://www.msftncsi.com/ncsi.txt
(表示構造) [protocol]://[host][uri]
(表示結果) http://www.msftncsi.comhttp://www.msftncsi.com/ncsi.txt

上記uriがプロキシ宛の場合httpおよびホスト名が入っているので、表示が崩れる。
そこで、修正を試みる。

Performs some HTTP requests

  • /usr/local/lib/python2.7/dist-packages/cuckoo/common/abstracts.py

Cuckooはmitm.logを読み込むにもかかわらず、実際のmitmのログはdump.mitmにあるため、データを読み込めていない。
Cuckooはmitm.logからデータが取得できない場合はプロキシ経由ではないと判断しHTTP通信をtcpdumpから取得するため表示が崩れる。
これは環境依存かも。

657c657,658
<         self.mitmout_path = os.path.join(self.analysis_path, "mitm.log")
---
>         #self.mitmout_path = os.path.join(self.analysis_path, "mitm.log")
>         self.mitmout_path = os.path.join(self.analysis_path, "dump.mitm")

Network Analysis

  • /usr/local/lib/python2.7/dist-packages/cuckoo/web/templates/partials/http-request.html

こちらはmitmの使用にかかわらずtcpdumpの結果から情報を取得するためプロキシ経由を考慮せずURLを取得する。
そのためデータ構造をhttp.uriだけに変更する。

6c6,7
<         <span class="url">{{ http.protocol }}://{{http.host}}{{http.uri}}</span>
---
>         <!--<span class="url">{{ http.protocol }}://{{http.host}}{{http.uri}}</span>-->
>         <span class="url">{{http.uri}}</span>

修正後、以下のような表示になる。

  • Performs some HTTP requests(3 events)

request GET http://www.msftncsi.com/ncsi.txt

  • Network Analysis

GET => 200 http://www.msftncsi.com/ncsi.txt

以上。

TXTレコードでトンネリングする疑似マルウェアの仕様とデモンストレーション

f:id:shutingrz:20171215043026p:plain
疑似マルウェアを動かしてTXTトンネリングしている際のパケット

しゅーとです。

以前AレコードでトンネリングするHelminthというマルウェアのC2サーバを作成しましたが、
今回はTXTレコードでトンネリングする疑似マルウェアおよびC2サーバを作ってみました。

DNSでトンネリングする理由などの詳細は以前の記事で記載しているのでそちらをご覧ください。
shutingrz.hatenablog.com

今回は研究者向けに仕様とデモンストレーションした際のpcapファイルを提供します。(本音: 詳細な説明が面倒くさい)
標的型攻撃でよく使われるDNSトンネリングマルウェアは、今回のようにTXTレコードを使用するものが多いです。芸がないですね。

pcap

localhostでデモンストレーションした際のpcapです。
http://www.shutingrz.com/misc/txtdoor.pcap

概要

本疑似マルウェアはqnameをランダム化しキャッシュされないように工夫しています。
そのため、キャッシュサーバを経由してサーバとやり取りすることが可能です。

※pcapではlocalhostで送受信しているため応答でAAフラグが立っていますが、
 本来想定されるクライアントPCとキャッシュサーバ間の通信ではAAフラグが立たないので注意してください。

特徴

以下の特徴点から、セキュリティ機器による検知が容易です。

  • qnameが長い
  • 実行結果をhexとしてqnameに埋め込むため可読性が高い
  • クライアントPCの通常利用としてあまり見られないTXT RRを用いる
  • 命令コマンドが平文

仕様

クライアントからサーバ

※クライアントからサーバの送信は前回の記事のHelminthと同じ仕様です。

全てqnameでトンネリングします。

botid の取得

00000000 + .example.com

コマンド命令有無の受付(keepalive)

00 + botid(a char) + 00000 + random(XXX) + 30 + .example.com

コマンド命令の受信受付

00 + botid(a char) + 00000 + random(XXX) + partid(XXX) + .example.com

コマンド実行結果の送信

00 + botid(a char) + fileid(XX) + partid(XXX) + ramdom(XXX) + data(length<25) + .example.com
※ data は hex文字列

サーバからクライアント

全てANSWERセクションのTXT RRでトンネリングします。

botid の応答

botid(a char)

コマンド命令に対して命令させたいコマンドがある場合の応答

fileid(XX)

コマンド命令の応答

plain
※送信終了時「###end###」を応答

クライアントからのコマンド実行結果の応答

recv

おまけ

クライアントから受信した実行結果をデコードする python コード

  def recvData(self, qdata): # qdata はドメイン名の最初のラベル
    botid = qdata[2:3]
    cmdid = qdata[3:5]  #fileid
    partid= qdata[5:8]  #partid (base36)
    rand  = qdata[8:11] #rand data (base36)
    data  = qdata[11:]  #txt data

    for dec in [(i+j) for (i,j) in zip(data[::2], data[1::2])]:
      encstr = "%" + dec
      print("%s" % urllib.unquote(encstr))

※このコードは partid の整列をしてないので注意

glibc の脆弱性 CVE-2017-12132 は glibc の脆弱性ではない

しゅーとです。

8/1 、glibcの開発者は、glibcにいわゆるアイコラ攻撃の脆弱性が存在するとして修正を行ったとのことです。
その脆弱性のCVE番号は CVE-2017-12132 で、下記に概要が載っています。

cve.mitre.org

また、日本語で概要が載っているページもあります。(※任意のコード実行の可能性との記載がありますが、これは間違いです。)

oss.sios.com

修正までの経緯

glibc脆弱性報告から修正まで、下記のページで行われました。

21361 – (CVE-2017-12132) resolv: Reduce advertised EDNS0 buffer size to guard against fragmentation attacks (CVE-2017-12132)

要約すると、「glibcはEDNS0のbufsizeが最大の65536byte(※正しくは65535byte)に設定してあり、アイコラ攻撃に脆弱である。bufsizeを1200に変更すればこの攻撃を防げる。」ということです。
開発者はこの報告を受け、「現在のglibcアイコラ攻撃に脆弱である」とし、ソースコードを修正し、CVE番号を発行しました。
修正したソースコードについては以下を参照してください。
sourceware.org Git - glibc.git/commitdiff

なにがマズいのか

アイコラ攻撃はDNS(さらに言えば、IPとUDP)のプロトコル上の問題(脆弱性)を突いたものであり、glibc の実装を突くものではありません。
glibc脆弱性ではないのに、なぜおせっかいをするのでしょう。さらに、これはプロトコル脆弱性なので、実装をもって脆弱性を修正することはできません。修正できるということは、それは仕様を逸脱するということです(実装依存除く)。
RFC3226では、EDNS0 の bufsize を 4000 にすべき(SHOULD)としていますが、CVE-2017-12132 の修正()を行ったことで仕様を逸脱していませんか?

あと、bufsize を 1200 にしても MTU によってはフラグメントすることがあるのですが、本当にアイコラ攻撃に脆弱ではなくなったんですか?

その他

glibc は CVE-2017-12132 のおかげでbufsizeが 1200 になったようですが、BINDやUnboundはbufsizeのデフォが4096なので、アイコラ攻撃に脆弱ですね!
ISC さんや NLnet Labsさんに「あなたのソフトウェアはアイコラ攻撃に脆弱なのでbufsizeを修正してCVEを発行してください」と伝えたらいかがですか。

その他2

私、DNSSECはわかりませんが、最近 KSK ロールオーバーに関連して IP フラグメント周りの設定確認が推奨されているようですね。
JPNICの下記ページには「max-udp-sizeとedns-udp-sizeの値を小さく制限していないことを確認します。 デフォルトの値は4096です。 」と記載してあります。glibcさんはいいのですか?ソースコードベタ書きで設定で変更できないようなのですが。
いいと思います

KSKロールオーバーについて - JPNIC

標的型攻撃で使われたマルウェアを解析して C2 サーバを作った。そのマルウェアは DNSトンネリングを行う珍しいものだった。

f:id:shutingrz:20170525142718p:plain
マルウェアを動かして 自作 C2 サーバとやりとりをしている図。詳しくはページ下部にて解説
 
しゅーとです。

去年あたりに、サウジアラビアの金融機関を狙った標的型攻撃があったのですが、その攻撃にDNS トンネリングを用いて情報を外部に送信するマルウェア「Helminth」が使われました。

詳細レポートは Palo Alto Networks の脅威対策チーム Unit42 が出してくれています。
OilRig攻撃活動: サウジアラビアの組織への攻撃でHelminthバックドアを配信 - Palo Alto Networks

ちょうど検体も出回っていたので、 Helminth の解析を行い、C2サーバ(C&Cサーバ)を作成してみました。

この記事では、解析の過程で発見した仕様と、マルウェアに馴染みがない方のためのDNSトンネリングの仕組みと概要を記載しています。

DNSトンネリングの仕組み

HTTP を用いた C2 通信

マルウェアが C2サーバと情報をやりとりする際に最も使われるプロトコルは、HTTP(S) です。
HTTP においてマルウェアから C2サーバに情報を送信するためには HTTP リクエストを行います。
また、C2サーバからマルウェアにコマンド指令を送信するためにはマルウェアからの HTTP リクエストに対して HTTP レスポンスを行います。
なぜマルウェアは HTTP 通信をよく用いるのでしょうか。私はいくつか理由があると思っています。
 

  1. ほとんどのOSでHTTP通信が可能である
  2. プロキシサーバが存在している場合でも、クライアントの通信がほぼそのままで外部に抜け出せるようになっている
  3. 様々なデータを柔軟に表現できる

 
セキュリティに気を使っている会社では、不必要なポートを閉じるようにして、プロキシサーバからでないと通信できないようにするなど経路を絞ることを頑張っています。

しかし HTTP通信はプロキシサーバを経由したとしてもクライアントが出した通信をほぼそのまま外に出すことができるため、攻撃者にとっては非常に使い勝手の良いプロトコルになっています。

※プロキシサーバを置く一番の理由はプロキシログを取って定期的な監査を行うためだと思いますが、最近は ChChes をはじめ、 Cookie に情報を入れるマルウェアが増えているため、プロキシログだけでは正確な監査が難しくなっています。

DNS を用いた C2 通信

監査をする人も上記の特徴を当然把握し HTTP 通信の監視を強化しているため、攻撃者は別の方法でなんとかバレないように情報をやりとりする方法を模索しています。
そこで注目されたのが DNS でした。
HTTP 通信の特徴を DNS に置き換えるとどうなるでしょうか。マルウェアから C2サーバは DNS クエリで、C2サーバからマルウェアDNS レスポンスになります。

またセキュリティに気を使っている会社では、HTTP と同様にキャッシュサーバ以外の IPアドレスから外部に名前解決ができないようにしていると思いますが、クエリの qname はどうしても外部に出さないといけません。その点で HTTP と非常に似た特徴を持っているのです。

具体的に TXT レコード の名前解決を例に出してみましょう。 通常は www.shutingrz.com の TXT レコードを問い合わせて 文字列が返される流れですが、マルウェアから C2サーバに感染端末の OS のバージョン情報を送信しようと考えると、 windows10.shutingrz.com というドメイン名の TXT レコードを C2サーバに問い合わせることで情報の送信ができます。

逆に C2サーバからマルウェアWindowsバージョン情報を取得しろという指令を出したい場合、マルウェアに一定間隔でドメイン名を問い合わせさせ、指令を出したいタイミングで TXT レコードのレスポンスに「ver」 (コマンドプロンプトで実行するとWindows のバージョンが取得できる) を載せれば指令の送信ができます。

以上のような手法を用いることで、DNS を用いた C2 通信が可能になるのです。

また、参考までにDNSトンネリング機能を持つマルウェアの一覧をまとめたので記載します。

DNS トンネリングを行うマルウェア一覧
マルウェア ホスト名の規則 レコード 備考
PlugX (0x36a4) [base32][何かの規則].subdomain.domain TXT DNS以外にICMP, HTTPでのC2通信がある
PlugX (0x2540) [base64].subdomain.domain TXT ホストのエンコード方式がbase64なので、ホスト名に "+" "/" が含まれる
MULTIGRAN亜種 log.[base32]. datavhg[.]com TXT 左端のホスト名が”log”で固定化されている
pisloader [何かの規則][base32].subdomain.domain TXT ホスト名に含まれる情報をデコードをするコードがUnit42のgithubページで公開されている
Feederbot [50 bytes].[CHUNK-ID].[qdparam].subdomain.domain TXT 2011年に発見されたマルウェアらしく、DNSをつかうものとしては古参
DNSMessenger [暗号化{データ]}].subdomain.domain TXT 最も最近(2017年2月?)に使われた、DNSトンネリングするマルウェア。データが多い時はTCPを使う
FrameworkPOS [エンコード].domain A/AAAA getaddrinfo を使っている
C3PRO-RACCOON [base64].domain CNAME レスポンスの規則: [cmd].[arg].domain ※CNAMEを用いている珍しいタイプ
Helminth [規則].subdomain.domain A 今回詳しく解説

まとめてみると想像以上にありました。色々なマルウェアがセキュリティ機器およびセキュリティエンジニアによる検知の回避のために趣向を凝らしていることがよくわかります。
また、ほとんどのマルウェアが TXT レコードを用いています。

SMTP を用いた C2 通信

HTTP, DNS 以外にも、直接の通信をファイアウォールで閉じたとしても別機器を経由することで外部ネットワークにそのまま情報を出せるものがあります。
SMTP(メール)です。
現時点では SMTP を使った C2 通信を行うマルウェアは滅多にありませんが、一応あります。PerfectKeylogger という名の少し古い時期に出たマルウェアです。

PerfectKeylogger はメールの送信先をC2サーバにして、感染端末の情報をメール本文に記載し送信します。
https://www.fireeye.com/content/dam/legacy/blog/2012/11/6a00d835018afd53ef01156e3247e0970c-800wi.jpg

詳しくは FireEye のレポートを参照してください。
E-Bandits - Part 1 « Threat Research Blog | FireEye Inc

メールは認証情報が必要だから攻撃者が使いづらいという意見もありそうですが、プロキシのID, Pass を取り出して HTTP 通信を行うマルウェアが既にあるので、SMTP を用いた C2 通信が多く使われるのは時間の問題かと思います。

Helminth の解析

Helminth の概要

ようやく Helminth の説明を始めます。Unit 42 には書かれていない、少し細かい内容を書いています。

Helminth は、2つのスクリプトから成り立っています。

今回は ps1 ファイルを解析し、それに合わせた C2サーバを作成しました。

Helminth の特徴

C2通信に A レコードを用いる点

Helminth の 1番の特徴は、よく使われるような TXT レコードではなく、 A レコードを用いて C2 サーバとの通信を行う点です。
TXT レコードは、汎用的に情報を載せることが可能である一方、通常のDNS通信ではあまり使われない レコードであることから、セキュリティ機器に検知されやすい弱点も持っています。
そのため、A レコードを使うことで検知される可能性を減らすことができます。当然 TXT レコードとは逆に情報を載せる場合の制約が多いというデメリット (IPアドレスの 1オクテットに載せられる情報は 8bitまで) があります。

Helminth は 8bit に収まる文字表現として アスキーコード(7bit) を用いています。

感染端末での実行コマンドの形式がバッチスクリプトである点

通常のマルウェアのC2コマンドは、あらかじめ決められたコマンドを用いることが多いです(put や get など)。
Helminth の場合はバッチスクリプトの形式になっていますが、これは、仕様の制約とDNSトンネリングのスクリプトは初期侵入に使われている点から様々なケースに対応するためだと思います。

なぜかドメイン名に載せる情報の表現がアスキーコードになっている点

C2サーバからマルウェアにコマンド指令をする際は IPアドレスとして情報を載せなければいけないためアスキーコードになっていることは納得できます。
しかし Helminth はC2サーバに送るドメイン名に情報を入れる際、アスキーコードで情報を入れているのです。

例(マルウェアからC2サーバへの実行結果を送信するときのクエリのqname):
001100000BQZ0D0A433A5C55736572735C7368753E64697220633A5C200D.s.com
C:\Users\shu>dir c:\

この仕様によって、Helminth はアスキーコードに入っている文字以外の文字を送信することができないのです。当然日本語を送ることも不可能です。

Helminth の細かい仕様の話をすると、 Helminth はバッチスクリプトの実行結果を 1行づつエンコードしパケットを送信します。
また、日本語 OS上で dir c:\ を実行した時に、日本語で「ドライブ C のボリュームラベルがありません」という出力がでる場合がありますが、
Helminth は実行結果の行にアスキーコード以外の文字が含まれる場合はその行を飛ばすという仕様になっているため、C2サーバで受信すると実行結果が歯抜けになってしまうんです。

Helminth はサウジアラビアの金融機関を狙ったとのことなので、そうなると標的 PCの言語はアラビア語ですよね?
アラビア語の文字はアスキーコードに含まれないので完全なデータを送れないのではと思います。
なぜこんな仕様なのかはよくわかりません・・・。
メリットとしては、アスキーコード 1文字のhexは ドメイン名において 2文字で表現できることから、少ない通信回数と固定長で情報を送れる点でしょうか・・・。

その他の特徴
  • 0.5秒間隔で 20回 DNSクエリを送信し、それまでに1回も A レコードが返ってきていない場合は終了する
  • ドメイン名の RFC に準拠するためなのか、ドメイン名に情報を載せる際のエンコード方式は base32

※他のマルウェアも base32 を使っているものがあるので特に珍しくはないです。

次項から具体的なクエリの法則について説明をします。

Bot ID の要求

bot からの bot id の要求通信

00000000[(random)]30.domain

↓上記に対する C2 サーバからの返答

[botid].0.0.0

C2 サーバの返答はアスキーコードの 10進数表現を IPアドレスとして埋め込んでいます。

  • 既に bot id がスクリプト内に埋め込まれている場合は通信を行わない
  • bot は A レコードの第一オクテットのみ確認するため、実際の C2 サーバが第2オクテット以降の値をどう設定しているかは不明

この通信は文字列長がある程度固定なので、通信を検知するためのシグネチャが書きやすいです。

実行コマンドの要求

bot からの実行コマンドの開始要求時のクエリ名

00[botid]00000[(random)]30.domain

↓上記に対する C2サーバからの返答

35.35.x.y ←x.yは cmdid(記号・制御文字以外であれば何でもよい)

↓転送開始時の、bot からの実行コマンド受付中のクエリ名

00[botid]00000[(random)]232A[chr(x)][chr(y)][partid].domain

・上記に対する C2 サーバからの返答
- 転送中のとき

a.b.c.d ←アスキーコード 10進表現

- 転送終了のとき

35.35.35.35

データの順番を整えるためにドメイン名に partid が振られているのはちょっと面白いです。

実行結果の送信

bot からの実行結果送信の通信

00[botid][cmdid][partid][(random)][DATA].domain

cmdid ← 実行コマンド応答時の cmdid
partid ← 実行結果を分割したときの通し番号
DATA ← 実行結果(アスキーコード 16進表現)

・上記に対するC2サーバからの返答
不明 (今回は便宜的に 127.0.0.1 を使用した)

botは結果送信時の応答について定めていないため、実際の C2サーバが A レコードの値をどう設定しているかは不明
実行コマンド転送に用いている 35.35. から始まるもの以外ならば何でも良いです。

Helminth を動かして情報をやりとりしてみた

一番初めの botid の取得からコマンド指令の受信、実行結果の送信をパケットキャプチャしました。

botid の取得

f:id:shutingrz:20170525142708p:plain

C2サーバからの返答は 76.0.0.0 です。
アスキーコード 10進数 の 76 を文字に変換すると、「L」であり、今回動かしたボットに与えた botid は L であることがわかります。

コマンド指令の受信

f:id:shutingrz:20170525142718p:plain

最初のパケットは「何か実行して欲しいものあったら言ってね」という旨のビーコンです。
C2サーバで実行して欲しい時には 35.35.x.y の形式でレスポンスを返します。
特に実行してもらう必要がない場合は無視をします。
今回は2つめのパケットで 35.35.x.y を返しているので実行して欲しいってことですね。


3つ目以降のパケットは実行して欲しいコマンドをIPアドレスの形で送受信しているところです。
C2 サーバが返した IP アドレスを下記に記載します。

IPアドレス アスキーコード 変換結果
100.105.114.32 100 105 114 32 dir [SP]
99.58.92.10 99 58 92 10 c:\ [LF]
10.10.10.10 10 10 10 10 [LF][LF][LF][LF]
35.35.35.35 35 35 35 35 (転送終了の合図)

※今回作成した C2 サーバでは、コードの簡略化のため最後のパディングとして [LF] を挿入させています。
 
デコードしたものを全て結合してみると「dir c:\ [LF][LF][LF][LF][LF]」になります。C ドライブ直下のディレクトリ構造を出力させるようなコマンドです。
バッチスクリプトでは空行は無視されるので、実行結果に影響はありません。

実行結果の送信

f:id:shutingrz:20170525142726p:plain

実行結果を Helminth がひたすら送信している図です。
応答はなんでもいいので、127.0.0.1 を返す実装にしました。

C2サーバに送ったドメイン名からデータ部分と partid を抜き出して下記に記載します。

【partid : data】

000:0D0A433A5C55736572735C7368753E64697220633A5C200D
004:0A0D0A323030392F30362F3131202030363A343220202020
005:2020202020202020202020203234206175746F657865632E
006:6261740D0A323030392F30362F3131202030363A34322020
007:2020202020202020202020202020313020636F6E6669672E
008:7379730D0A323030392F30372F3134202031313A33372020
009:20203C4449523E20202020202020202020506572664C6F67
00A:730D0A323031362F31322F3138202031313A313920202020
00B:3C4449523E2020202020202020202050726F6772616D2046
00C:696C65730D0A323031362F31322F3138202030393A313320
00D:2020203C4449523E2020202020202020202055736572730D
00E:0A323031362F31322F3138202031313A3139202020203C44
00F:49523E2020202020202020202057696E646F77730D0A2020
00K:88E60D0A

partid をよーく見てみると、001-003, 00G-00J が抜けています。
これは、該当行に日本語が含まれていたため、 Helminth がその行を抜かしてC2サーバに送ったためです。

また、データをデコードした結果を記載します。

C:¥Users¥shu>dir c:¥ 

2009/06/11  06:42                24 autoexec.bat
2009/06/11  06:42                10 config.sys
2009/07/14  11:37    <DIR>          PerfLogs
2016/12/18  11:19    <DIR>          Program Files
2016/12/18  09:13    <DIR>          Users
2016/12/18  11:19    <DIR>          Windows
  域

なぜか最後に 88E6(=> SJIS で「域」)が含まれていますね。日本語が複数行にわたって記述されていた関係でしょうか。原因調査していないのでわかりません。

おまけ

Helminth からのクエリを見てどのモードか判断する python コード

#qname.label[0] => host part.
#ex.  aaa.google.com => aaa
  if (helm.qname.label[-2] + "." + helm.qname.label[-1]) == TARGETED_DOMAIN:
    data = helm.qname.label[0]
    print("data: %s" % data)
    
    #GetID   (GetSub 0)
    if data[0:8] == "00000000":
      print("  [+] GetID")
      msg = helm.getID();

      s.sendto(msg, peer)
    
    #Alive & send command (batch program.) (GetSub 1)
    elif (data[0:2] == "00" and data[3:8] == "00000") :
      print("  [+] Alive or Send")

      #check botid
      if data[2:3] == helm.botid :
        print("       - botid:%s" % helm.botid)

        msg = helm.getCmd();  #get batch program

        s.sendto(msg, peer)

    #Received data (GetSub 2)
    elif (data[0:2] == "00" and data[3:8] != "00000") :
      print("  [+] receive data")

      #check botid
      if data[2:3] == helm.botid :
        print("       - botid:%s" % helm.botid)

        msg = helm.recvData(data);

        s.sendto(msg, peer)
      

    else:
      pass;

GetSub の意味については検体を確認してください。

Helminth から受信した実行結果をデコードする python コード

  def recvData(self, qdata): # qdata はドメイン名の最初のラベル
    botid = qdata[2:3]
    cmdid = qdata[3:5]  #fileid
    partid= qdata[5:8]  #partid (base36)
    rand  = qdata[8:11] #rand data (base36)
    data  = qdata[11:]  #txt data

    for dec in [(i+j) for (i,j) in zip(data[::2], data[1::2])]:
      encstr = "%" + dec
      print("%s" % urllib.unquote(encstr))

※このコードは partid の整列をしてないので注意

検体

Helminth DNS client's (dns.ps1) md5 hash:
541d10027191b062c4c534b82686639c

その他

質問は @shutingrz までお願いします。
パケットが欲しい人がいればその旨を伝えてください。
C2 サーバが欲しい人がいれば・・・私と友好関係を築いてください・・・。

unboundが保存するキャッシュ情報について

dump_cache

DNSキャッシュポイズニングの勉強中、キャッシュサーバの動作を知るためにキャッシュのダンプをしたくなる時があります。
unboundでは、以下のコマンドでキャッシュ情報を見ることができます。

$ unbound-control dump_cache

START_RRSET_CACHE
;rrset 86394 1 0 1 0
a.gtld-servers.net.     172794  IN      A       192.5.6.30
;rrset 86394 13 1 8 0
.       518394  IN      NS      k.root-servers.net.
.       518394  IN      NS      b.root-servers.net.
.       518394  IN      NS      l.root-servers.net.
.       518394  IN      NS      d.root-servers.net.
.       518394  IN      NS      e.root-servers.net.
.       518394  IN      NS      m.root-servers.net.
.       518394  IN      NS      h.root-servers.net.
.       518394  IN      NS      a.root-servers.net.
.       518394  IN      NS      g.root-servers.net.
.       518394  IN      NS      j.root-servers.net.
.       518394  IN      NS      f.root-servers.net.
.       518394  IN      NS      i.root-servers.net.
.       518394  IN      NS      c.root-servers.net.
.       518394  IN      RRSIG   NS 8 0 518400 20160416050000 20160406040000 60615 . pH3jzvLP/4XK8zYrHf9+MUnQra95+J0eSbAo1Z0o46+iSojyaphy/6DJ6zUcPgiZXVF6bsZT/rKdCVy7OMf3aeCvmuGHXkGOHbp2ZQfj5vuLJ5rW/ICoJpWwzXghitvlfk0WpItaLMOwroDLNdqXL4BM5CO0Ndp0Ah+5MUwQ8PY= ;{id = 60615}
;rrset 3598 1 0 3 0
ns.shutingrz.com.       3598    IN      A       133.242.130.136
;rrset 3598 1 0 8 0
www.shutingrz.com.      3598    IN      A       133.242.130.136
;rrset 86398 1 0 1 0
ns2.shutingrz.com.      172798  IN      A       133.242.130.136
;rrset 3592 1 0 7 0
shutingrz.com.  3598    IN      NS      ns.shutingrz.com.

(この内容は抜粋したものです。)


この記事では、ここのキャッシュ情報の信頼度を紹介します。

rrset行

全てのrrsetのキャッシュには、キャッシュをした際のメタデータが付与されています。
各rrsetの上についている「;rrset」から始まる行です。
この;rrsetの読み方を知ることで、キャッシュ情報を知ることができるのです。

;rrsetについてはmanにも記載されていないので、unboundのソースを読む必要があります。
読んだ結果、以下の意味だとわかります。

;rrset [残りのTTL], [RRSetにあるRRの数] [RRSetにあるRRSIGの数] [このRRSetの信頼度(優先順位)※1] [RRSetのセキュリティ状態]

DNSキャッシュポイズニングで最も重要は情報は、※1の「このRRSetの信頼度(優先順位)」です。
この部分の数値に対応するものを以下に記載します。

数値 意味
0 initial value for trust
1 Additional information from non-authoritative answers
2 Data from the authority section of a non-authoritative answer
3 Additional information from an authoritative answer
4 non-authoritative data from the answer section of authoritative answers
5 Data from the answer section of a non-authoritative answer
6 Glue from a primary zone, or glue from a zone transfer
7 Data from the authority section of an authoritative answer
8 The authoritative data included in the answer section of an authoritative reply
9 Data from a zone transfer, other than glue
10 Data from a primary zone file, other than glue data
11 DNSSEC(rfc4034) validated with trusted keys
12 ultimately trusted, no more trust is possible


この数値は大きいほど信頼度が高くなっています。また、この優先順位はRFC2181 5.4.1 Ranking Dataにほぼ対応しています。
Ranking Dataと異なる点については、unboundのソースのutil/data/packed_rrset.hに記載してあります。以下に引用します。

/**
* RRset trustworthiness. Bigger value is more trust. RFC 2181.
* The rrset_trust_add_noAA, rrset_trust_auth_noAA, rrset_trust_add_AA,
* are mentioned as the same trustworthiness in 2181, but split up here
* for ease of processing.
*
* rrset_trust_nonauth_ans_AA, rrset_trust_ans_noAA
* are also mentioned as the same trustworthiness in 2181, but split up here
* for ease of processing.
*
* Added trust_none for a sane initial value, smaller than anything else.
* Added validated and ultimate trust for keys and rrsig validated content.
*/

スタブリゾルバがwww.shutingrz.comのA RRをフルリゾルバ兼キャッシュサーバに問い合わせをし、キャッシュに該当のRRが存在しなかった場合、フルリゾルバはルートから順にwww.shutingrz.comのA RRを問い合わせをします。
問い合わせし、その内容をキャッシュしたときのダンプが記事冒頭にある出力となっています。

各RRSetについて見ていきます。

;rrset 3598 1 0 8 0
www.shutingrz.com. 3598 IN A 133.242.130.136

スタブリゾルバがwww.shutingrz.comのA RRを問い合わせしたので、信頼度が8と、大きくなっています。キャッシュサーバがこれより大きい信頼度を持つRRSetをキャッシュする機会はほぼありません。

;rrset 3598 1 0 3 0
ns.shutingrz.com. 3598 IN A 133.242.130.136

ns.shutingrz.comは、www.shutingrz.comのA RRの権威ある応答に付随するAdditional Sectionに存在したので信頼度は3となっています。

;rrset 86398 1 0 1 0
ns2.shutingrz.com. 172798 IN A 133.242.130.136

ns2.shutingrz.comは、shutingrz.comの委譲元であるgtld-servers.netのNSの、shutingrz.comの委譲応答には含まれていましたが、www.shutingrz.comのA RRの権威ある応答に付随するAdditional Sectionに存在しなかった(Lame Delegation)ので信頼度は1となっており、とても低い信頼度となっています。



参考

この信頼度を利用した委任インジェクション、移転インジェクションについては以下のURLを参考にしてください。
キャッシュポイズニングの開いたパンドラの箱 -1-
キャッシュポイズニングの開いたパンドラの箱 -2-

あるDNSサーバのTTLの短さとLame DelegationについてIPAに報告したら

届出内容を確認したところ、下記の判断理由の通り、本枠組みにおける
脆弱性ではないとの判断に至った為、取扱いを終了させて頂こうと考え
ておりますが、如何でしょうか。

取扱いに問題がある場合は 10 営業日を目処にご連絡をお願い致します。

ただし、取扱いを終了した場合でも、参考情報としてウェブサイト運営
者へ連絡したいと考えております。

【判断理由】

  • ------------------------------------------------------------------

届出頂いた情報は 2 点ありますので、それぞれ分けて判断理由を記載い
たします。

■1. TTL 値が短い点について
A レコードの TTL 値が短いというご指摘に関しまして、ガイドライン
おける「ウェブアプリケーションにおいて、ウェブサイト運営者の不適
切な運用によって、(中略)セキュリティが維持できなくなっている状
態」に該当するか検討いたしました。

まず、参考文献で頂いた情報から、TTL 値が短い事で DNS キャッシュポ
イズニングのリスクが高まる事は同意いたします。

しかし、A レコードの TTL 値につきまして、RFC2181 等を確認した所、
A レコードの TTL 値に関する推奨値等の取り決めはありませんでした。
また、IPA で確認した限り TTL 値が小さい事により DNS キャッシュポ
イズニングに対して脆弱であると言える情報は確認できませんでした。
参考文献の文中に記載されている通り、A レコードのTTL 値が 30 と短
い場合は攻撃が成功する確率が高まります。しかし、文献にもある通り
CDN 等のような意図的に TTL 値を短く設定している場合があります。そ
のため、運営者の設定が不適切かどうかは判断出来ません。

よって、本届出はガイドラインにおける「ウェブアプリケーションにお
いて、ウェブサイト運営者の不適切な運用によって、個人情報等が適切
なアクセス制御の下に管理されておらずセキュリティが維持できなくな
っている状態」には該当しないと判断しました。

■2. Lame Delegation 状態である点について
Lame Delegation 状態によって DNS キャッシュポイズニングが容易にな
るとのご指摘に関してですが、Lame Delegation 状態でない場合に比べ
DNS キャッシュポイズニングに対してリスクが高まることは同意いた
します。ただし、リスクが高まる条件は「カミンスキーアタック」を行
わない手法に限定されると思われます。

Lame Delegation 状態のドメインは権威 DNS サーバへの問い合わせ回数
が正常な状態に比べて増加するため、毒入れが成功する可能性が上がり
ます。しかし、「カミンスキーアタック」によって Lame Delegation 状
態では無いキャッシュサーバへも問い合わせ回数を増加させることがで
きます。そのため、毒入れが成功する確率は最大でも「カミンスキーア
タック」と同等であると判断しました。

「カミンスキーアタック」を実行される事はネットワークの仕組み上防
げない事から「カミンスキーアタック」以上の成功率が考えられる場合、
脆弱性と判断する可能性があります。しかし、本問題を悪用した場合の
功率は同程度の問題であるため、ガイドラインにおける「ウェブアプ
リケーションにおいて、ウェブサイト運営者の不適切な運用によって、
個人情報等が適切なアクセス制御の下に管理されておらずセキュリティ
が維持できなくなっている状態」には該当しないと判断しました。

但し、当該ドメインの設定が「Lame Delegation」状態である事につき
まして、不適切な状態であるためウェブサイト運営者に参考情報として
通知すべきと判断しました。

  • --

1のTTLの短さについての回答は言いたいことはわかるが・・・。
2のLame DelegationによるDNSキャッシュポイズニングに対しての弱さは、カミンスキー型攻撃手法がある以上、今更そんな問題どうでもいいよっていうのがIPAの見解らしい。
なんだかなぁ・・・


追記(2014/12/31)
私がIPAに送った報告内容のうち、lame delegationについて報告した部分を記載します。digコマンドの結果と実在するホスト名は隠しました。改変した内容は[]に囲まれています。

(引用始まり)

以下はa.dns.jpに対して[www.example.jp]のAレコードについて非再帰問い合わせをしたdigコマンドです。

[ここにdigコマンドが入る]

上記のAUTHORITY SETIONのNSレコードのひとつである、 [ns1.example.net] は稼働していません。
これはLame delegationです。


キャッシュサーバが[ns1.example.net]に問い合わせをした場合、[ns1.example.net]は稼働していないので、
応答がありません。その無応答時間を利用してより大量の偽応答をキャッシュサーバに送信することでDNSキャッシュポイズニングがしやすくなります。

(引用終わり)

また、Twitter上で、lame delegationによってリスクが高まるのはlame delegationがどのようなものかによると指摘されましたが、今回はns1.example.netからの応答が返ってこなく、タイムアウトになるケースです。

追記終わり(2014/12/31)