断片

です・ます調が記事によって違ったりするブログ

DNS over Tor

はじめに

DNS over Torが持つメリットとリスクについて書きます。大体ポエムです。

読むのが面倒な方向けに先に結論(持論)を書いておくと、DNS over TorはDNS Leakに対しては有効ですが、名前解決自体は出口ノード依存です。つまり、出口ノードの参照先フルサービスリゾルバがDNSブロッキングを実施していたり、出口ノード自身がMaliciousな場合は本来とは異なる名前解決結果を得る可能性があります。現実でそのようなケースを引き当てることは多くはないですが(全出口ノードのおよそ40%はGoogle Public DNSを参照している)*1、リスクとして把握しておく必要はあります。

DNS over Tor

DNS over TorはTorネットワークを介して名前解決を得るための仕組みです。0.2.0.1-alpha以前*2のTorでは、Polipo(Privoxy)のようなサードパーティのプロキシを用いて実現していましたが、0.2.0.1-alpha以降はTor本体にリゾルバ(TorDNS)が実装されました。そのため、現在では下記のいずれかの方法でTorDNSを使用するのが一般的のようです。

  • dnsmasqのようなローカルキャッシュDNSサーバとTorDNSを併用する

    • torrcのDNSPortを9053にしてTorを起動
    • ローカルキャッシュDNSサーバの上流DNSをTorDNS(localhost:9053)に向ける
  • TorDNS単体で使う

    • torrcのDNSPortを53にしてTorを起動

また、FirefoxChromeのような一般的なブラウザでDNS over Tor および、Tor経由の通信を実現するためには、ブラウザの設定でSOCKS5プロキシをTorのSocks Port(9050)に向け、SOCKS5のリモートDNS機能を有効にするだけです(この場合、DNS over SOCKS5 over Torというような構成になります。DNS over SOCKS5というと語弊がありますが、これについては後述します)。Tor Browser Bundleは既に初めからそのような設定・構成がされているので、DNS Leakを気にする必要はありません。しかし、名前解決が出口ノード依存という点に変わりはありません。ちなみに、tor-resolveコマンドではTor Browser Bundle同様SOCKSを用いた名前解決を行います。

なお、TorはUDPに対応していないため、TorDNS(DNS over Tor)であっても、SOCKSを用いた名前解決(DNS over SOCKS5 over Tor)であっても、実際のDNSUDPパケットを投げているわけではありません。TCPを用いた擬似的な名前解決を行っています。

DNS over TorはA/AAAAレコードにのみ対応しており、TXTやMX、SOAといったレコードには対応していないようです。Tor 0.3.2.10の src/or/dnsserv.c 96行目付近は下記のようになっています。

[tor/src/or/dnsserv.c]

for (i = 0; i < req->nquestions; ++i) {
  if (req->questions[i]->dns_question_class != EVDNS_CLASS_INET)
    continue;
  switch (req->questions[i]->type) {
    case EVDNS_TYPE_A:
    case EVDNS_TYPE_AAAA:
    case EVDNS_TYPE_PTR:
      /* We always pick the first one of these questions, if there is
         one. */
      if (! supported_q)
        supported_q = req->questions[i];
      break;
    default:
      break;
    }
}

TorDNSを使ってみる

ここではTorDNS単体で使う方法で設定を行い、実際にTorDNSを用いて名前解決が行われることを確認してみます。

$ sudo lsof -i:53
COMMAND  PID       USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
tor     3956 debian-tor    7u  IPv4  39295      0t0  UDP localhost:domain
$ dig torproject.org | grep -e "torproject.org." -e " Query time"
;torproject.org.            IN  A
torproject.org.     300 IN  A   154.35.132.71
;; Query time: 531 msec

名前解決時間(Query time)は531ミリ秒でした。当たり前ではありますが、Torを介しているため通常の名前解決より遅いです。この時のlocalhost:53の様子を確認してみます。 (GuardノードのIPアドレスが含まれる部分を * で隠しています)

