プロセス移行と回避

LinuxBeginner
オンラインで実践に進む

はじめに

この実験では、攻撃者がどのようにして永続的なアクセスを維持し、基本的な検知を回避するかを学びます。Metasploit のような自動化フレームワークでは、Meterpreter を使用してペイロードを Windows の安定したプロセス(explorer.exeやsvchostなど)へシームレスに移行させますが、Linux 環境では異なるアプローチが必要となります。

一般的な原則はプラットフォームに依存しません。攻撃者は、不安定で明らかに疑わしい実行コンテキストよりも、長期間動作し、一見して正常に見える実行コンテキストの中に隠れることを好みます。

Linux において、攻撃者は安定したシステムプロセスを特定し、「プロセス名偽装(Process Name Spoofing)」を用いることで、悪意のあるペイロードを偽装し、全く同じ回避目標を達成します。ここでは、実行中のプロセスの偵察方法、信頼できるシステムコンポーネントの特定方法、そして検知を回避するために正規のカーネルスレッドになりすますペイロードの実行方法を学びます。

これは安定性の問題であると同時に、人間の認識の問題でもあります。防御側は膨大なプロセスリストを監視する際、システム上の「ノイズ」として期待される名前に紛れ込んでいるプロセスを見過ごす傾向があるからです。

実行中のプロセスの確認 (ps)

このステップでは、Linux システム上で実行中のプロセスをリストアップし、分析する方法を学びます。攻撃者はこの偵察フェーズを利用して環境を理解し、なりすましが可能な正規のプロセスを探します。

繰り返しになりますが、まずは列挙が先決です。ホスト上で何が「正常」であるかを知らなければ、説得力のあるカモフラージュ対象を選ぶことはできません。

ps (process status) コマンドは、アクティブなプロセスを表示するための標準的なツールです。システム上で実行されているすべてのプロセスを包括的に把握するには、aux フラグを使用します。

ターミナルで以下のコマンドを実行し、実行中のプロセスを表示してください。

ps aux | head -n 15

a フラグはすべてのユーザーのプロセスを表示し、u はユーザー指向のフォーマット(CPU やメモリの使用量を含む)で表示し、x は端末に接続されていないプロセスを表示します。出力を head -n 15 にパイプすることで、最初の 15 行のみを表示し、見やすくしています。

以下のような出力が表示されるはずです。

USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.1 167008 11468 ?        Ss   10:00   0:01 /sbin/init
root           2  0.0  0.0      0     0 ?        S    10:00   0:00 [kthreadd]
root           3  0.0  0.0      0     0 ?        I<   10:00   0:00 [rcu_gp]
root           4  0.0  0.0      0     0 ?        I<   10:00   0:00 [rcu_par_gp]
root           5  0.0  0.0      0     0 ?        I<   10:00   0:00 [slub_flushwq]
root           6  0.0  0.0      0     0 ?        I<   10:00   0:00 [netns]
root           8  0.0  0.0      0     0 ?        I<   10:00   0:00 [kworker/0:0H-events_highpri]
root          10  0.0  0.0      0     0 ?        I<   10:00   0:00 [mm_percpu_wq]
root          11  0.0  0.0      0     0 ?        S    10:00   0:00 [rcu_tasks_rude_]
root          12  0.0  0.0      0     0 ?        S    10:00   0:00 [rcu_tasks_trace]
root          13  0.0  0.0      0     0 ?        S    10:00   0:00 [ksoftirqd/0]
root          14  0.0  0.0      0     0 ?        I    10:00   0:00 [rcu_sched]
root          15  0.0  0.0      0     0 ?        S    10:00   0:00 [migration/0]
root          16  0.0  0.0      0     0 ?        S    10:00   0:00 [idle_inject/0]

[kthreadd] や [kworker/0:0H-events_highpri] のように、角括弧で囲まれたプロセスに注目してください。これらはカーネルスレッドです。非常に安定しており、継続的に実行され、システム管理者が検査することもほとんどないため、回避の対象として最適です。

安定したターゲットプロセスの特定

このステップでは、回避に最適な特定のプロセスを特定します。安定したプロセスとは、通常、自動的に起動し、長期間実行され続けるシステムデーモンやデスクトップサービスのことです。

攻撃者のペイロードがクラッシュすると、アクセス権を失ってしまいます。ペイロードを安定したプロセスとして偽装することで、疑念を抱かれることを防ぎます。一部の Linux 環境では、kworker エントリは観察しやすく、名前が技術的で長いプロセスリストに溶け込むため、便利な命名モデルとなります。

