CI/CDツール「Jenkins」のサーバが暗号資産マイニングに不正利用されるリスク
設定不備を抱えたJenkinsの「スクリプトコンソール」が攻撃者に狙われ、暗号資産マイニングなどの活動に不正利用されるリスクを分析します。
- Jenkinsに設定不備があると、攻撃者によってスクリプトコンソールから不正なGroovyスクリプトを起動され、暗号資産マイニング絡みのサイバー犯罪に利用される可能性があります。
- 認証や承認に関する設定不備として、エンドポイント「/script」を攻撃者側に公開してしまうパターンが挙げられます。これは、リモートコード実行(RCE:Remote Code Execution)などの不正操作を誘発します。
- 脆弱なJenkinsサーバを発見した攻撃者は、そこから不正なスクリプトを起動し、暗号資産マイナーのダウンロード、実行に及ぶ可能性があります。さらに、「cronジョブ」や「systemd-run」などのユーティリティによって永続化を図るケースも考えられます。
Jenkinsは、ソフトウェア開発のCI/CD(Continuous Integration and Continuous Delivery:継続的インテグレーションとデリバリ)を支援するオープンソース・ツールであり、テストやビルド、デプロイなどの工程を自動化する機能を備えています。本ツールはユーザに多大なメリットをもたらしますが、設定不備や修正パッチの適用漏れがあると、攻撃者によって暗号資産マイナーやバックドアをインストールされる他、機密情報を窃取される恐れがあります。本稿では、設定不備を抱えたJenkinsの「Script Console(スクリプトコンソール)」が攻撃者に狙われ、暗号資産マイニングなどの活動に利用されるリスクを分析します。
技術分析
Jenkinsのスクリプトコンソールは、Jenkinsサーバ上でGroovyスクリプトを直接実行するための機能を管理者や承認済みユーザに提供します。対象のスクリプトは、Jenkins自身のアクセス権限で実行されます。そのため、比較的高いレベルの操作が可能となります。スクリプトの言語として、JenkinsはGroovyをサポートしています。
Jenkinsのデフォルト設定において、スクリプトコンソール上でGroovyスクリプトを実行できるのは管理者権限を有する承認済みユーザのみであり、そこに匿名ユーザは含まれません。しかし、Jenkinsの全インスタンスが安全に設定されているとは限らず、認証機構が正しくセットアップされていないパターンも考えられます。これに加えて「Sign Up(サインアップ)」や「Registration(登録)」のオプションが有効化されていると、攻撃者によってJenkinsサーバやエンドポイント「script」にアクセスされ、そこからRCE攻撃(リモートコード実行)を実行される可能性があります。そのため、こうしたインターフェースを適切に保護することは、セキュリティ上の必須要件と考えられます。しかし残念ながら、設定不備を抱えたままインターネットに公開されているJenkinsインスタンスも存在し、不正利用に脆弱な状態で放置されています。
今回はサーバ検索サイト「Shodan」を利用し、インターネットに公開されているJenkinsサーバの件数を調べました。その結果を、図2に示します。公開されている全サーバが不正利用のリスクを抱えているわけではありませんが、攻撃上の拠点として利用される可能性があることに注意する必要があります。
仮に攻撃者がJenkinsのスクリプトコンソールにアクセスできた場合、そこから不正なスクリプトを実行し、暗号資産の獲得を目的とした活動に繋げられることが判明しました。図3に、調査時に発見された不正な通信データの例を示します。
攻撃者は、上図の通信データをJenkinsサーバに送信し、Groovy用プラグインの設定不備を突くことで、不正なスクリプトを実行しようとしました。この不正なスクリプトは、Base64でエンコードされています。
以降、本スクリプトの解析結果について述べます。
はじめに本スクリプトは、標的のサーバ上でコマンドパッケージ「BusyBox」が稼働しているかをチェックします。稼働している場合、後続の活動を行わずに処理を終了します。
本スクリプトには「svalid」という名前の関数があり、特定のディレクトリに書き込み権限があるかをチェックします。
本関数は、第1引数で指定されたディレクトリ内に一時的なシェルスクリプト「vinars」を作成した上で、実行属性を付与し、これを起動します。vinars自体は、コンソール上に文字列「ginerd」を出力するだけの単純な内容となっています。この後、vinarsの実行結果を変数「$?」は、直前に実行したコマンドの終了ステータスを表すものです。一連の処理は、指定ディレクトリの内部でスクリプトが実行可能であるかを調べる目的で使用されます。
本スクリプトはさらに、他の暗号資産マイナーと同様、マイニングの効率的な実行に必要なシステムリソースを確保します。そのために、CPUリソースの90%以上を消費しているプロセスを探し、該当するものがあれば、停止します。さらに、休止状態の全プロセスを停止します。
次に本スクリプトは、暗号資産マイナーの配備先として利用可能なディレクトリを探します。まず、現在のユーザがディレクトリ「/dev/shm」での書き込み権限と実行権限を有しているかを、先述の関数「svalid」によってチェックします。本関数が終了ステータスとして0以外の値を返した場合(当該ディレクトリでは書き込みや実行ができないことを示唆)、他のディレクトリを探します。この際、「/proc」と「/sys」は対象外とします。
条件に合ったディレクトリが見つからなかった場合は、「/tmp」を作業ディレクトリとして扱い、その配下にサブディレクトリ「duet」を作成します。このサブディレクトリには、最高権限「777(全ユーザで読み込み、書き込み、実行の全てが可能)」を付与します。
続いて本スクリプトは、対象ディレクトリに暗号資産マイナーのバイナリがすでに存在するかをチェックします。存在しない場合は、当該バイナリをダウンロードし、永続化の手続きを実行します。存在チェックの手段として、下記のSHA256ハッシュ値を確認します。
上図のコマンドが「失敗」に相当するステータスコードを返した場合、ダウンロードツール「wget」を用いて目的のバイナリファイル「cex」を以下のURLから取得します。
https[:]//berrystore[.]me
cexはtar形式のアーカイブであり、暗号化されています。
wgetでファイルをダウンロードできなかった場合は、OpenSSLのオプション「s_client」を利用してSSL/TLSプロトコルでのダウンロードを試みます。
本コマンドは、HTTPSのGETリクエストをサーバに送信して応答データを受信し、その末尾2,481,008バイトを入力ストリーム経由で抽出します。これは、検知回避を意図した動作と考えられます。次に、抽出したバイト列をファイル「cex」として保存します。
「cex」はtar形式のアーカイブをAES-256アルゴリズムで暗号化したものであるため、OpenSLLの機能によってこれを復号します。パスワードからの鍵抽出には、SHA256値を使用します。次いで、復号後のファイルをコマンド「tar」によって展開し、元のファイル「cex」を削除します。最後に、展開されたバイナリファイルに実行権限を付与します。このファイルが、先にコマンド「sha256sum app」で見つけようとしたものに相当します。
本スクリプトは、ジョブスケジューラ「cron」や「systemd-run」を用いて暗号資産マイナーの永続化を図ります。また、システムユーティリティ「flock」を使用し、マイナーのインスタンスが同時に複数起動しないように制御します。
- システムユーティリティ「flock」によってファイル「/var/tmp/verl.lock」をロックし、オプション「-c」で指定されたコマンドのインスタンスが複数起動しないように制御する。
- 複数インスタンスの同時起動を抑止する追加手段として、集計コマンド「awk '!a[$0]++'」を用いてcronジョブ内の重複エントリを全て削除する。
- 上記awkの出力を「crontab -」にパイプ経由で渡す。これによってcrontabの内容を、フィルタリング済みの一意なcronジョブエントリで更新する。
上図の「systemd-run」を含むコマンドは、カレントユーザのD-Busセッション・バスに対応するソケットファイルのアドレスを、下記の環境変数に格納します。
DBUS_SESSSION_BUS_ADDRESS
これにより、ユーザ・セッション内で稼働するアプリケーションやサービス間で、D-Bus経由の通信が可能となります。
続いて攻撃者はsystemd-runを利用し、暗号資産マイナーが毎時0分に起動するように、スケジュールを登録します。また、ユーティリティ「flock」のロック機能を用い、複数インスタンスの同時起動を抑止します。
さらに攻撃者は、暗号資産マイナーが期待通りに起動しなかった場合に備え、別の手段を併せて用意しました。
このスクリプトが実行する処理の内容を、下記に示します。
- マイニングのrig IDを設定するための文字列をファイル「strptr」に書き出す。
- コマンド「trap '' SIG」により、シグナル「SIG」を無視するように制御する。これは、特定のシグナルによってスクリプトが停止されないようにするための措置と考えられる。
- コマンド「( sleep 40; kill -9 [PPID )」については、サブシェルとしてバックグラウンドで稼働する(直後の「&」指定による)。本サブシェルは、40秒のスリープ後に、シグナル「SIGKILL(強制終了)」を親プロセス(PPID)に向けて送信する。これは、一定時間が経過した後に、スクリプト自身をクリーンアップするための処置と考えられる。
- 最後に、コマンド「exec」によって暗号資産マイナーを起動する。
- Jenkinsが提供する「Script Approval」の機能を使用する。
- Webコンソールへのアクセスに関わる認証、承認のポリシーを適切に設定し、運用する。Jenkinsからは、アクセスコントロールに関するガイドラインが公表されている。
- Jenkinsが提供する「Audit Logging」の機能を使用する。
- インターネットからJenkinsサーバにアクセスできないことを確認する。
- eventSubId: 2 AND processCmd:* exec * --rig-id *
- eventSubId: 2 AND processCmd:cron AND objectCmd:* exec * --rig-id *
まとめ
Jenkinsは柔軟かつ強力な機能を備え、近年のソフトウェア開発に欠かせないツールの1つとなっています。しかし、こうした機能も、設定やアップデートを怠れば大きなリスクを引き起こします(Jenkinsに関する前回の記事でも述べた通りです)。本調査では、Jenkinsのスクリプトコンソールが不正利用されるパターンとして、暗号資産マイニング用スクリプトが実行されるリスクを分析しました。
企業や組織がJenkinsサーバを安全に運用していく上では、適切な設定、強固な認証と承認、定期的な監査、インターネットアクセスの制限を含むステップを、全て実行することが重要です。そうすることで、Jenkinsのインスタンスが攻撃に利用されるリスクを最小限に抑え込み、開発環境の安全性を高めることが可能となります。
侵入の痕跡(IoC:Indicators of Compromise)
侵入の痕跡(IoC)はこちらで確認してください。
MITRE ATT&CK Techniques
MITRE ATT&CK Tactics and Techniquesは以下を確認してください。
参考記事:
Turning Jenkins Into a Cryptomining Machine From an Attacker's Perspective
By: Shubham Singh, Sunil Bharti
翻訳:清水 浩平(Core Technology Marketing, Trend Micro™ Research)