$ sudo tcpdump -i lo port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
00:28:58.356075 IP localhost.32932 > localhost.domain: 33784+ [1au] A? torproject.org. (43)
00:28:58.357530 IP localhost.59343 > localhost.domain: 32736+ PTR? *.*.*.*.in-addr.arpa. (45)
00:28:58.357684 IP localhost.domain > localhost.59343: 32736 1/0/0 PTR *.ip-*-*-*.eu. (115)
00:28:58.358021 IP localhost.47104 > localhost.domain: 19011+ PTR? 10.0.168.192.in-addr.arpa. (43)
00:28:58.358144 IP localhost.domain > localhost.47104: 19011 NXDomain 0/0/0 (43)
00:28:58.887745 IP localhost.domain > localhost.32932: 33784 1/0/0 A 154.35.132.71 (48)

次に、この名前解決要求を受けてTorが実際にGuradノードのORPort(443)に接続している様子を確認してみます。 (GuardノードのIPアドレスが含まれる部分を * で隠しています)

$ sudo tcpdump -i wlp3s0 port 443
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wlp3s0, link-type EN10MB (Ethernet), capture size 262144 bytes
00:28:58.356395 IP 192.168.0.10.38530 > *.*.*.*.https: Flags [P.], seq 1633253232:1633253775, ack 1193388446, win 1444, options [nop,nop,TS val 3583398 ecr 3185613847], length 543
00:28:58.641147 IP *.*.*.*.https > 192.168.0.10.38530: Flags [.], ack 543, win 1452, options [nop,nop,TS val 3185634151 ecr 3583398], length 0
00:28:58.887383 IP *.*.*.*.https > 192.168.0.10.38530: Flags [P.], seq 1:544, ack 543, win 1452, options [nop,nop,TS val 3185634398 ecr 3583398], length 543
00:28:58.887498 IP 192.168.0.10.38530 > *.*.*.*.https: Flags [.], ack 544, win 1440, options [nop,nop,TS val 3583531 ecr 3185634398], length 0

DNSブロッキングの検証

ここでは実際にDNSブロッキングを行う出口ノードを構築して検証します。とはいえ、実際のTorネットワークで検証するのはtor projectのポリシーに反するので*3、ここではprivateなTorネットワークを構築し、その中で検証します。

github.com

今回は合計7ノードからなるTorネットワークを構築しました。うち5ノードは出口ノードの役割を果たします。

$ docker ps 
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS                                                  NAMES
80f4bf39f34e        antitree/private-tor   "docker-entrypoint..."   2 hours ago         Up 2 hours          80/tcp, 9001/tcp, 9030/tcp, 9051/tcp                   private-tor-network_hs_1
9b8680f38efb        antitree/private-tor   "docker-entrypoint..."   2 hours ago         Up 2 hours          7000/tcp, 9001/tcp, 9030/tcp, 9051/tcp                 private-tor-network_exit_1
0b0b242adf15        antitree/private-tor   "docker-entrypoint..."   2 hours ago         Up 2 hours          7000/tcp, 9001/tcp, 9030/tcp, 9051/tcp                 private-tor-network_relay_1
2bed3aa7b897        antitree/private-tor   "docker-entrypoint..."   2 hours ago         Up 2 hours          9001/tcp, 9030/tcp, 0.0.0.0:9050-9051->9050-9051/tcp   private-tor-network_client_1
ff78de4d068d        nginx                  "nginx -g 'daemon ..."   2 hours ago         Up 2 hours          80/tcp                                                 private-tor-network_web_1
8910c7f6a786        antitree/private-tor   "docker-entrypoint..."   2 hours ago         Up 2 hours          7000/tcp, 9001/tcp, 9030/tcp, 9051/tcp                 private-tor-network_da2_1
01fd20bbf316        antitree/private-tor   "docker-entrypoint..."   2 hours ago         Up 2 hours          7000/tcp, 9001/tcp, 9030/tcp, 9051/tcp                 private-tor-network_da1_1
5e9709373409        antitree/private-tor   "docker-entrypoint..."   2 hours ago         Up 2 hours          7000/tcp, 9001/tcp, 9030/tcp, 9051/tcp                 private-tor-network_da3_1