この環境で kworker 形式の名前が表示されるか確認してみましょう。以下のコマンドを実行してください。

ps -ef | grep kworker | head -n 5

-e フラグはすべてのプロセスを選択し、-f はフルフォーマットでリストを表示します。grep を使用して「kworker」を含む行のみをフィルタリングしています。

環境がカーネルワーカーのエントリを公開している場合、以下のような出力が表示されることがあります。

root           8       2  0 10:00 ?        00:00:00 [kworker/0:0H-events_highpri]
root          25       2  0 10:00 ?        00:00:00 [kworker/1:0H-events_highpri]
root          31       2  0 10:00 ?        00:00:00 [kworker/2:0H-events_highpri]
root          37       2  0 10:00 ?        00:00:00 [kworker/3:0H-events_highpri]
root          43       2  0 10:00 ?        00:00:00 [kworker/0:1-events]

もし grep コマンド自体しか表示されず、実際の kworker エントリが見当たらない場合でも、この実験環境では問題ありません。次のステップでは、特定のカーネルスレッドが見えるかどうかに依存するのではなく、プロセス名偽装の仕組みを学ぶことが目的であるため、馴染みのある [kworker/X:Y] という命名スタイルを使用します。

安定したプロセスへの移行

このステップでは、長時間実行されるプロセスを起動し、そのプロセス名を偽装することでプロセス移行をシミュレートします。

~/project に malicious_payload.sh というダミーのペイロードが用意されていますが、ここで重要な Linux の仕様があります。シェルスクリプトを実行すると、プロセスリストには通常 /bin/bash /home/labex/project/malicious_payload.sh のようにインタープリタが表示されてしまいます。この挙動により、この環境では偽装された名前を明確に観察することが困難です。

偽装を簡単に検証できるように、代わりに単純な長時間実行コマンドを使用します。セキュリティの概念は同じです。プロセスに誤解を招く表示名を与えることで、プロセスリストに溶け込ませるという点です。

以下のコマンドを実行して、偽装されたバックグラウンドプロセスを起動してください。

bash -c 'exec -a "[kworker/u4:2]" sleep 600' &

bash -c の部分は新しい Bash プロセスを開始し、続くコマンド文字列を実行します。exec -a "[kworker/u4:2]" はその Bash プロセスを sleep 600 に置き換えますが、オペレーティングシステムに対してプロセス名を [kworker/u4:2] として表示するように指示します。sleep 600 コマンドは、検査を行うのに十分な時間プロセスを生存させます。末尾の & はプロセスをバックグラウンドで実行します。

以下のように、バックグラウンドジョブ番号とプロセス ID(PID)を示す短い出力が表示されます。

[1] 1337

これで、偽装されたプロセスがバックグラウンドで静かに実行されており、偽装された名前で表示されるはずです。

永続性とアクセスの検証

最後のステップでは、偽装されたプロセスがその偽装された ID で表示されることを確認し、その後クリーンアップを行います。

前のステップで割り当てた偽装名を探します。

ps aux | grep "kworker/u4:2"

以下のような出力が表示されるはずです。

labex       1337  0.0  0.0   7008  1536 pts/0    S    10:15   0:00 [kworker/u4:2]
labex       1345  0.0  0.0   6480  2272 pts/0    S+   10:16   0:00 grep --color=auto kworker/u4:2

この環境において、偽装されたプロセスは sleep で作成されたデモンストレーションに過ぎず、本物のカーネルワーカーではありません。重要な点は、プロセスリスト上の表示名が、信頼できるシステムコンポーネントのように見えるようになったということです。

最後に、偽装名を含むコマンドラインを終了させることで、デモンストレーションプロセスをクリーンアップします。以下のコマンドを実行してください。

pkill -f "kworker/u4:2"

もう一度 ps aux | grep "kworker/u4:2" を実行して、偽装されたプロセスが正常に終了したことを確認できます。

まとめ

おめでとうございます!「プロセス移行と回避」の実験を無事に完了しました。

攻撃者が実行中のプロセスを分析し、安定した信頼できるシステムコンポーネントを特定する方法を学びました。また、プロセス名偽装(exec -a)を使用して、悪意のあるペイロードを正規のカーネルスレッドに見せかけ、Meterpreter のような高度なフレームワークで使用される回避技術を効果的にシミュレートする方法も習得しました。最後に、偽装されたプロセスのステルス性を検証し、適切に終了させる方法を学びました。これらのスキルは、永続的な脅威が Linux 環境内でどのように隠れているかを理解するために不可欠です。