本文の内容は、2023年3月7日に BIAGIO DIPALMA が投稿したブログ(https://sysdig.com/blog/bypassing-network-detection-with-graftcp)を元に日本語に翻訳・再構成した内容となっております。 Sysdig 脅威リサーチチーム (TRT)の日々の攻撃解析から、graftcp (GitHub page)という新しいネットワークオープンソースツールが発見されました。昨今、脅威行為者は、新しいツール(PRootの記事で紹介しました)を使って、できるだけ多くのターゲットにヒットするようにコードの互換性を高め、痕跡を適切に隠すことで、技術の向上を図っています。 Graftcpは、攻撃者がローカルプロキシを設定して、よく知られている悪意のあるドメインやIPへの直接接続を隠し、検出を回避できるようにするツールです。このガジェットの革新的な特徴は、グローバルなネットワーク設定を変更することなく、特定のプロセスから来るトラフィックを再ルートできることです。 この記事では、graftcpの仕組み、攻撃者がこれを便利だと思う理由、そしてFalcoを使ってこの種の活動を検出する方法について説明します。
類似のツールとの違いは何ですか?
私たちのハニーポットで、SOCKS、SOCK5S、または古典的なネットワークプロキシを使って悪意のある接続を隠そうとする脅威行為者を分析したのは、今回が初めてではありません。しかし、この種のアクションを実行しようとするとき、彼らはしばしばファイアウォール設定、ネットワーク設定、またはライブラリのロードに苦労します。これらのコンポーネントの変更は本当に珍しいことで、一般的に簡単に検出されます。 graftcpに似たツール(tsocksやproxychainsなど)は、異なるメカニズムに基づいているという事実にもかかわらず、同様の機能を提供するものがすでにいくつか見られました。 これらのツールは、ld_preloadハックを使用して、デフォルトのconnect()システムコールをカスタムのものにラップします。新しい接続を開始するとき、このツールは宛先IPがローカルであるかどうかをチェックします。そうでない場合は、指定されたプロキシに接続をリダイレクトします。しかし、ld_preloadのトリックは、異なる目的の異なるテクニックで使用され、ld.so.preloadファイルを編集するため、一般的に検出可能です。したがって、この手口は動的にリンクされたプログラム(例えば、PythonやGoで書かれたスクリプト)に対してのみ悪用可能です。では、なぜGraftcpがクールなのでしょうか?
Graftcpは、特定のプロセスから来るネットワーク接続を隠し、リダイレクトする機能によって、類似のものとは一線を画すユニークなツールです。ネットワーク設定の変更やシステムコールのラップを必要とする他のツールとは異なり、graftcp は fork と ptrace システムコールの賢い利用に基づいています。graftcp はどのように動作するのか?
新しいプロセスが起動すると、graftcp はそのプロセスをフォークし、ptrace システムコールを使用してそれを追跡します。また、接続が行われると、その呼び出しを傍受して一時的に停止し、ローカルのプロキシにリダイレクトして、実行します。このため、graftcp は汎用性が高く、動的にリンクされた実行可能ファイルだけでなく、あらゆるタイプのプロセスに適用できます。 graftcpを使用すると、任意のコマンドを実行し(または新しいシェルを開くことも可能)、生成されたプロセスに関連するすべてのネットワーク接続がローカルプロキシを通じてルーティングされます。これを確実に行うには、“graftcp”コマンドを前に付けてコマンドを実行すればよいのです。 以下、使用したアーキテクチャーを紹介します:物事をうまく進める
graftcpを使い始めるために、環境設定をしてみましょう。- 希望のプロキシモードを選択する
- プロキシの認証情報を入力する
- ローカルプロキシのポートを設定する
128.199.120.139root@ceacb39eb45a:/# ./graftcp/graftcp curl ifconfig.me 128.199.120.139 root@ceacb39eb45a:/# ./graftcp/graftcp curl dockerhub.com <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd"> <html> <head> <title>301 Moved Permanently</title> </head> <body> <h1>Moved Permanently</h1> <p>Object moved permanently -- see URI list</p> </body> </html>
何が見えてくるのか?
graftcpの動作は、connect()システムコールを監視することで検出することができます。攻撃者が単純なcurlコマンドの前にgraftcpコマンドを実行した場合、2つの接続が表示されます:1つ目はローカルプロキシに対して、2つ目はホストからリモートプロキシサーバに対してです。ここで見ることができるように:connect curl 127.0.0.1:36812 127.0.0.1:2233 | cmdline: curl ifconfig.me | parent cmdline:graftcp curl ifconfig.me connect graftcp-local 172.17.0.2:52086 128.199.120.139:443 | cmdline: graftcp-local -config graftcp/local/graftcp-local.conf | parent cmdline: graftcp-local -config graftcp/local/graftcp-local.conf同じコマンドを普通に実行した場合にもかかわらず、このようになります:
connect curl 172.17.0.2:37496 34.160.111.145:80 | cmdline: curl curl ifconfig.me | parent cmdline: bash
Falcoでgraftcpを検出する
その動作のおかげで、プロセスやシステムコールの可視性が低い場合でも、graftcp は簡単に検出できます。 Sysdig 脅威リサーチチーム (TRT) は、graftcp ツールの使用を検出する 2 つの Falco ルールを開発しました。 FalcoはCNCFのインキュベートプロジェクトで、クラウドネイティブ環境における異常な活動をリアルタイムに検知し、アラートを送信する機能を備えています。お客様は、Falcoのデフォルトのルールを利用するか、Falcoのわかりやすく適応性の高い言語を使用して独自のカスタムルールを作成することができます。 最初のルールは、graftcpが悪用するptrace syscallの使用に基づいて、プロセスをトレースし、最終的に接続を傍受して迂回させるものです。- rule: PTRACE anti-debug attempt condition: > evt.type=ptrace and evt.dir=> and evt.arg.request=1 and proc_name_exists output: > Detected potential PTRACE_TRACEME anti-debug attempt (proc.name=%proc.name proc.args=%proc.args fd.name=%fd.name proc.cmdline=%proc.pcmdline proc.pname=%proc.pname container=%container.info proc.pcmdline=%proc.pcmdline user.uid=%user.uid user.name=%user.name group.gid=%group.gid container.id=%container.id container.name=%container.name image=%container.image.repository) priority: WARNING - macro: localhost_connection condition: > ((((evt.type in (accept,listen,connect) and evt.dir=<)) and (fd.typechar = 4 or fd.typechar = 6)) and (fd.ip = "0.0.0.0" or fd.net = "127.0.0.0/8") and (evt.rawres >= 0 or evt.res = EINPROGRESS))2つ目のルールは、このツールのネットワークの側面に依存するもので、graftcpに関連すると思われる名前のプロセスによって実行されるlocalhostへの接続を検出します。
- rule: Graftcp local proxy detected condition: > localhost_connection and (proc.name in ("graftcp", "graftcp-local") or proc.pname in ("graftcp", "graftcp-local")) output: > A connection to a potential local proxy was detected (proc.name=%proc.name proc.args=%proc.args fd.name=%fd.name proc.cmdline=%proc.pcmdline proc.pname=%proc.pname container=%container.info proc.pcmdline=%proc.pcmdline user.uid=%user.uid user.name=%user.name group.gid=%group.gid container.id=%container.id container.name=%container.name image=%container.image.repository) priority: WARNING