これらの全ての出口ノードはブロッキングを行うフルサービスリゾルバ(dockerコンテナとは別に構築したunbound)を参照します。ブロッキングの内容についてはtorproject.orgのAレコードに対して0.0.0.0を返す仕様とします。

[unbound.conf]

server:
    verbosity: 1
    interface: 0.0.0.0
    access-control: 172.18.0.0/24 allow
    access-control: 192.168.122.0/24 allow
    access-control: 127.0.0.1/32 allow

    do-daemonize: no
    chroot: ""
    username: ""
    directory: ""
    logfile: ""
    pidfile: "unbound.pid"

    local-data: "torproject.org. IN A 0.0.0.0"

クライアントからtor-resolveコマンドを実行し、torproject.orgの名前解決を行うと0.0.0.0が表示されることが確認できます。

$ sudo lsof -i:9050
COMMAND     PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
docker-pr 29174 root    4u  IPv6 382567      0t0  TCP *:9050 (LISTEN)
$ tor-resolve torproject.org
0.0.0.0

実験用Torネットワークを構築する方法として、他にもネットワークシミュレータを使用する方法があり、例えばShadowがあります。Shadowは離散事象(discrete-event)ネットワークシミュレータの一種です。TorやBitocinといった実際のアプリケーションのシミュレーションに適しており、単一のマシン上で、実際のTorネットワークに近い構成で実験・検証を行うことができます。ただし、Shadowはアプリケーションごとにプラグインを作成する必要があり、Torに関してもshadow-plugin-torを導入する必要があります。Tor自体の開発においてネットワークの動作検証がしたい、という場合はこちらを使うと良いと思われます。

shadow.github.io

github.com

Bad Exit

不正なフルサービスリゾルバを参照している出口ノードや出口ノード自身がMaliciousな場合はBad Exitフラグが付加されるのでサーキットのパス選択時に弾かれるのではないか*4、と考えた方もいるかと思います。確かにその通りで、実際OpenDNSをフルサービスリゾルバにしている出口ノードがBad Exitとして弾かれるケースが多いようです*5。ただし、Bad Exitのラベル付加はDirectory Authorityのオペレータや彼らにボランティアとして協力する人々によって運営されているので、ネットワーク上で自動検出が行われるわけではありません。ちなみにBad Exitを自動検出するresearch projectとして、spoiled onions*6があります。このresearch projectで開発されたプロダクトであるexitmapについては以前記事を書きました。

epcnt19.hatenablog.com

リスクに対する対策

「名前解決に必ずTorを用いる」と前提した上でのリスクに対する対策を考えてみました。

  • torrcのExcludeNodesとExcludeExitNodesを適当に調整する。

  • torrcのExitNodesで信頼できる出口ノードを指定する。

    • あまりやらない方が良さそう。
  • DNS over TLSを使う

    • 出口ノードに名前解決を依存させないかつ、UDPでない(=TCP)な方法がDNS over TLS over SOCKS5 over Torとなる。TLSにするのは同時にMaliciousな出口ノードによるDNSレコード改竄と盗聴を防げるため。TCPに対応したローカルキャッシュサーバとSOCKS5にリダイレクトするProxyを手元に設置すれば良さそう(未検証)

3つ目の方法については未検証ですが、redsocksのようなプロキシと組み合わせることで実現できるものと思われます。未検証なのでまた別の機会に検証します。

github.com

参考

tor.stackexchange.com

tor.stackexchange.com

*1:We also find that a set of exit relays, at times comprising 40% of Tor’s exit bandwidth, uses Google’s public DNS servers - https://nymity.ch/tor-dns

*2:0.2.0.1-alphaは2012年頃のリリースバージョンであり、0.2.0.xのTorは現在のTorネットワーク上では動作しない https://blog.torproject.org/end-life-tor-020x-branch

