RapperBotとは
NICTでは、日本国内のNVR/DVRなどのIoT機器を標的として感染活動を行い、DDoS攻撃を実施するRapperBotと思われるボットネットの攻撃キャンペーンを観測しました。 RapperBotは、Miraiと呼ばれるIoTマルウェアの亜種であり、Miraiのソースコードを改良して開発されている形跡がサンプルに見られます。感染活動の目的は主にDoS攻撃ですが、過去にはクリプトジャッキングを新たに取り入れた活動も観測されています。今回観測したキャンペーンの中で、特定のホストに対するDoS攻撃を観測することに成功しました。
本ブログでは、今回観測されたRapperBotの感染源となる標的機器及びボットネットのコアな機能と、DoS攻撃の標的について紹介します。
キャンペーンの概要
直近で確認できたRapperBotのキャンペーンの変遷を図に示します。NICTでは2023/12頃から活動が観測され始めました。当初は感染活動を拡大するためのスキャン活動が確認できましたが、2024年に入ったあたりからスキャンが確認できなくなりました。そのため、感染しているホストを特定することが難しくなってきていると考えられます。また、その時期からC2サーバに接続するために名前解決を行うようになってきており、2024年に入ってからサンプルに大きな変化が見られました。
図中で言及している「miraiの特徴」とは、スキャンに使用するSYNパケットの「あて先アドレス」と「シーケンス番号」が等しいことを指しています。
感染活動
RapperBotは、国内でも販売されているNVRの未公開の脆弱性を悪用して感染活動を実施しています。感染活動をする際、無差別に脆弱性を悪用するペイロードをばらまいているわけではなく、標的となる機器かどうか事前に調査・判別してからペイロードを送り込んできています。そのため、感染活動の把握自体が困難です。NICTでは、実機もしくは実機と攻撃者に思わせるハニーポットを用意して攻撃者の活動を観測し、マルウェアのサンプルを入手しています。
マルウェアの分析
今回のキャンペーンではいくつかのサンプルが確認できました。本ブログでは主に、2024年3月ごろに観測され最も活発にDoS攻撃が観測されたサンプルである「b3caf173f7e59eb180376b7f3b77efd9509aa29f68c6e4b35fbbd3afda166a95」についての分析結果を説明します。
文字列の難読化
RapperBotはMirai同様、いくつかの文字列が難読化されています。難読化自体はシングルバイトのXORという単純な方法によって行われていますが、各文字列に対して異なるバイト値を使うという点が、他のMirai亜種にはあまり見られないユニークな特徴でした。
難読化された文字列は、付録で紹介するスクリプトを実行することで取得することができます。取得できた文字列の中には、いくつかのファイルパスや攻撃者のC2を表す文字列が確認できます(C2を表す文字列は、「\」でデファングしています)。また、RapperBotが感染成功した際にコンソールに出力するメッセージである「listening tun0」も確認できます。
ntpclient
listening tun0
/etc/resolv.conf
nameserver
/proc/net/udp
/proc/
/exe
/fd
tvoewev\.link
keipyeb\.africa
dfubdf\.click
/bin/ntpclient
avahi-daemon
/dev/watchdog
avahi-daemon
/bin
/sbin
/usr/bin
/usr/sbin
/dev/watchdog
C2通信
RapperBotは、C2の情報を難読化して保有していました。ここでは、実際にC2サーバとどのようにして通信を行い、目的であるDoS攻撃まで実行するのかについて説明します。
C2サーバと主に下記4種類のメッセージのやり取りを実施します。それぞれのメッセージについて説明します。
- ボットオンラインメッセージ
- ボットハートビートメッセージ
- サーバハートビートメッセージ
- コマンドメッセージ
ボットオンラインメッセージ
RapperBotがC2サーバに接続できたときに最初に送信するメッセージです。下記のような感染端末の情報をC2サーバに送信して、感染に成功したことをC2サーバに伝えます。
- ハードコードされた値: 3 bytesの値で、「b”\x73\xfe\x05"」
- ローカルIPアドレス: 4 bytes
- グローバルIPアドレス: 4 bytes、stunによって取得
- 引数の値: 32 bytes、実行時の第一引数の値
- ホスト名: 32 bytes
ボットハートビートメッセージ
ボットは最初のオンラインメッセージを送信した後、サーバとの接続を維持するために定期的にハートビートにあたるメッセージをC2サーバに送信します。
送信するメッセージは4 bytes長で、最初の3 bytesは「b”\x00\x01\x00”」で固定されており、最後の1 byteは変化します。
サーバハートビートメッセージ
サーバは、ボットとは異なるハートビートメッセージをボットに対して送信します。メッセージ長は3 bytesで、値は「b”\x00\x00\x00”」で固定されています。
コマンドメッセージ
C2サーバからボットに特定の動作を行うためのメッセージです。下記は、実際に確認したコマンドメッセージのサンプルです。
コマンドメッセージは下記のような構造になっていると考えられ、先頭1 byte目はボットにどのような動作を行うか指示するコマンドIDです。
- コマンドID : 1 byte、0x01, 0x02, 0x03と3種類存在
- コマンド長 : 2 bytes
- 攻撃間隔 : 4 bytes
- 攻撃手法 : 1 byte、UDPやGRE IPなど、どのようなDoS攻撃を実行するかを指定
- ターゲットアドレス数: 1 byte
- ターゲットアドレス : 4bytes
- ネットマスク : ターゲットアドレスのネットマスク値
- オプション数 : 1 byte、送信データ長やあて先ポートなどのオプションを指定する数
- オプションID : 1 byte、使用するオプションを指定
- オプション長 : 1 byte、オプションの値の長さ
- オプションの値 : n bytes、オプション長で指定されたバイト長
観測中、0x02以外で始まるコマンドは確認できなかったため、残りのコマンドIDの動作について詳細は不明です。サンプルを分析した結果、下記のような動作をすると考えられます:
- 0x01 : C2接続を終了
- 0x02 : DoS攻撃の実行
- 0x03 : プロセスをkill
サンプルのコマンドは、特定のIPアドレスにDoS攻撃を実行するコマンドでした。実際に確認できた攻撃の様子を示します。
他にも、UDPを使用した攻撃、UDPでカプセル化したGREパケットによる攻撃など、様々なDoS攻撃を観測しました。
DoS攻撃の分析
「マルウェアの分析」の章で、本ブログで紹介したRapperBotがC2とどのような通信を行うかについて説明しました。NICTでは、RapperBotのC2通信を模倣してコマンドを解析するツールを開発し、RapperBotの攻撃者がどこを標的としてDoS攻撃を実施しているかを明らかにしました。ツールはRustで書いており、取得・解析したコマンドをデータベースに登録して可視化できるようにしています。本章では、取得・解析したコマンドベースでRapperBotのDoS攻撃の実態について、少し掘り下げて紹介していきます。
2024/3/19~2024/4/22 のおよそ1カ月程度の期間においてRapperBotのC2サーバを追跡・監視し、DoS攻撃を行うコマンドの収集を行いました。その結果、4,630件のコマンドを取得することができました。ターゲットのアドレスは1つのコマンドで複数指定可能であり、アドレスごとに分けると9,772件でした。コマンドツールの実行中、C2サーバが変更になったこともあり、データが収集されていない時期があることはご了承ください。
3/26と、4/18にピークが来ていることが分かります。標的となったIPアドレスの国ごとの割合は下記のとおりです。
中国が半数弱を占める割合を持っており、RapperBotの攻撃者は主に中国を標的としてDoS攻撃を行っていると思われます。IPアドレスからAS情報を調べると、中国の通信事業者と思われるIPアドレスを標的としていることが分かりました。 また、日本のIPアドレスもいくつか標的に含まれていました。しかし、日本のIPアドレスで標的となっているものは、日本の特定の企業・組織ではなく、クラウドベンダーのIPアドレスが多数を占めていたので、DoS攻撃に関しては割合や標的となるIPアドレスの情報から、日本を特に標的としているわけではなさそうです。
ターゲットアドレスの指定で、最大規模のものはターゲットとするアドレスの数が「56」に指定されていました。加えて、アドレスのネットマスクも単一のアドレスを指す「/32」ではなく「/24」が指定されていたので、かなりの数のアドレス帯のホストに対してDoS攻撃が行われた瞬間があったことが推測されます。コマンドの発生時期はいずれも3/26であり、ターゲットアドレスの国情報はブラジルで、その通信事業者と思われるIPアドレス帯域が標的とされていました。RapperBotを使用して、特定のタイミングで大規模なブラジルへのDoS攻撃が実行されたのではないかと推測されます。使用された攻撃プロトコルは、分析の結果ではTCPではないかと考えられます。
次に、攻撃継続時間についてです。今回紹介しているサンプルのRapperBotの攻撃コマンドはMiraiベースとなっていると考えられ、その場合「攻撃間隔」に当たる4 bytesの値が攻撃の実行時間に当たる値になります。単位はMiraiのソースコードを継承していると思われるので、「秒」であると考えられます。件数の上位10件を下記表に示します。
攻撃継続時間 [秒] | 件数 |
---|---|
60 | 9581 |
100 | 80 |
30 | 53 |
35 | 11 |
20 | 10 |
45 | 8 |
40 | 9 |
300 | 5 |
50 | 3 |
15 | 3 |
攻撃継続時間で最も多い値は「60」であり、全体の98%を占めていました。一番大きな値では「300」という値が使用されていました。この値が使用されているコマンドは5件確認され、いずれも4/22頃に同一かつひとつのIPアドレス宛にUDP攻撃を実行するコマンドになっていました。アドレスやあて先のポート番号で調べるとゲーミングサーバがヒットしたので、RapperBotがこのタイミングで集中的にゲーミングサーバを標的にしていることが判明しました。
最後に、攻撃オプションについてです。DoS攻撃の際に使用するあて先ポートやデータサイズ、送信元ポート・アドレスなどは、オプションIDを指定して設定します。指定しなかった場合はデフォルトの値もしくは、ランダムな値が使用されます。今回取得したコマンドで非常に多く確認できたオプションIDは「0」と「7」でした。それぞれ「データサイズ」と「あて先ポート番号」を意味します。 あて先ポート番号が指定されているコマンドは全体の9割弱で、残り1割程度のコマンドはあて先ポート番号が指定されていませんでした。あて先ポート番号が指定されない場合、あて先ポート番号はランダムな値が使用されます。そのようなコマンドを受信したボットは、ランダムなあて先ポートに対してDoS攻撃を実行します。
まとめ
日本国内の機器を標的として主にDoS攻撃を行うRapperBotの攻撃キャンペーンの紹介とその分析について紹介しました。RapperBotは、Tbotと呼ばれる他のボットネットとは異なり、目立つような活動ではなく、標的を定め目立たぬように活動している様子が観測されています。NICTでは、今後もRapperBotの活動を追跡してレポートしていく予定です。
IoC (Indicators of Compromise: 侵害指標)
マルウェアサンプル
- 4ab29632c2aafe9b927e617240c90007e28b737c8e500fb545a1c748aaebbffe
- a2c2a58995a8d79c4af92a7117d9c3ba5eb2e3b0600a5871b81558fcd7aeb97b
- 42fe6afc957c80a19b82c807cdd31161fd44115dab6553a8c8a321640854f68a
- 26303c7e809dcf507f3292fc850ede9b7d6557eeaaadca9971651b8a2b6bb161
- 8000e9f881c14126491d82c21cb7fa271f9530fd7c94babbe70e53501c83d136
- 19dcec9d15b688e979b19c4ab043dd71ad338da904506084f92af5e21ec71482
- 45992f2904fef00c43979744c000b3eadca45a97eed505959890ff9c5ff8341a
- a4ca46fe5bae9753c53e3a2479bea960c7e9e8e1e89637d73bfa8b21ace843c7
- b3caf173f7e59eb180376b7f3b77efd9509aa29f68c6e4b35fbbd3afda166a95
Command & Control
95.214.27\.202:1111
dbovmix\.xyz:81
167\.99.0.202:1024
tvoewev\.link:1024
103.35.191\.174:1024
ダウンロードサーバ
95.214.27\.202
167.99.0\.202
zyb\.ac
付録
本ブログで紹介したサンプルから難読化された文字列を取得する際に作成したスクリプトです。
import idautils
import idc
# sample: arm7
# sha256: b3caf173f7e59eb180376b7f3b77efd9509aa29f68c6e4b35fbbd3afda166a95
table_init_addr = 0x00008AA0
def table_deobf(table_addr):
table_data_list = []
mnem = idc.print_insn_mnem(table_addr)
opr1 = idc.print_operand(table_addr, 0)
while True:
data_addr = None
data_len = 0
if mnem == "B":
break
if mnem == "LDR" and opr1 == "R2":
data_addr = idc.get_first_dref_from(idc.get_operand_value(table_addr, 1))
nxt_mnem = idc.print_insn_mnem(idc.next_head(table_addr))
nxt_opr1 = idc.print_operand(idc.next_head(table_addr), 0)
if nxt_mnem == "MOV" and nxt_opr1 == "R3":
data_len = idc.get_operand_value(idc.next_head(table_addr), 1)
encode_data = idc.get_bytes(data_addr, data_len)
xor_key = encode_data[-1]
decode_data = ""
for byte in encode_data:
decode_data += chr(byte ^ xor_key)
table_data_list.append(decode_data[:-1])
else:
nxt_mnem = idc.print_insn_mnem(idc.next_head(idc.next_head(table_addr)))
nxt_opr1 = idc.print_operand(idc.next_head(idc.next_head(table_addr)), 0)
if nxt_mnem == "MOV" and nxt_opr1 == "R3":
data_len = idc.get_operand_value(idc.next_head(idc.next_head(table_addr)), 1)
encode_data = idc.get_bytes(data_addr, data_len)
xor_key = encode_data[-1]
decode_data = ""
for byte in encode_data:
decode_data += chr(byte ^ xor_key)
table_data_list.append(decode_data[:-1])
table_addr = idc.next_head(table_addr)
mnem = idc.print_insn_mnem(table_addr)
opr1 = idc.print_operand(table_addr, 0)
return table_data_list
def main():
encode_data_list = table_deobf(table_addr=table_init_addr)
print(encode_data_list)
if __name__ == "__main__":
main()
参考文献
- https://www.fortinet.com/jp/blog/threat-research/rapperbot-ddos-botnet-expands-into-cryptojacking
- https://www.fortinet.com/jp/blog/threat-research/ddos-botnets-target-zyxel-vulnerability-cve-2023-28771