*3:Should I snoop on the plaintext traffic that exits through my Tor relay? - No - https://www.torproject.org/eff/tor-legal-faq.html.en

*4:Bad Exitは全Directory Authorityのうち、半分以上が承認する必要がある [2.2.1. Choosing an exit] - https://gitweb.torproject.org/torspec.git/tree/path-spec.txt?id=426e9ac1069ee843000aaeed9260ba4c9733af00#n184

*5:OpenDNSはユーザ保護の目的で異なるDNSレコードを返す場合があるらしい - [What specifically causes an Exit to get a Bad Exit flag?] https://tor.stackexchange.com/questions/253/what-specifically-causes-an-exit-to-get-a-bad-exit-flag/254?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

*6:spoiled onions - https://www.cs.kau.se/philwint/spoiled_onions

Torのサーキット生成ルール

はじめに

Torがサーキットを生成する際にどのようなルールで各ノードを選択するのか気になったので調べた.torspecの2.2項(Path selection and constraints)に書いてあった.

選択のルール

  • 1.同じパス上で同じノードを2度選択することはない.

  • 2.同じファミリの中で複数のノードを選択することはない.

  • 3./16のサブネットの中で複数のノードを選択することはない.

  • 4.有効でないノード(Validフラグを持たないノード)または、実行されていないノード(Runningフラグを持たないノード)を選択することはない.

  • 5.Torの接続に使用する入口ノードはGuardノードでなければならない.

2について、各ノードは"family"というエントリを持っていて、例えば2つのTorノードがfamilyエントリにお互いのノードを持っている場合、それらのノードは同一のfamilyといえる.

4について、これは設定(torrc)によって変更が可能.デフォルトの設定では、non-validなノードに関してはrendezvousノードとmiddleノードの選択において許可されている.

5について、Guardノードとは長期間運用の実績と適切な帯域を持つノードのこと(Guardフラグを持つ).入口ノードはTor利用者のグローバルIPアドレスを直接見ることができるため、信頼性の高いノード(=Guardノード)が求められる.

Guard・Exitノードに関しては帯域幅の割合と利用者が選択している位置(torrcのEntryNodes項目およびExitNodes項目)に応じて重み付けがなされ、決定される.さらに、次のルールのうち1つ以上を考慮してサーキットを生成する場合がある.

  • 1.全てのIntroductionサーキットとRendezvousサーキットの生成には安定したノード(Stableフラグを持つノード)が選択されるべきである.

  • 2.長期間の接続が予想される場合には安定したノードが選択されるべきである.

  • 3.DNS(DNS over Tor)を使用する場合には、torrcのExitPolicyが"reject *:*"でないExitノードが必要である.

  • 4.DNSの逆引きにはeventdnsに対応したバージョンのTorが必要である(Tor 0.1.2.1-alpha-dev以降)

  • 5.全ての接続には、接続先アドレスとポートをポリシーによってrejectしていないExitノードが必要である.

1について、IntroductionサーキットとRendezvousサーキットはHidden Serviceにアクセスする際に生成されるサーキットでRendezvousノードは利用者とHidden Serviceのサーバの中間地点にあたる.詳細に関してはこちら(Tor : Onion Service Protocol)を参照のこと.

2について、利用者が長期間接続するかどうかは接続時のリクエストポートを見ることによって判断していて、以下のポートの場合は安定ノードが選択されるようである.
21, 22, 706, 1863, 5050,5190, 5222, 5223, 6667, 6697, 8300

おわりに

他にもBad Exitが有効なExitノードは選択されないようになっている.Torの実際のソースコードを読んで確認したわけではないので今後時間があれば確認・検証していきたい所存.

参考

tor.stackexchange.com

tor.stackexchange.com

DLLインジェクションの検証

これはMCC Advent Calendar10日目の記事です.
前回はUm6ra1(@v1ru5) さんによる,LinuxのUSBドライバを書いてみよう ~RTL2832uでLチカ~でした.

はじめに

本記事では,DLLインジェクションを実際に実装・検証していきます.DLLインジェクションとは,Windowsにおいて,プロセスに意図しないDLL(Dynamic Link Library)を埋め込む攻撃手法です.この手法はUser Mode Rootkit等のマルウェアでよく用いられるテクニックでもあります.

環境

以下の環境で検証を行いました.実装はC++を使用しました.

OS Windows10 Pro x86-64
Visual Studio Community 2015 Version 14.025431.01 Update 3

手順

基本方針としては,DLLパスを攻撃対象プロセスの仮想アドレス空間のメモリ領域に書き込み,リモートスレッドを生成する形でDLLコードを実行します.具体的には以下の手順で攻撃対象へDLLインジェクションを行います.

1. プロセスへのアタッチ -> OpenProcess()
HANDLE OpenProcess(
  DWORD dwDesiredAccess,  // アクセスフラグ
  BOOL bInheritHandle,    // ハンドルの継承オプション
  DWORD dwProcessId       // プロセス識別子
);

https://msdn.microsoft.com/ja-jp/library/cc429278.aspx

2. プロセスの仮想アドレス空間内のメモリ領域確保 -> VirtualAllocEx()
LPVOID VirtualAllocEx(
  HANDLE hProcess,         // 割り当てたいメモリを保持するプロセス
  LPVOID lpAddress,        // 割り当てたい開始アドレス
  DWORD dwSize,            // 割り当てたい領域のバイト単位のサイズ
  DWORD flAllocationType,  // 割り当てのタイプ
  DWORD flProtect          // アクセス保護のタイプ
);

https://msdn.microsoft.com/ja-jp/library/cc430225.aspx

3. 確保済みメモリ領域へDLLパスのコピー -> WriteProcessMemory()
BOOL WriteProcessMemory(
  HANDLE hProcess,               // プロセスのハンドル
  LPVOID lpBaseAddress,          // 書き込み開始アドレス
  LPVOID lpBuffer,               // データバッファ
  DWORD nSize,                   // 書き込みたいバイト数
  LPDWORD lpNumberOfBytesWritten // 実際に書き込まれたバイト数
);

https://msdn.microsoft.com/ja-jp/library/cc429067.aspx

4. リモートスレッドの生成(DLLコードの実行) -> CreateRemoteThread()
HANDLE CreateRemoteThread(
  HANDLE hProcess,        // 新しいスレッドを稼働させるプロセスを識別するハンドル
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
                            // スレッドのセキュリティ属性へのポインタ
  DWORD dwStackSize,     // 初期のスタックサイズ (バイト数)
  LPTHREAD_START_ROUTINE lpStartAddress,
                           // スレッド関数へのポインタ
  LPVOID lpParameter,     // 新しいスレッドの引数へのポインタ
  DWORD dwCreationFlags,  // 作成フラグ
  LPDWORD lpThreadId      // 取得したスレッド識別子へのポインタ
);

https://msdn.microsoft.com/ja-jp/library/cc429075.aspx

CreateRemoteThread関数の実行において,lpStartAddressにLoadLibraryのアドレス,lpParameterにプロセスの仮想アドレス空間のメモリ領域に書き込まれたDLLパスのアドレスを指定するようにします.こうすることでリモートスレッドのエントリポイントがLoadLibraryによってロードされたDLLのDllMain関数となります.

HMODULE LoadLibrary(
  LPCTSTR lpFileName   // モジュールのファイル名
);

https://msdn.microsoft.com/ja-jp/library/cc429241.aspx

今回は検証用DLL(dllexample.dll)をメモ帳(notepad.exe)にインジェクションします.検証用DLLのDllMain関数部分は以下の通りです. gist.github.com また,インジェクション実行のプログラム(injector.cpp)は以下の通りです. gist.github.com 以上のプログラムを実行すると以下のような結果になり,メモ帳に対してDLLインジェクションが成功したことが確認できました. f:id:epcnt19:20171209221922p:plain

参考

おわりに

DLLインジェクションの攻撃手法自体は以前から知っていましたが,手を動かして検証したことがなかったのでやってみました.

次回はsasamijpさんによる,街中謎解きゲームの話です.
今年は某先輩専用のAdvent Calendarが開催されなかったことが残念でなりません.

セキュリティ・ミニキャンプ in やまなし 2017 に参加してきた

9月24日に開催されたセキュリティ・ミニキャンプ in やまなし の専門講座にチューターとして参加してきた.ミニキャンプは23日に一般講座も開催していたがその時は専門講座の会場設営などを行っていた(実際は電車を乗り過ごして一番遅く着いたのでほとんど設営は終わっていた).今回は専門講座で行われた技術的な内容について書いていく.

1. 手作りパケットでWebサーバと通信しよう

Scapyでhttp通信を行うプログラムを書いた.事前課題ではコネクション確立,コネクション確立後の通信,コネクションの切断の際のシーケンス番号(seq),応答確認番号(ack)の変化について調べる課題とNetcat,PythonのSocketに関して基本的な操作方法を覚えてくる課題が出された.講義では最終的にコネクション確立,確立後のHTTPリクエスト,コネクション切断までの一連の流れを書き,tcpdumpwiresharkを使用しながら実際にパケットの流れの観測と検証を行った.

gist.github.com

(www.example.comというのは今回記事として書く上での適当なホスト名であり講義で実際に使用したわけではない)

TCPのシーケンス番号,応答確認番号については,個人的にはこの辺りの説明がわかりやすいと思う.TCPの機能は正直あまり理解していない部分が多いのでRFCを読もうと思う.ちなみに知り合いのとあるイケメンパケリストはRFCの文書->疑似言語->プログラミング言語みたいな感じで翻訳していけばTCPプロトコルスタックが実装しやすいと言っていた気がする.

OSがRSTパケット(RST/ACK)を送信してしまう

これはカーネルTCPスタックがSYNを認知していない状態でサーバからのSYN/ACKを受けるため.TCPスタックがはじめのSYNを認知できないのはScapyがRawSocket経由でパケットの送信を行っているためである.ということでScapyで3ウェイハンドシェイクを行うためにはiptablesでRSTをDROPする必要がある.

$ sudo iptables -I OUTPUT -p tcp --tcp-flags RST RST -j DROP

2. ローカルプロキシで遊ぼう

講師の先生が自作したローカルプロキシ(Nodejs製)を使って与えられた課題を解決するようにプロキシのプログラムを改変した.課題は以下の通り.

必須課題

1. レスポンスがHTMLだった場合,"Bad"という文字列を"Good"に置換して返却する.
2. Basic認証を常に突破できるようにする.(userid/passwordは知っている状態)

1はヘッダのContent-Type行がtext/htmlだった場合にボディ中の"Bad"を"Good"に書き換える.2は通常時のBasic認証のHTTPを観察し,Authorization行を常にヘッダに追加するようにすればよい. これはわかっていてもJavaScriptがわからず沼にはまっている人が多く私もJavaScriptの経験が浅いので結構沼にはまった. JavaScriptやっていきたい.

ちなみにこれらは必須課題で任意課題(発展課題)もある.そちらの方はまだ検証中なので追々追記していく.

感想

初めてチュータを経験したが参加者とは違った側面の面白さや学びがあった.セキュリティ・キャンプは全国大会・地方大会含め参加者として何度かお世話になったので今後は新たな参加者の方をサポートしていく立場に回れればと思う.(一般 | 専門)講座参加者・講師・チュータの皆様,開催にあたり支援して下さった皆様,お疲れ様でした.

exitmap

はじめに

TorがOnionRoutingという仕組みで秘匿性を保っていることは既に皆さんご存知かと思います.そしてOnionRoutingにおいて,Torネットワークからクリアネット(非Torネットワーク)への架け橋となる出口ノード(ExitNode)の存在は非常に重要で,エンドtoエンドでの暗号化通信を行っていない場合,ExitNodeにはクライアントの通信内容が筒抜けになります.Torネットワークの各ノード(EntryNode,BridgeNode,RelayNode,ExitNode)は誰でもなることができるため,悪意をもって盗聴や改ざんを行うExitNodeの存在が非常に脅威となります.そこで,今回は悪意のあるExitNodeや,そういった疑いのあるExitNodeを探索するツールであるexitmapについて紹介します.

exitmap

exitmapはスウェーデンのカールスタード大学 PriSecグループとオーストリアのSBA Researchの共同研究によって2014年に開発されたもののようです. Pythonベースのプログラムになっており,内部的にStemを使用しているため,Tor本体をインストールしておく必要があります.

https://www.cs.kau.se/philwint/spoiled_onions/ github.com

イメージとしては,exitmap内でモジュール(例えば,ファイルのダウンロード・Webサーバへの接続等を行うモジュール)が評価対象のExitNodeを通じて実行され,その実行結果からNegative/Positiveを判定する感じです.モジュールは各自で開発することもできます.

使ってみる

環境

$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.10
DISTRIB_CODENAME=yakkety
DISTRIB_DESCRIPTION="Ubuntu 16.10"
$ uname -mr
4.8.0-52-generic x86_64

インストール

$ git clone https://github.com/NullHypothesis/exitmap
$ cd exitmap
$ pip install -r requirements.txt
$ cd ..

使い方

$ ./exitmap/bin/exitmap (モジュール名) のように指定します.デフォルトで入っているモジュールには以下のようなものがあります.

  • checktest
    • https://check.torproject.org/に接続し,Torと判定されるかチェックする.(ExitNodeがプロキシを刺しているかチェックする)
  • testfds
    • 単純なWebページの内容を取得できるかチェックする.(ExitNodeのファイルディスクリプタが正しく機能しているかチェックする)
  • dnspoison
    • 名前解決を行い,受信したAレコードと予想されるAレコードの比較を行う.(ExitNodeがDNSスプーフィングを行っているかチェックする)
  • dnssec
    • ExitNodeがDNSSECを検証するかどうかチェックする.
  • patchingCheck
    • ファイルのダウンロードを行い,改ざんをチェックする.
  • cloudflared
  • rtt
    • RTTをチェックする.

正直なところ,各モジュールの役割についてはソースコードを読んだ方が早いです.モジュールは./exitmap/src/modules/以下に配置されています. また,exitmap本体にもいくつかのオプションがあります.詳細はhelpオプションで確認できるので,ここではいくつかの重要なオプションについて紹介します.

  • --country [Country Code]
    • ExitNodeの国を指定するオプションです.日本であればJPのように指定します.
  • --first-hop [FingerPrint]
    • EntryNode(first hop)を20バイトのフィンガープリントで指定します.
  • --exit [FingerPrint]
    • ExitNodeを20バイトのフィンガープリントで指定します.
  • --build-delay [Seconds]
    • Torのサーキットを生成する際に任意の秒数間休止します.

以下の例は全ての出口ノードに対してdnspoisonモジュールを実行した例です.今回はDNSスプーフィングの疑いのあるExitNodeは発見できませんでした.

https://gist.github.com/epcnt19/84d753545ac715a569e31cc44fed883f#file-exitmap

おわりに

悪意のあるExitNodeを発見するためには,exitmapによる継続的なスキャンや,モジュールの拡張・自作を行う必要がありそうです.ただし,継続的なスキャンという点に関してはスキャンがTorネットワークへ負荷を与えているという点に注意する必要があります.

独り言

全出口ノード数は800〜900程度だそうですが,案外少なくないですか(調べてみたら,ここ数年で結構減少してるっぽい)

https://metrics.torproject.org/relayflags.html

DECAFのセットアップ

DECAFの環境を構築したので,再度構築する時のための自分用メモ.
github.com

環境

  • ホストOS Ubuntu16.10(LTS) 64bit
  • ゲストOS① Ubuntu14.04(LTS) 64bit
  • ゲストOS② Windows XP 32bit

ホストOSの上でゲストOS①を動作させ(Virtualbox),その上でゲストOS②を動作させる(DECAF(QEMU)). ホストOS上で直接DECAFを動作させなかったのは、Ubuntu16.10上でのビルドが上手く行かなかったためで,現在原因調査中.

パッケージのインストール

$ sudo apt-get update
$ sudo apt-get install qemu binutils-dev libboost-all-dev
$ sudo apt-get build-dep qemu
$ sudo apt-get -y install build-essential linux-headers-$(uname -r)
$ sudo apt-get install zlib1g-dev libssl-dev libncurses5-dev
$ sudo apt-get install libcurl4-openssl-dev libexpat1-dev libreadline-gplv2-dev
$ sudo apt-get install uuid-dev libfuse-dev bzip2 libbz2-dev git
$ sudo apt-get -y install automake1.9 autoconf libtool
$ git clone https://github.com/sycurelab/DECAF
$ cd DECAF/decaf
$ ./configure
$ make
$ cd ..

イメージの作成

  • WindowsXP(modernIE)のVMware用イメージをダウンロードした.
  • VMWare用イメージ(vmdk)をqcow2イメージに変換したものでDECAFを起動しようとしたところ,No bootable deviceと出てしまい,ブートできなかった.原因調査中.
  • qcow2イメージではなく,rawイメージに変換したものを使用したところ,問題なく起動できた.

$ unzip IE8.XP.For.Windows.VMware.zip
$ qemu-img convert -f vmdk -O raw IE8_-_WinXP-disk1.vmdk winxp.img
$ ./decaf/i386-softmmu/qemu-system-i386 -monitor stdio -drive file=./winxp.img

さいごに

今後は以下を参考にプラグイン開発をやっていく予定.

追記

https://groups.google.com/forum/#!topic/decaf-platform-discuss/iLw8E7p559w

参考

記念撮影

f:id:epcnt19:20170501140856p:plain

onionアドレスの生成

TorのHiddenServiceの識別子として用いられるonionドメインのアドレス(以下,onionアドレス)ですが,どのように生成されるのか気になったので調べました.

仕組み

知りたかったことは以下の記事にほとんど載っていました.

上記の記事によると,

  1. RSA(1024bit)の公開鍵と秘密鍵のキーペアを作成する.
  2. 公開鍵をDERエンコードする.
  3. DERエンコードされた公開鍵からSHA1ハッシュ(160bit)を生成する.
  4. 生成したハッシュ値の前半半分(80bit)を取り出し,Base32エンコードする.

という手順で生成しているようです.Base32は40bitを8文字に変換するエンコード方式で,80bitのハッシュ値から16文字の文字列にエンコードされ,これがonionアドレスとなるようです.一般的な手順でHiddenServiceの設定を行った場合,Tor側が自動でonionアドレスと秘密鍵を生成してくれます.ちなみにこれらはtorrcのHiddenServiceDir項目で指定したパスの配下にhostname,private_keyという名前で生成されます.

任意の文字列をonionアドレスにしたい

例えば,facebookcorewwwi.onion(FacebookのHiddenService)のように任意の文字列をonionアドレスに指定するための方法ですが,指定したパターンが出現するまでキーペアを生成し続ける(ブルートフォース)作業を行うことによって実現できます.そのようなツールは既にいくつも存在して,Shallotやscallionが有名なようです.

github.com github.com

試しにShallotでアドレスを生成してみたところ,1-5文字程度であればある程度高速にonionアドレスを算出できました.ちなみに,facebookcorewwwi.onionは8文字ですから一般的なマシンでのブルートフォースではまず不可能でしょう.

おわりに

TorのHiddenService,RelayNode,ExitNodeの設定方法をブログに書いていなかったのでそのうち書きます.とはいえ,HiddenService,RelayNodeに関しては以下のページに基本的な設定方法がある程度説明されているので,自分のメモ用程度にしか需要はないと思いますが.

Hidden Service - Hideki Saito Wiki Japanese
Linuxに安全にtorリレーをインストールする方法 - Qiita
Ubuntu14/CentOS6xにtor入れてrelayサーバーにする - Qiita