切られたしっぽ

産業廃棄物の投下場所

Fakenet-NG 単体で証明書エラー無くHTTPS通信の復号をやらせるまで

TL;DR

  • Fakenet-NG を改造して、証明書のエラーなく任意の通信先に対して HTTPS の通信を行わせるための備忘録です
  • 実質 MitM をさせる Proxy を作るための話になります

はじめに

マルウェア解析の動的解析環境(Sandbox 環境)を構築する際、TLS/SSL を用いた HTTPS 通信をどのようにして取得して分析可能とするかというのは一つの至上命題です。マルウェアがC2サーバと通信する際に TLS/SSL を使う場合はもちろんそのやりとりの中身を記録したいですし、解析環境検知のためにメジャーなWebサービスに対して HTTPS でダミー通信を発する場合もあります。現代だとほぼ必須の要望といっても過言ではありません。

おそらく最も一般的な手法として用いられるのは、Burp などの proxy サーバを立てて通信を MitM (Man-In-The-Middle) させ、それを INetSim などのインターネットサービスシュミレータにリダイレクトさせることで確立したコネクションの中身を分析する方法ではないかと思われます。このようなマルウェアを動かす端末と proxy兼擬似C2サーバの2台を用いた構成は @soji256 氏や @masaomi346 氏のブログでも紹介されているため、記事を参考にすることで円滑に環境を構築することができるでしょう。
soji256.hatenablog.jp

qiita.com


しかしながら、この手法だと Virtual Machine が2台構成になってチョットリソースを多めにとるという点と、INetSim がかれこれ4年更新がないという点もあり現代風にアップデートした環境を用意したいです。筆者は個人PCで環境を用意しているということもあり、1VM構成かつ執筆時もアクティブなインターネットサービスシュミレータ Fakenet-NG を利用した構成を目指しました。

github.com


Fakenet-NG は mandiant のFLARE teamが作成したツールです。以前筆者のブログ記事でも紹介したので、この投稿を見てくれている方の多くはすでに使ったことがあるのではないかと思います。最近の記事を確認すると一目瞭然ですが、このツールはインターネットサービスシュミレータとしての機能だけではなく、DNSサービス, ルーティング, さらには Proxy としての機能も持たせることができる非常に高機能なツールです。おそらくですが、2024年5月現在インターネットサービスシュミレータとして最も多く活用されているツールではないかと、筆者は推測しています。根拠は、身の回りで使用者が多いからという非常に Low な確証度です。
cloud.google.com

これだけ見ると「マルウェアを動かす端末で Fakenet-NG を動かせば通信はすべてフォワーディングされて localhost にリダイレクトされるし、Proxy を挟むことで HTTPS 通信も覗き見できるし万事解決」と思うかもしれませんが、これだと1つ問題があります。 それはサーバ証明書に関する問題です。

Fakenet-NG は Proxy Listener の機能によって TLS/SSL の handshake を検出した場合 MitM を試みようとはしてくれますが、Fakenet-NG 側のサーバ証明書の変更を試みようとはしてくれません。これは該当部分のコードを見てもらえるとわかりますが、証明書が保存されているパスが直接指定されています。

Fakenet-NG のサーバ証明書読み取り部分のコード

当たり前の話ですが、マルウェアがアクセスしようとしたホスト名とサーバ証明書にある SAN (Subject Alternative Name) の値が異なると証明書の検証でエラーとなるため、自作のサーバ証明書を既存の Fakenet-NG に導入しようとすると、マルウェアHTTPS で通信する宛先すべてを知っている状態で証明書を作りコンフィグに設定しなければならなくなります。特に大量にC2サーバの宛先を保有していて次々と通信先を変えるようなマルウェアにとってはこの手法だと面倒です。


この課題を解決するために、筆者はコードに手を加えた Fakenet-NG をせっせこ作っていました。前置きが長くなってしまいましたが、Fakenet-NG 単体で MitM を円滑に成功させるための変更方法を備忘録として残すのが、この投稿の趣旨となります。また、筆者はネットワーク回りが素人なので、もっとスマートな方法を思いつく方がいらっしゃればコメント願います。

環境構築

はじめに、今回目指すものの全体像だけ先に提示します。やることを率直に書くと『TLS/SSL 通信が発生するたびに自作のCA秘密鍵と証明書から通信先を SAN に詰め込んだ自己署名証明書を作成し、それを参照させる』ようにします。概要を図示ししたものが以下です。

概要図

ここからは詳細な手順を書きます。

0. 事前準備

python のコードを直接いじるので、Fakenet-NGGithub からコード一式を clone し、No installation の項目に沿って必要なモジュールをインストールします。

コードが用意できたら、今度は CAの秘密鍵と証明書を作成して、CA証明書をマルウェアを動作させる端末に『信頼されたルート証明機関』としてインポートさせます。CA秘密鍵と証明書の作成については、筆者は以下の記事を参考にさせていただきました。図も大量にあって初心者にもわかりやすかったです。
zenn.dev

以下、ブログから必要な部分のコマンドだけ抜粋します。

# CA 秘密鍵作成
$ openssl genrsa -out localCA.key 2048

# CSR (Certificate Signing Request) 作成
$ openssl req -out localCA.csr -key localCA.key -new

# CA証明書作成
$ openssl x509 -req -days 3650 -signkey localCA.key -in localCA.csr -out localCA.crt

作成したCA秘密鍵と証明書は、Fakenet-NG を clone したフォルダから見て "\fakenet\listeners\ssl_utils\localCA.key""\fakenet\listeners\ssl_utils\localCA.crt" にそれぞれ配置してください。自己署名証明書を作成する際に利用します。また、CA証明書(localCA.crt)は端末でインポートさせることを忘れないでください。やり方がわからない方は、こちらのブログ記事などを参照していただくとうまくいくのではないかと思います。これで一旦の下準備完了です。

1. 通信先情報の取得

さてここから通信先に合わせた自己署名証明書を作るわけですが、何はともあれ通信先の情報をコネクションの起点となる Proxy Listener から抽出する必要があります。抽出に必要なデータを受け取っている Proxy Listener のコードは以下あたりです。

どうやら Proxy Listener が最初に受け取ったデータが、\fakenet\listeners\ssl_utils\ssl_detector.py にある looks_like_ssl関数で識別される場合にサーバ証明書を差し替えるルートにいくようです。looks_like_ssl の実装は tls handshake を捕まえているようなので、最小限のコード追加を考えた場合、Proxy Listener 視点では handshake から通信先に関する情報を見つける必要がありそうです。

ドメイン(ホスト名)

まずはマルウェアがホスト名で通信する場合です。handshake から通信先のホスト名を特定する方法がわからなかったので、TLS Protocol v1.3 の RFC を確認してみると、ホスト名で通信を行う場合 client hello の Extensions structure に server_name (type 0x0) としてその文字列が格納されているらしいです。

datatracker.ietf.org

実際に client hello をパースするスクリプトを公開してくれている方がいたので試してみると、client hello のデータがきれいにパースされました。なので、client hello のパーススクリプトに server_name 部分もパースして抽出させるようにします。 Extensions structure は別に RFC があるようなのでこちらを参考にデータ構造を見て、パースさせます。

datatracker.ietf.org

上記の公開されたスクリプトに server_name パースを付け加えたコードが以下です。

import struct
import binascii


_int16 = struct.Struct(">H")


def int16(b):
    """
    Return first two bytes of b as an unsigned integer.
    """
    return _int16.unpack(b[:2])[0]


def take(data, count):
    prefix = data[:count]
    data = data[count:]
    return prefix, data


def parse_hello(data):
    """
    Parse TLS 1.2 ClientHello from data, return the extensions as binary data
    or None if not found.
    Likely to raise struct.error or IndexError on error.
    """
    try: 
        header, data = take(data, 7)
        messageId, major, minor, l1, l2 = struct.unpack(">BBBHH", header)

        header2, data = take(data, 4)

        # random
        random, data = take(data, 32)
        # session identifier
        slen, data = take(data, 1)
        slen = slen[0]
        session, data = take(data, slen)
        # ciphers list
        clen, data = take(data, 2)
        clen = int16(clen)
        ciphers, data = take(data, clen)
        # compression methods (should always be an array of length 1, with one 0 element)
        compression_length, data = take(data, 1)
        compression_methods, data = take(data, compression_length[0])
        # extensions
        extlen, data = take(data, 2)
        extensions, data = take(data, int16(extlen))
        
        while extensions:
            _type, extensions = take(extensions, 2)
            length, extensions = take(extensions, 2)
            body, extensions = take(extensions, int16(length))
            if not _type == b"\x00\x00":
                continue
            name_type, body = take(body, 1)
            
            if not name_type == b"\x00":
                continue
            
            server_name_len, body = take(body, 2)
            if body[0] == 0:
                server_name_len, body = take(body, 2)
            return body

        return None
    except Exception:
        return None

かなり雑なのですが、これで TLS client hello に該当するデータを Proxy Listener が受け取った場合、通信先のホスト名が識別できるようになりました。今回は、これを \fakenet\listeners\ssl_utils\parse_client_hello.py に保存します。

IPアドレス

次にマルウェアIPアドレスで直接通信する場合です。そんなもん「IP の Dst header を見れば解決では?」と思うかもしれませんが、Proxy Listener が受け取るデータは IP header が落ちているのでその手は使えません。また、Extensions structure の server_name に必ずIPアドレスも入るとも限らないのでホスト名と同様の手法も使えません。

どうしたものかと Fakenet-NG のコードを読んでいると、どうやら Proxy Listener より上流にいる diverter が IP port forwarding をする際に管理している forwarding 用のテーブルを Proxy Listener にも渡していることがわかります。(IP forwarding 回りのコードを参照)

なので、純粋にfowarding 管理テーブルである ip_fwd_table から取得することで解決させます。コードは以下のような感じです。

ip_fw_table = self.server.diverter.ip_fwd_table
for fowarded, original in ip_fw_table.items():
    if f'TCP/{self.client_address[1]}' in fowarded:
        # self.client_address[1] がフォワード元の port 番号なので、
        # 合致する key があればそれに対応する value が forwarding 前の通信先
        create_cert(original)  

なお、ホスト名アクセスの場合は Fakenet-NG 内部の DNSサーバがすべて自身のIPアドレスを返すようになっているので、 forwarding 前のIPアドレスは自身のIPアドレスになっています。なのでホスト名でのアクセスの場合、同様の手法はとれません。全く違うアプローチをしなけばならないのは面倒ですね。

2. 自己署名証明書の作成

通信先の情報が取得できたので、あとはその情報を SAN に設定したサーバ証明書を通信の度に毎回作ります。大量に証明書ができるのですが、いい方法がこれしか思いつきませんでした。しかし解析環境の場合作られる証明書はせいぜい100程度だろうと考え、たいした容量にもならないと思いこの方法で妥協します。サーバ証明書の作り方については、以下の記事を参考にコードを流用させていただきました。

zenn.dev

最終的に作成したコードは、以下のようなシンプルなつくりです。

  • \fakenet\listeners\ssl_utils\certs にすでに一度作成した通信先のための証明書がないかを確認する
  • なかった場合は、引数に与えらえた通信先を SAN に設定して、事前準備で作った CA秘密鍵で署名したサーバ証明書を作る
  • ファイルを \fakenet\listeners\ssl_utils\certs 配下に置き、サーバ証明書秘密鍵と証明書のパスを tuple で返す
import os
import logging

from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption, load_pem_private_key
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import hashes
from datetime import datetime, timedelta, timezone

CERTS_DIR = os.path.join(os.path.dirname(__file__), 'certs')
logger = logging.getLogger("CreateCerts")
logger.setLevel(logging.DEBUG)


def create_new_cert(hostinfo, overwrite=False):
    if not os.path.exists(CERTS_DIR):
        os.makedirs(CERTS_DIR)
    
    if isinstance(hostinfo, bytes):
        hostinfo = hostinfo.decode()
    
    key_path = os.path.join(CERTS_DIR, f'privkey_{hostinfo.replace(".","-")}.pem')
    cert_path = os.path.join(CERTS_DIR, f'server_{hostinfo.replace(".","-")}.pem')


    if (os.path.exists(key_path) and os.path.exists(cert_path)) and not overwrite:
        return cert_path, key_path

    try: 
        with open(os.path.join(os.path.dirname(__file__), 'localCA.crt'), 'rb') as fc:
            ca_cert = load_pem_x509_certificate(fc.read())

        with open(os.path.join(os.path.dirname(__file__), 'localCA.key'), 'rb') as fk:
            ca_key = load_pem_private_key(fk.read(),password=None)
            
        server_private_key = rsa.generate_private_key(
            public_exponent=65537,
            key_size=4096,
            backend=default_backend()
        )

        now = datetime.now(timezone.utc)
        csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
            x509.NameAttribute(NameOID.COUNTRY_NAME, "JP"),
            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Tokyo"),
            x509.NameAttribute(NameOID.LOCALITY_NAME, "Dokoka"),
            x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Fakenet"),
            x509.NameAttribute(NameOID.COMMON_NAME, "localhost"),
        ])).add_extension(
            x509.SubjectAlternativeName([x509.DNSName(hostinfo)]),
            critical=False
        ).sign(server_private_key, hashes.SHA256(), default_backend())

        server_cert = x509.CertificateBuilder().subject_name(
            csr.subject
        ).issuer_name(
            ca_cert.subject
        ).public_key(
            csr.public_key()
        ).serial_number(
            x509.random_serial_number()
        ).not_valid_before(
            now - timedelta(days=365)
        ).not_valid_after(
            now + timedelta(days=365)
        ).add_extension(
            x509.SubjectAlternativeName([x509.DNSName(hostinfo)]),
            critical=False
        ).add_extension(
            x509.BasicConstraints(ca=False, path_length=None), critical=True,
        ).sign(ca_key, hashes.SHA256(), default_backend())
     

        with open(key_path, 'wb') as k:
            k.write(server_private_key.private_bytes(encoding=Encoding.PEM, format=PrivateFormat.TraditionalOpenSSL, encryption_algorithm=NoEncryption()))

        with open(cert_path, 'wb') as c:
            c.write(server_cert.public_bytes(Encoding.PEM))
        
        logger.info(f'Create New certs for {hostinfo}: {key_path}')
            
        return cert_path, key_path
        
    except Exception:
        return None, None
    

これを \fakenet\listeners\ssl_utils\parse_client_hello.py に配置して、Proxy Listener から呼べるようにします。

3. Proxy Listener への組み込み

必要な機能ができたので、あとは Proxy Listener 側から作成した証明書を参照してあげます。\fakenet\listeners\ProxyListener.py から上記2つのpythonファイルを import して、ssl handshake 検出後にホスト名/IPアドレスを抽出して自己署名証明書を作成、パスを上書きするだけです。変更部分のコードは以下になります。

(snip.)
from .ssl_utils import create_certs
from .ssl_utils import parse_client_hello
(snip.)

class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
(snip.)
    def handle(self):
        (snip.)
        is_ssl_encrypted = 'No'

        if data:

            if ssl_detector.looks_like_ssl(data):
                is_ssl_encrypted = 'Yes'
                self.server.logger.debug('SSL detected')
                hostinfo = parse_client_hello.parse_hello(data)
                if hostinfo:
                    certfile_path, keyfile_path = create_certs.create_new_cert(hostinfo)

                else:
                    ip_fw_table = self.server.diverter.ip_fwd_table
                    for fowarded, original in ip_fw_table.items():
                        if f'TCP/{self.client_address[1]}' in fowarded:
                            hostinfo = original
                            certfile_path, keyfile_path = create_certs.create_new_cert(hostinfo)
                            break
(snip.)
                listener_sock.start()
                # remote_sock.setblocking(0)

                # ssl has no 'peek' option, so we need to process the first
                # packet that is already consumed from the socket
                if ssl_remote_sock:
                    ssl_remote_sock.setblocking(0)
                    remote_q.put(data)
                else:
                    remote_sock.setblocking(0)
                
                while True:
                    readable, writable, exceptional = select.select(
                            [ssl_remote_sock if ssl_remote_sock else remote_sock], [], [], .001)
(snip.)

ちなみに remote_sock.setblocking(0) 周辺のコード (元の該当コードで言うとこのあたり) を変更しているのは、TLS 検出した場合は ssl.wrap_socket で remote_sock の socket が ssl_remote_sock に wrap されてしまうため、ここでエラーが発生してしまうためでした。今回いろいろ変更を加えてしまったので平常時が動いていたのか定かではないですが、おま環起因ではない場合は HTTPS 通信を Proxy Listener が吸っただけで必ずエラーになるので、改造前の状態だと全く機能していないことになります。。。(まさかね??)

4. テスト

これで必要なパーツがそろったので、証明書エラーなしで通信ができるかテストをしてみます。HTTPS の通信が Proxy Listener を必ず通るように \fakenet\configs\default.ini に書かれた HTTPListener443 の Hidden 設定を True にして Fakenet-NG を起動します。

[HTTPListener443]
Enabled:     True
Port:        443
Protocol:    TCP
Listener:    HTTPListener
UseSSL:      Yes
Webroot:     defaultFiles/
Timeout:     10
DumpHTTPPosts: Yes
DumpHTTPPostsFilePrefix: http
Hidden:      True

Fakenet-NG の起動コマンドは以下です。

$ python -m fakenet.fakenet

起動したら、Webブラウザからホスト名ベースでのアクセスを、powershell からIPアドレスベースでのアクセスを試みてみましょう。エラーなくアクセスできたことが確認できると思います。*1

自己署名証明書の動作テスト


また、Fakenet-NG は終了時にこれまで記録していた通信を pcap ファイルにダンプして Fakenet-NG のホームディレクトリに保存してくれています。pcap を確認してみると、先ほど試行した HTTPS の通信が復号された状態で中身を確認することができました。

ダンプされたpcapデータの確認

これにて、Fakenet-NG 単体でやりたかったことができるようになったので満足です。

おわりに

ほぼほぼ MitM 攻撃の解説みたいな記事になってしました。内容も内容なので、おそらく世界で1, 2人くらいしか参考にならない投稿なような気がしています。

現状だと色々粗があるのでそのままでは PR 書けませんが、もしいろんな人に需要がありそうなら fork したプロジェクトを公開するか頑張ってリファクタして PR 出そうかなと思います。それでは。

*1: curlpython でもCAを参照させるために、環境変数 CURL_CA_BUNDLE に "\fakenet\listeners\ssl_utils\localCA.crt" へのfull pathを入れてあげてください

「2024年も始まったしそろそろマルウェアの勉強を始めるか」と思っている人向けのマルウェア解析ツール入門話

  • 追記と修正
    • 2024/01/09: FOR710 についてはプロ視点で賛否両論あったので表現を変えました
    • 2024/01/09: FLARE-VM の構築部分でも書きましたが、解析環境と普段生活する環境は分離しましょう。VMWare or VirtualBox を使ってください。普段使いの環境にここで述べた解析ツールをいきなりインストールするとAnti-Virusに検知される可能性もあります。

TL;DR

  • 将来的にベンダーレポートやカンファレンス発表レベルでの"マルウェア解析"を想定した話です
  • とりあえず FLARE-VM 環境を作ってインストールされたツールを見る・触るところから始めるといいんじゃないでしょうか

はじめに

最近は引きこもりをやめてときどき外部に顔を出すようになり、マルウェア解析やインテリジェンス関連の話をする機会も増えました。それに伴って、「これってどうやってやっているんですか?」「参考になる本やWebサイトありますか?」といったマルウェア解析に使うツールややりかたに関する質問もポツポツいただくようになりました。

「(もう令和もはじまって6年目になるし、勉強できるプラットフォームや本も大量に転がっているし、筆者への会話デッキの一つとしてみんな話題を振ってくれているんだろうなぁ)」とか筆者は思っていたのですが、先日とあるところでやったセキュリティイベントのアンケートにて「Windows バイナリの Reversing なんて初めてやるし、ツールとかどんなのがあるかわからないし、事前に教えてほしい」といった意見を目にして、意外と適切なツールをググって探してくるのも初学者にとっては難しいのかもしれないと考え方を改めました。
たしかに SEO の仕組みを考えても古い記事は検索上位に出にくくなるし、現在進行形で入門を考えている方向けの記事があってもいいのかもしれないと思い、筆者が利用するツールやそのツール選択の元となっているプールについてダンプしてみます。

内容的には「何番煎じなんだろう......」ってものですが、マルウェア解析のツール選定に関わるエントリーレベルの記事にありつけていない人がいれば何かの参考にしていただけると幸いです。

ちなみに筆者のバックグラウンドは、

程度です。知らないツールやプラットフォームもいっぱいありますし、筆者のやり方は特殊で思想が偏っている可能性もあります。もっと有用・一般的なものがあれば追記いたしますのでコメントしてください。

"マルウェア解析" のスコープと前提知識の明確化

まず"マルウェア解析"の勉強と一口に言ってもかなり主語がデカいので、今回深堀する"解析"の対象をより明確にしておきます。筆者がここで紹介するマルウェア解析のツールというのは、「マルウェアの静的解析からシグネチャを作成したり、TTP を収集したり、帰属の考察をしたり、C2サーバとの通信を復号したりする」ために使うツールを対象にしています。なので、ファイルのトリアージマルウェアEDR などに残すログ、フォレンジックといった観点の話はほとんど入っていません。また、マルウェアとして解析する対象はどうしても Windows PE が多くなるので、oletools のような Office 製品の解析なども一旦省略します。

なので、より抽象的なレイヤーでのマルウェア解析のはなしが知りたい方はマルウエアの教科書を、トリアージからフォレンジックまで幅広く知りたい人は初めてのマルウェア解析を購読してみることを推奨します。

また、解析に必要な事前知識まで話すときりがないので、本ブログでは割愛します。気になる方は pinksawtooth 先生が書いている以下の記事がめちゃくちゃ参考になるので読んでください。
github.com


ちなみに筆者のおすすめの勉強方法は、Practical Malware Analysis (宇宙人本)を一冊やり通すのと Zero2Automated というマルウェア解析における Try Harder 系のトレーニングをやるという2つがオススメです。

慣れてきたらすでにレポーティングされている簡単めな検体を Any.Run から拾ってきて解析してみるのがスキルアップにはよいとは思うのですが、危険と隣合わせなのであまりオススメはしません。個人的な腕試しのオススメは FLARE チームが主催している FLARE-On challenge です。かなり実務寄りの問題が多いのでマルウェアの勉強の実践としては十分なのではないかと思います。
flare-on.com

ツールの選択元(プール) : FLARE-VM

さて、余談が長くなってしまったのですが本題に戻ります。
まず大前提をお話しすると、「マルウェア解析においてツール選定が決定的となるような場面は少ない」というのが筆者の考えです。どちらかというとコンピュータサイエンスの基礎知識やツールに対する練度の方が重要で、いくつかのポイントを自分の使いやすいもので見れればそれで充分ではないかと思います。筆者の感覚で「何かしら自分の手に馴染むツールを抑えていたほうがいいんじゃない?」思うのは、以下の5つくらいです。(より具体的にあげるとフォレンジック関連ツール、各々の言語ごとの解析ツール、モジュールレベルのはなし.......と様々ありますがキリがなくなってしまうので、今回は一般的なマルウェア解析=>レポーティングの流れでほぼ必ず通るものに絞りました。また、pythonVSCode といったセキュリティ関係なく使う系のツールは省略しています。)

大項目を5つあげましたが、各々のツールをいちいち調べて集めてくるのも少々面倒です。なので、解析ツールを学ぶエントリーとしては分析に必要なツール一式が導入されているディストリビューションを利用して、仮想環境マシンを作成し、中に入っているツールを調べて使ってみるのが一番よいかなと思います。ペンテストで言うところの 「まずは Kali Linux 落としてきて中身見てみたら」のニュアンスですね。筆者の一番のおすすめは、mandiant がOpen-Sourceで提供している Windows OSベースのディストリビューション FLARE-VM です。

github.com

筆者も大量のマルウェアアナリストを見ているわけではありませんが、VMWare 製品上に Windows 仮想マシンを立て FLARE-VM をインストールしている方を非常によく見ます。(もしかしたら、Ghidra実践ガイド での環境構築で述べられているのが影響しているかもしれません。) ツールも大量にインストールされるので、公式の Installation instruction を参考にしながら導入してみてください。現在は GUI でインストールするツールが決められるので、とりあえず200個近くあるツールすべてインストールしてみましょう。

画面遷移後に 3時間くらい放置すれば以下のようなデスクトップに切り替わると思います。これでひとまず導入は完了です。(余談ですが、昔の FLARE-VM のデスクトップイメージは水色のMマークでしたが、いつの間にか某アンダーなテイルのメタ〇ンっぽいキャラになってました。いつの間に変わったんだろうか。)

FLARE-VM インストール後のデスクトップ

あとは、デスクトップにある "Tools" ディレクトリを見てみましょう。様々なツールが並んでいると思います。知ってる単語や興味のある単語から子階層を漁って、ツールを調べて触ってみるといいんじゃないでしょうか。


FLARE-VM に入っている中でもよく使うツール

FLARE-VM インストールして中を見てみましょうだとさすがに不親切だと思ったので、筆者自身が中からよく引っ張り出すツールも簡単にまとめてみます。

PEStudio

www.winitor.com

マルウェア解析に限らずリバースエンジニアリングで最も大切なことは「自分が今向き合っているモノは何なのか」のあたりをつけることなのではないかと筆者は考えています。.NET で作られていれば de4dotdnSpy を使って難読化解除やデコンパイルをしますし、pyinstallernexe によって実行ファイル化されたツールであればネイティブコードの抽出を目指す人が多いでしょう。つまり、対象がWindows PEファイルであれば最適な分析手法を割り出すためのワンクッションがあったほうが効率的です。そのためのツールの1種別が表層解析系のツールで、筆者は PEStudio を好んで使用します。

ただし、この項目についてはめっちゃ派閥がわかれると思います。pe-beerCFF Explorer のほうがツールとして使いやすいという人もいますし、malwoverview のようなツールでトリアージは自動化している人、Detect It Easy のような最低限の表層解析ツールで十分の人もいます。

ここまでいろいろ書きましたが、ぶっちゃけ最適な解析ツールを導出することができればなんでもよいと思うので、あとは皆さんが触ってみたフィーリングやレベル感によって使いやすいものを決めてください。筆者はなんで PEStudio 使っているかというと strings の部分が優先度順で並ぶのと全体的にグラフィカルでわかりやすいからです。


IDA Free (Pro)

hex-rays.com

最強です。純粋なマルウェア解析をやっている時間の9割以上がこのツールを触っている時間と言っても過言ではないかもしれません。チラッと目次を見てもらった方には「あれ、デバッガ書いてなくね?」と思った方もいらっしゃるかもしれませんが、現在は x64 のアーキテクチャであれば Free からデコンパイルもできるしデバッグもできるのでほぼこのツールで完結します。つよいです。

IDA Free decompiler & debugger

ただし Free だと x86 や arm まではデコンパイルできないので、そういう場合は Ghidra でディスアセンブル/デコンパイルしながら x64dbg を使うという人が多いのではないかなと思います。(ただやはり Ghidra を使うとデコンパイルの精度やショートカットの微妙さなどが気になるので、できることなら IDA 使いたいなと筆者はよく感じます。あと、バージョンアップのたびにプラグインをビルドしたり python3 がデフォルトで使えないのがあまりにも厳しい。。。)


また、最近なぜか WinDbg を使いますという声もちらほら聞きます。たしかに先日 かえるのほんだな さんが0円というまさかのバグ価格でWinDbg本を公開されていたので、こちらを参考にしながらデバッガの勉強をするのも非常にありな選択肢だと思います。
techbookfest.org

雑にまとめますが、基本 IDA を使う練度を上げて使えない部分は他のツールでカバーするというのが一番実践的だと思う、というのが筆者の主観です。

FakeNet

github.com
FLARE チームが作成したネットワーク通信のエミュレートツールです。デフォルトだとほぼすべてのネットワーク トラフィックインターセプト、リダイレクトし FakeNet 側で指定したカスタムレスポンスを返させることができます。つまり、マルウェア解析の場面ではホストオンリーの環境でもC2サーバの擬似応答を返させることでデバッグ解析を継続させることができるという強力なサポートをが得られるツールです。(リバエン力が高くない筆者にとっては、ここまでの上三つがとりあえず使うツール3強な気がしています。)

試しに FakeNet を起動した状態で googlecurl を叩いてみると、FakeNet からの fake レスポンスを返してくれることがわかります。

FakeNet sample

DNS も解決してローカルホストにリダイレクトさせてくれるので、ここからC2サーバのレスポンスを作りこみ、解析をより深く行うこともできたりします。FakeNet に届いた通信は pcap 形式でdumpしてくれるので、事後分析もしやすいです。総じて優秀なので、デバッグしながら解析している際には脇で動かさない手はないでしょう。

mandiant さんの公式ブログを見るとカスタムレスポンスのつくり方なども書いてあるので、興味がわいた方はこちらを参考にカスタムしてみてください。
www.mandiant.com

Yara

github.com

ファイルに対するシグネチャマッチングのデファクトスタンダードです。多くのベンダー・組織がマルウェアの検知ルールとして Yara rule を公開しており、さらにセキュリティ製品でもこの Yara が導入可能となっているものが多いです。なので、解析で Yara を使わなくても純粋に Yara の読み書きができるというだけでも得をする場面はあるかなと筆者は想像しています。特にマルウェア解析を仕事にしている人だと、解析結果から Yara ルールを作成して、それを組織のセキュリティ製品に組み込んで運用できる状態にしてもらうことをアウトプットの一つにしていたりするのではないかなと思います。
ルールのイメージがわかない方は JPCERT/CC さんが公開しているものなどを参考にしてください。

脇道にそれたので話を解析に戻します。主に解析後の話を中心として Yara を記述しましたが、筆者のトリアージプロセスの一つとして Yara をかけるというのは最初期段階で行います。「シグネチャマルウェアのファミリ判定されれば儲けもの」くらいのモチベーションです。たしかに標的型検体や Pack されているマルウェアなどからはいい結果が得られませんが、ものの数秒くらいのロスにしかならないのでとりあえず JPCERT/CC さんなどのGithubに公開されているルールをかけて損はないと思います。

またシグネチャマッチングとは少々異なりますが、実行ファイルがどんなことをしていそうかというのを推定してくれる capa というケーパビリティツールもあります。
github.com

筆者は自分でルールを作りこむことまではしたことなく mandiant さんが提供するルールを IDA Pro のプラグインから使ってトリアージに活用しているだけなのですが、IIJ さんのブログなどを参考にすると自身でルールを書いてもっと有用な使い方ができそうな気がしています。皆さんはぜひ有効活用してください。
eng-blog.iij.ad.jp

FLARE-VM に入ってないけどよく使うので別途入れているツール

本当は上で終わるつもりだったのですが、なんだかんだ3割くらいは別途ツールをインストールして使っている気がするのでこちらも書いてみます。静的解析で使う細かめの話が多いです。ご了承ください。

FileInsight

俗にいうバイナリエディタです。FLARE-VM にも一時期話題になった午前3時から頑張る人向けのバイナリエディタ ImHex 010 Editorなんかが入ってはいるのですが、筆者の肌感にあわずメインでは使ってません。

代わりに何を使っているかというと McAfee 製の FileInsight というのを使っています。こちらは有志の方がマルウェア解析に特化したような plugin を作ってくれたりしていることもあり、雑にデータの復号とか解凍とかができるのがうれしい点です。バイナリエディタ単体で起動することもあまり多くは無いのですが、振り返ってみると一番使っているのはこれですね。

github.com

あとは、IDA にも Hex 表示の機能がついているので、けっきょくのところそこで見て python 使ってデータいじってしまうことが多いですかね。。。IDA つおい。

Process Hacker

processhacker.sourceforge.io

プロセスが使用しているメモリやネットワークレベルのリソースまで確認できる、プロセスリソースモニターです。
似たようなツールとしてProcess Explorerもありますが、筆者の場合 Executable なメモリを見つけたりそこからメモリをダンプしたりする機能が便利すぎてずっと Process Hacker を使っています。

また、少し余談になりますが、Process Explorer などに代表される Sysinternals tool は有用なものが多く FLARE-VM にも標準でインストールされるため見てみることをオススメです。("Tools -> sysinternals" にあります)
learn.microsoft.com

前にも述べた通り筆者はほぼ IDA を使うばかりで動的解析をしなくなってしまったのであまり使ってはいないのですが、Process Monitor, Autoruns なんかはマルウェアをとりあえず動かしてサクッと挙動を掴むうえで有用なツールだと思います。

直近だと IIJ さんのブログにも Process Monitor を活用した動的解析ツール Noriben のはなしがあるので、いきなり静的ではなく動的から勉強していきたい人は活用してもらえるといいのではないかと思います。(初めてのマルウェア解析 の本を持っている方はここからでも学べたりします)
eng-blog.iij.ad.jp

bindiff

github.com

最近 Open-Source になったことで話題となったディスアセンブルコードの比較ツールです。同じところで何年も働いていると一度解析したことのあるマルウェアの亜種とは何回も戦うことになり、詳細を全部確認すると無限に時間がとられてしまいます。なので、限られた時間で読む部分にあたりをつける、さらにはコードの更新部分を第三者にわかりやすく説明するためにかなり重宝されます。(特に、非エンジニアに説明する意味だと後者はデカいと思います。)

具体的なイメージが見たい方は moly さんのブログを参考にしてください。Ghidra での解析差分をサクッとそしてビジュアブルに図示できることがわかると思います。

morimolymoly.hateblo.jp


ちなみに IDA Pro を使っている方は diaphora という便利なプラグインがあるためこちらを使っている方が多いかもしれません。こちらでも bindiff と同等のことができますが、関数をクリックするだけで IDA の該当の関数に飛んでくれるので非常に親和性が高いです。 Pro がある人はこっちも試してみることをおすすめします。
github.com

BlobRunner

github.com

かなり tips よりのツールだが、「抽出した shellcode をサクッとデバッグしたい。。。」とアナリストならば一度は思ったことがありそうな要望を叶えてくれるツール。Initial Accessでは全部が shellcode でできたようなツールがポンポン降ってくるような昨今ではすごく有用だと思います。

筆者もかつては「指定したファイルを読み込んで、Executable なメモリに配置して、3分sleepして、call する。。。」なんてツールを書いて使っていましたが、BlobRunner だとデバッガでアタッチしたあとにエンターキー押せば breakpoint まで飛んでくれるので利便性高いですね。

OALabs さんは他にも API hashing の解決を補助してくれる hashdb のようなプロジェクトや Youtube channel で解析手法なんかを公開していて非常に有用なので、時間に余裕のある方はチラ見してみてください。(筆者自身も、こういうところから便利そうなツールの情報を盗むことが多いです)
github.com

Hayabusa

github.com

大和セキュリティさんが公開している Windows のファストフォレンジックツールです。「あれ、フォレンジックツールは紹介しないんじゃなかったっけ?」と思った方もいらっしゃるかもしれませんが、筆者は Sigma と呼ばれる SIEM でのログ検出用のシグネチャルールを検証する際に使用しています。

github.com

下記は Sigma 公式 Github の README に載せられている図ですが、Sigma ルールは Sigma rule のコンバーターと何かしらの SIEM (に検証したいログがたまっている状態)がないと有効活用、つまり検証できません。

https://github.com/SigmaHQ/sigma/raw/master/images/Sigma_description_light.png

Hayabusa は Sigma を解釈したうえでローカルに溜まったエベントログをスキャンしてくれるので、コンバーターと実質 SIEM 部分の役割を担ってくれます。便利です。Sigma ルールを書いたり検証したりするジョブに就いている人にとっては、マルウェアをローカルでガチャガチャ動かして検証できるようになるツールなので入れておいて損はないと思います。

おわりに

けっこうコンパクトにまとめたつもりがかなりぐちゃった内容になってしまいました。

もっと体系的に学びたいと思った方がいれば、学生の場合はセキュリティ・キャンプの脅威解析クラス, 社会人の場合はFOR710なんかがいいんじゃないかなと思っていましたが賛否両論あるようなので、現場の解析経験ある人から知見を吸収してみましょう。

最後になりますが、一歩目の踏み出し方がわからない方の参考になったり、何かしら新しい知見が得られた方がいれば幸いです。それでは。

某のフィッシングキットから見る、調査のときに留意したいクローキングのこと

はじめに

フィッシング詐欺は企業にも個人にも迫る身近なサイバー脅威の1つであり、それが占める被害件数の割合はサイバー攻撃全体で見てもおそらく最大クラスです。
大規模な SOC や CSIRT に所属している方にとっては、対応することが多いアラート・インシデントの一つになっているのではないかと思います。
もちろんアラート・インシデントがあれば対応者がフィッシングサイトの調査をする必要が出てきますが、ここで一つ課題になるのは クローキング の存在です。

クローキングは一般的なIT用語なのですでに知っている方も多いと思いますが、いわゆるアクセス元の情報を頼りに表示するコンテンツを変える技術のことですね。
wacul-ai.com

フィッシングサイトもクローキングによってフィッシング用コンテンツと良性コンテンツの表示を切り替えているのですが、問題はこのクローキング技術は対応者・リサーチャー側からは見えないブラックボックスの存在であるという点です。
「User Agent によって動作が変わる」, 「IPアドレスによっても動作が変わる」なんて話も人から聞いたことはありますが、実際にコードを見たことがないので調査も伝聞の知見をもとにやるしかありません。

筆者もこれまではサーバ側のコードを見たことがなかったので勘で調査を行っていたのですが、今回ひょんな機会でフィッシングキットを見る機会があったので、フィッシングサイトが使うクローキング技術をコードレベルで確認してみることにしました。
せっかくの長期休暇中なのでいつもと違う分析もしてみようというモチベもあり、調べた結果を簡単ではありますがメモ書き程度に残します。筆者と同じような境遇にいてフィッシングサイトの調査をする機会があった場合参考にしていただければ幸いです。

免責事項

本投稿はフィッシングキットの使用を促す内容ではありません。よって、フィッシングサイトの構築といった部分には触れることもありません。
あくまで行うことはソースコードをベースに攻撃者が行っているクローキング手法を分析することであり、リサーチャーが効果的にフィッシングサイトを調査するための視点を学ぶことを目的としています。
本投稿内容を悪用目的では使用しないでください。

ことのあらまし

2023年9月の頭、16shop というフィッシングキットを使用していたサイバー犯罪者が海外で逮捕された事件は皆さんの記憶にも新しいと思います。
筆者も下記のTrendMicroさんの記事を見ながらその功績の詳細を追うとともに、簡単にフィッシングサイトを作成できる「16shop」というツールキットについても概要を知ることができました。
www.trendmicro.com

......が、記事の中で一枚の画像が目に留まります。それは Maltego での分析画像でしたが、VirusTotal に16shopのフィッシングキットがアップロードされているようです。

フィッシングキット16shopの分析、トレンドマイクロとインターポールのパートナーシップ(TrendMicro)』, 図5:複数のフィッシングキットが保存されているサーバ より画像引用

なぜキットがアップロードされているか理由はわかりませんが、ツールは海賊版も存在しているようなので、どこかで海賊版を入手した攻撃者がウイルスのチェックをするために VirusTotal にアップロードしたりしたのかもしれません。何はともあれ、`16shop` というキーワードのある zip だけで VirusTotal から見つけることができそうです。

試しに、以下のクエリを試してみると 47 件ほど存在しました。 TrendMicro さんの記事にある命名と同じなので、これらが海賊版(?)の16shopフィッシングキットのようです。

entity:file tag:zip name:16Shop
VirusTotal で16shopのフィッシングキットを search する

せっかく見つかったので、ツールキットを分析して筆者の中でブラックボックス化していたクローキング技術をクリアにしてみることにしました。
これで、勘でやっていたクローキング対策がより論理的に行使されるようになるでしょう。

16shop フィッシングキットの調査

基本情報

今回の分析する対象は以下のキットです。これを対象とした理由は、投稿日時が最も新しかったためです。
www.virustotal.com

ファイル名が『16Shop-Amazon.zip』なので、おそらく Amazon のフィッシングサイト構築用だと思われます。zip の Bundle info にある Latest Content Modification が 2023-05-31 なので、おそらく4か月ほど前に作られたものなのではないかと推測できます。

概要

今回入手したツールの中身を覗いてみると、どうやら php で書かれているツールのようで、index.php へのアクセスからすでに大量のクローキング処理が行われています。画像に見える blocker.php, blocklist.php などがそれに該当する処理ですね。読み込んでいる php ファイルの量が多くすべての処理を列挙していると記事の内容が非常に長くなってしまうため、いくつかにグルーピングして要点だけまとめていきたいと思います。

ディレクトリ構成


余談ですがTrendMicro さんの記事を見た際はツールキットは python で実装されているように見えたので、時代や種類によってキットの構成は一新されているのかもしれません。*1

クローキング処理部分の詳細分析

16shop の場合、フィッシングコンテンツを表示させるかどうかに使っている情報は以下のようです。

  • CLIENT-IP, X-FORWARDED-FOR ヘッダ
  • アクセス元のIPアドレス
  • アクセス元のホスト名
  • アクセス元のISP
  • User-Agent ヘッダ
  • Referer ヘッダ

そこそこあるように書きましたが、実態としては アクセス元のIPアドレス と HTTP header にある User-Agent の2つで、おまけ程度に Referer がある程度です。しかし、IPアドレス部分についてはそこから正規利用者かどうかの判定ロジックが多いのと、そもそもIPアドレスをどのようにして判定するかというロジックがあるため少し小分けにして記述してます。ここからは、各項目を細かく見ていきます。

CLIENT-IP, X-FORWARDED-FOR ヘッダ

大前提として、このフィッシングキットはアクセス元のIPアドレスを取得し、それがbotのアクセスやblacklistに登録されたIPアドレスであった場合はフィッシングコンテンツを返さずブロックするという仕様を持っています。では、そもそもアクセス元のIPアドレスをどのように取得しているかというと以下の部分のコードです。

アクセス元のIPアドレス取得部分

筆者も見て驚きましたが、ロジックがかなりザルです。このコードでは HTTP header に CLIENT-IP または X-Forwarded-For がある場合、それらを真っ先に優先してIPアドレスとして認識します。この先に様々なクローキング処理がありますが、まずは理想に見えるIPアドレスをこれらのヘッダーに入れることから試してみてもよさそうです。

アクセス元のIPアドレス

では理想的に見えるIPアドレスは何かというと、blacklist に載っていないIPアドレスを選択することになります。blacklist に載っているIPアドレスは単発のものもあれば一定のレンジのものもあるので注意が必要ですね。例えば、レンジでのblacklistを見るとTOR や AMAZONIPアドレス帯などは基本的にblockされています。とりあえず TOR からアクセスしてもクローキングに阻まれてしまう可能性は十二分にありますね。

アクセス元のホスト名

ここではIPアドレスからgethostbyaddrでホスト名を問い合わせ、blacklist にないかをチェックします。しかし、なぜか先述べたIPアドレスチェックのロジックではなく $_SERVER['REMOTE_ADDR'] で取得したIPアドレスからホスト名を取得しているので、結局のところアクセス元のIPアドレスはHeader以外でもきちんと偽装する必要がありそうです。

中をざっと見てみると VPN のホスト名などもチェックしていたので、VPN アクセスかどうかもクローキングの対象にしているようです。筆者は NordVPN や ExpressVPN を使いますがどちらもblacklistに入っていたのでVPNの契約バリエーションを増やす必要があるなと再認識しました。

アクセス元のISP

こちらはIPアドレスの取得ロジックで取得したIPv4に対して、Internet Service Provider を問い合わせてblacklistに当てはまった場合弾くロジックです。
中を見ると、Digital Ocean やら Choopa やらリサーチャー側がよく攻撃インフラとして使われているのを見る文字列は見えましたが、OCN などの日本の利用者向けのものは見えませんでした。ここらの Provider は bot ばかりで一般的な利用者がいないという判断なのでしょうかね。

User-Agent ヘッダ

このヘッダも、基本的には blacklist にマッチしたものを弾く仕組みなので、Webで検索して一般人が使用する OS, Browser のものを引っ張ってくれば弾かれることはなさそうでした。もちろん雑に curl したり、python の requests で訪れたりした場合は弾かれるので CLI から検証をする場合は必ず User-Agent を変更しましょう。


Referer ヘッダ

Referer の blacklist は .htaccess 側にその記載がありました。どうやら phishtank からのアクセスなどはここで弾けるようにしている実装のようです。Referer はヘッダに入っていた場合に弾く材料として使われているようなので基本は設定せずとも問題ないとは思いますが、Webサービス経由で調査を行う場合などは考慮する必要がありそうです。

その他、気になったこと

これはクローキングの仕組みとはずれる話となりますが、blacklist などによってbot判定された場合のIPアドレスや理由はその都度記録されていて、そこは「よくできているなー」という感想が漏れました。例えば、以下のコードは antibot[.]pw にIPアドレスを問い合わせて bot かどうかを判定する処理なのですが、bot 判定された場合はそのIPアドレスをファイルに書き出しています。

bot 判定された場合、そのIPアドレスを別途記憶する処理

書きだされたIPアドレスが即座に使われる様子は今回のコードから確認できませんでしたが、おそらくここで手に入れたIPアドレスを利用して、攻撃者が今後のblacklist拡張などに活用するものと思われます。このような処理は他の blacklist 処理のコードでも散見されるため、調査の一番最初できちんとクローキングを意識したアクセスをするかどうかが非常に大切なことがわかりますね。もし弾かれた場合、即座にVPNの切り替えなどを行った方が賢明かもしれません。

余談ですが、コードを最初に見たときは「『一度アクセスしたIPアドレスbot判定されたら blacklist 入りする』といった設定が入っていた場合、とりあえずメールに書かれているURLを全部雑にcurlすることで企業ネットワークの同じ出口にいる従業員の被害を最小限にできるかなー」とか妄想していたのですが、16shop の場合それができなそうなので残念でした。

まとめ

簡単ですが、フィッシングキットの調査をしてブラックボックスだったクローキング技術をクリアにしました。基本的にはクローキングはblacklist方式で行われているようで、フィッシングサイトにアクセスする際には

  • CLIENT-IP, X-FORWARDED-FOR ヘッダ
  • User-Agent ヘッダ
  • Referer ヘッダ
  • 出口となるVPN

を最低限工夫してから初動の調査を行われなければいけないことがわかりました。リサーチャーの場合、攻撃者の環境には分析用の仮想環境から TOR, VPN などを経由してアクセスすることになると思いますが、フィッシング関連のインシデント報告を受けてアクセスした結果それらしいものが表示されない場合、VPN を別のものに切り替えたり調査用の専用線からアクセスするようなアクションが必要となりそうです。

最後になりますが、本投稿はあくまで特定の1つのフィッシングキットを分析したサマリになります。他のフィッシングキットは同じような動作をするとは限りませんし、より入念な準備をしている攻撃者ならblacklist以外のクローキング技術を施しているかもしれません。しかしインデント対応者はその仮説が外れた場合、ブラックボックスな状態から変数を考察して次の手を打つことは必須です。この投稿がフィッシングインデントの対応者にとっての、初動対応を考えるための一助になればと思います。

*1:もしかしたら、この php のものは古い海賊版を改造しながら使いまわしている可能性もあるかもしれません。

Webミリしら人間の OSWA 合格体験記 (2023/08)

はじめに

夏休みに暇な時間ができたので、 OSWA という OffSec. の資格を取得しました。

まだ日本語でのレビュー記事や体験記がなかったので、簡単ですが備忘録を残します。

なお今回はWebセキュリティ資格関連の話をしますが、筆者はWebの専門家でもなければWebセキュリティについては全然詳しくない人間です。頓珍漢なことを書いている場合はご訂正いただけると助かります。

What is OSWA & WEB-200 ??

OSWA は Offensive Security Web Assessor の略で、Offsec.が提供するWeb アプリケーションのペネトレーションテスト資格です。
www.offsec.com

日本人の受講記録は筆者調べだと存在せず、多くの日本人にとって未知な部分が多い資格かなと思います。筆者はLearn Unlimitedを契約しているので、夏休みに様子見ということで受講してみました。

Offsec が提供するWebのペネトレーションテスト資格はWeb-300に該当する OSWE のほうが著名ですが、Web-200 は Web-300 よりもより入門者向けに作られたトレーニングとなっています。具体的に述べると、Web-300 はWebアプリケーションテストのホワイトボックステストに大きく焦点が当てられているようですが、Web-200はブラックボックステストが中心です。そのため、コードに対する深い理解などはいらず基本的なコンピュータサイエンスの知見とファジングの基礎知識があれば十分戦えるという内容になっています。公開されているアジェンダをまとめると、以下のような内容が学べます。

  • XSS (Cross-Site Scripting )
  • SQL Injection
    • RCE までを含む
  • CSRF (Cross-Site Request Forgery)
  • SSRF (Server-Side Request Forgery)
  • SSTI (Server-Side Template Injection)
  • Command Injection
  • XXE (XML External Entities)
  • Directory Traversal
  • IDOR (Insecure Direct Object Reference)

CTF やWebが得意な人なら「かなり基本的な内容しかないな」と感じたと思いますが、ご想像の通りでWeb-200の扱うスコープはかなりメジャーなWeb脆弱性のみなので少々ボリュームが少なめです。そしてCVEベースの脆弱性もスコープ外であり、基本的には構築されたWebアプリケーションの実装上の脆弱性を探すという内容になっているので、とにかく列挙列挙列挙ファジングファジングファジングが重要なゲーミングになっています。そのため、すでにWebの脆弱性診断やセキュリティに関わっている人にとっては少々退屈な話題だと思うので、そのような方は最初からWeb-300を受講することを強くお勧めします。ちなみに、筆者は「へー "/api/user/100" => "/api/user/101" にアクセス試すのってIDORって言うんだー」「XML External EntitiesってXXEって訳すんだー今までXEEって言ってたかもー」レベルだったので純粋にトレーニングコンテンツを楽しむことができました。しかしながら、用意されているラボが現状だとまだ8台しかなく、3日で遊びきってしまったのでボリューム的には不満でした。OSWA 試験が提供され始めたのも2022年(だった気がする)のでまだ発展途上な研修であることは否めず、受講者自体が現状少ないのもそのあたりが相まっているものと思われます。

試験

試験概要

OSWA の試験は OSCP と同じく1マシンからlocal.txtとproof.txtを取得するタイプの試験ですが、実態はOSCPと少々異なります。OSCP はuser shellの取得証明でlocal.txt, privilege shell の取得証明でproof.txtを提出しますが、OSWA はwebのコントロールパネルへの侵入でlocal.txtが, そこからfile system上のファイル読み出しができてproof.txtが得られるような試験になっています。(ここでいう webのコントロールパネル というのは、WordPress の admin dashboard だと考えてもらえればOKです。)

wordpress.com


つまり権限昇格のフェーズは存在せず、HackTheBox でいうところのlocal shellが取得できるまであたりがゴールという感覚です。これは"権限昇格がないので簡単です"という表現ではなく、WEB-200で取り上げているような脆弱性でもRCEにつながらないものを試験に取り上げるための都合だと思われます。具体例をあげると、単純なXSS脆弱性ではRCEにつながらないのでOSCPの試験だと取り上げにくいですが、コントロールパネルへの侵入が第一目標だとcookieをstealする問題として出しやすいという感じですね。なので、OSCP のように "whoami + cat or type proof + ip a or ipconfig" のスクリーションは必要なく、local.txt or proof.txt が映ったBrup SuiteからのスクリーンショットとWeb UIのスクリーンショット2つをレポートに張り付けることが変わりに求められていますね。

https://help.offsec.com/hc/en-us/articles/4410105650964-WEB-200-Foundational-Web-Application-Assessments-with-Kali-Linux-OSWA-Exam-Guide


もう少しイメージしやすい具体的なboxを挙げると、"soccer" というマシンのuser shell取得までをもう少し難しくしたマシンになります。
infosecwriteups.com

このようなマシンが5台分存在し、local.txt, proof.txt がそれぞれ10 pointで合計70 points overで合格です。ボーナスポイントは存在しないので、最低でも4つのマシンでコントロールパネルに侵入できないとアウトとなります。取り扱っている内容が難しくないとはいえ、8割のマシンでexploitを成功させなければならないのでスピードが重要な試験ですね。

試験本番のタイムスケジュール

Web のペネトレは列挙がすごく多いので、筆者のレベルでは時間がかなりカツカツでした。筆者の試験タイムスケジュールは以下で、合格までは15.5時間程度の時間がかかりました。

時間 score 詳細
11:00 0 試験開始.
11:31 10 1台目 local
- - 脆弱性っぽいところは見つかるがexploitまでつながらず一旦あきらめ
14:47 20 2台目 local
- - 列挙しても脆弱性見つからず一旦あきらめ。内心焦り始める。
18:03 30 3台目 local
18:38 40 3台目 proof
19:29 50 4台目 local
19:57 60 4台目 proof
- - ご飯食べて仮眠。3,4台目がめちゃ簡単だったので、"まさかね......" とベットで考えていたことを1台目で試したら通った。
02:23 70 1台目 proof
- - 合格ライン超えたのでレポート作成始め, proofと再現のチェック
08:30 70 ほぼレポートのひな形が完成し一応5台目へ
09:21 80 5台目 local
10:00 90 5台目 proof
10:45 90 2台目の proofも粘ったけど取れず
13:00 レポート提出

1, 2台目のマシンと筆者のメンタルモデルが合わず前半はけっこう焦りましたが、後半はラボやトレーニングの内容をベースにポンポン進んだので内心ホッとしました。悩んで首をひねり続けていても見えないものは見えないので、チートシートを使ってどんどん列挙を続けるのが大切な試験でしたね。ある意味、OSCP のときにやった諦めない列挙の心というのを思い出しました。

github.com

最後1台目のproof.txtだけどうしても取得できず90pointsで終了。スクショの取得漏れが一番怖いので合格点達成時点でレポートを書き、最後に5台目分の内容を追記する形で早めにレポートを提出しました。レポート提出後は別の作問作業などをしていましたが、ピッタリ24時間後に合格通知が来て特に山もなく谷もなくといった具合でWeb-200は修了です。

完走した感想

最後に、いつものように試験のことは書けないので感想を残して終わります。まず試験ですが、OSCPのときと同様に「ちょっと意地悪やなぁ」という問題が多いように感じましたね。Hy3n4 さんのレビューには以下のような文章が書かれています。
medium.com

I would consider myself as a pentester with some decent level of experience. But I have to admit that the time frame in this certification probably makes it even for more experienced pentesters not like a walk in the park.

一言でまとめると「経験者でも楽勝ではないよ」という内容になるかと思います。OffSec. の試験だとツールをただ回すだけではexploitの兆しが見えにくいというのがあり、やはり手動で微調整した列挙や、自分で簡単なコードを書いて試験する必要性が出てきます。CTFで簡単なWeb問をやっていた人なら問題ないと思いますが、bliend SQL injection の検証レベルのコードが書けたほうができることの幅が広がるので、ラボを通してコーディングへの抵抗は少なくした方が賢明です。筆者の場合は、bliend SQL injection からlocalにあるファイルを読みだすスクリプトと、gopher を使ったssrfのURLエンコーディングを二重にするコードは事前に作っておきました。

ここまでネガティブ方面に見えることを書き連ねてしまいましたが、筆者はOSWAにあまりネガティブな印象を持っているわけではありません。ラボや試験で対面したマシンはモダンな作りのWebサイトが多く、やはり実践的なトレーニングができるOffSecの研修はいいなと再認識しました。OSCPのラボやよくある日本の研修だとLAMPという平成の遺産をつかってWebの脆弱性を学ぶことが多いですが、OSWAだと node + mongo やbackendにgraphqlがいるようなモダンなつくりのwebサービスを対象にして遊べるので、「php の webshell 置いて終わり」なんてラボは一切なく非常に楽しかったです。同じような内容は OWASP Juice Shop でも遊べるのですが、やはりマシンが複数ある分Webサービスとしてのバリエーションが多く、起動やリスタートも簡単なOSWAのラボのほうが快適で楽しかったというのは心の底から思います。

owasp.org

HTBの似たようなマシンでも学べはしますが、やはりあちらもshellをとることに特化しているサービスなので、実際のWebサービスペネトレーションという意味ではOSWAのほうが実践的なのではないか、と浅薄ながら思う所存です。


おわりに

Web ミリしら人間だったので、OSWA を通してWeb脆弱性のことを少しは学ぶことができたかなとうれしく思っています。やはり「知識として持っているだけだと実際のexploitで活用できない, 応用が利かない」というのはどのOffSecトレーニングをやっても痛感することで、今回の試験でもそれを学ぶことができたことは一つの実りです。その一方でWeb-200のみだとトレーニングのボリュームは不満に感じる部分もあるので、診断経験などがある人は素直にWeb-300からやるのが無難かなと思います。しかし、セキュリティ何もわからないけれどもペンテスター目指したいような人の場合、OSCPだとスコープが広すぎて覚えることが多くたいへんな面もあると思うので、OSWAから始めてみるというのも一つの選択肢とありだと考えます。最終的なエントリーレベルとしてどちらを選択するかは、自身のキャリアプランと相談してみましょう。筆者の場合、もうちょっとWebに詳しくなるためにも今度はWeb-300を受けますかね。

そのほか、気になることがあれば Xまで気軽にリプかDMを送ってください。それでは。

SOCっぽいことをしている中の人の OSDA 合格体験記 (2023/07)

はじめに

先日 OSDA というOffsec.の資格を取得しました。

N番煎じなブログですが、体験記のリクエストをもらったので自身の記録を書き残しておきます。OSDAの取得を考えている人の参考になれば幸いです。

What is OSDA & SOC-200 ??

OSDA 合格に関わるブログは、すでにたくさんの方がまとめてくださっているためご存じの方も多いかもしれません。まだ試験が始まって1年も経っていないはずなのに早いですね。

レオンテクノロジー様『OSDA(Offsec Defense Analyst)の受験記』
www.leon-tec.co.jp

GMO CYBER SECURITY by IERAE 様『OffSec Defense Analyst (OSDA)受験記』
gmo-cybersecurity.com

nknskn さん『OSDA のケーススタディ
news-nknskn.hatenablog.com

ここでも簡単に説明すると、OSDA は Offsec Defense Analyst の略で、Try Harder で有名なOSCP資格と同じOffsec.が提供する唯一のDefense向け資格です。OSDA 試験のためのトレーニングとして SOC-200 というコースが設けられており、その名の通りSIEMを活用したログ分析の手法を学ぶことができます。具体的には、以下のようなことを学ぶことができます。

  • Windows イベントログそのものの勉強/監査設定
  • WindowsLinuxの初期侵入/横展開/権限昇格/永続化 をした際に発生するログ
  • Active Directory環境での横展開/ドメイン掌握 を行った際に発生するログ
  • Kibanaの操作、アラートルール、視覚化ダッシュボードの作成方法

一言でまとめると、Elasticsearch + Kibana を使ったログ分析ゲーミングとなります。筆者はKibanaを使ったSIEM運用やEndpointログ分析を日常からバリバリ行う職場にいるため、分析環境はとてもなじみ深いもので使いやすかったです。

また、トレーニングの内容としても『監査設定をする => どんなWindows eventログが見えるようになったか確認する => 攻撃をしてどんな特徴的なログが出るかを見る 』という基本のキに沿った内容だったので非常に親切であり、初心者入門教材としては十分だと思われます。その一方で、そこまでハイレベルなログ分析の視点までは紹介されず、一般的なドメイン環境の侵害で使うツールが残すログを雰囲気で追えるレベルの解説しかなかったのは物足りない部分だと感じました。 弊チームにいると 「event id `4662` の3回出現で何されたかも読めないの!?」と詰められますが、この研修だと「lsass.exe に Process Access されたからcredential accessされました」くらいの粒度でわかればOKなので、非常にやさしいです。より専門的なログ分析の方法については SOC-300 が出るのを待ちましょうという感じですかね。

また、この研修はOffsec研修の中でも最高に親切で、用意されている Lab (challenge) の半分以上は OffSec Academy (OSA)という動画付きの講義で詳しく解説してくれますし、Offsec の discord に行って以下のように chatbot を起動すれば、各 Lab のヒントをもらうことができます。
ぶっちゃけ Try Harder 感はほぼないので、初心者向け Offsec トレーニングともいえるでしょう。筆者の肌間的にはOSCP, OSEP, OSWPに比べてかなり快適だったので、Blue teamの人たちの温かさに感動していました。

discord chatbot

試験まで

筆者は4/10からトレーニングの受講をはじめましたが、Offsec側でVMインスタンスが安定して起動しないというトラブルがずっと発生していて、まともにLabができるようになったのは5月末からでした。別の方の合格体験記では「試験環境が不安定でログがSIEMに残らない問題があった」という記述がありましたが、同時期のLab環境でも同じような現象が発生しており「そもそも演習環境のVMが正しく立ち上がるまでが一番難しい」という状態でした。なので、VMインスタンスにちゃんと触れるようになってから約2か月Kibana触ってLabを2周くらいしあたと、「まぁいけるかな」という状態になったため7月末に試験にゴーという感じです。

試験前の対策としてはいつも使用するクエリのチートシートやKibana Dashboardの作成などをしていました。特に、SOC-200 で使用するElasticsearchのバージョンは メジャーバージョン 7 の最終系 であるため、8で運用している人とは微妙に使用感が異なります。「普段 Elasticsearch + Kibana 使っているし余裕」という人も、試験前に使用感をチューニングすることをお勧めします。(「8.8 から使える Response console スゲー」と感動して現場でそれしか使っていない人は使えないので要注意です。)
www.elastic.co

また、分析用のDashboardとosqueryのクエリチートシート(endpoint fileのハッシュ計算や通信しているプロセス列挙など)があると時短になるので、短期間で試験を受ける人もこの2つだけは準備することをおすすめです。

Kibana Dashboard のサンプル

試験

試験は10個のフェーズに分かれた攻撃を順番に分析する24時間の試験です。各フェーズ10点満点で合計75点に達すれば合格になります。体感的には10時間くらいで終わる内容で、特にトラブルもなく最終フェーズまで進んだので運がよかったかもしれません。詳細なスケジュールを書くと以下のような感じです。筆者の場合金曜日業務の終わった後の土曜日夜1時から初めて、月曜日の0時45分までにレポート提出の日程でやったので途中眠すぎて椅子の上で気絶していました。OSCPを受験した際は連勤の間に試験挟む程度余裕だったのですが、もう年のせいか徹夜試験は身体に響きますね。。。

時間 Phase 詳細
01:00 0 試験開始. まずは試験環境の視察. 基本の検索クエリ生成
01:20 1
02:05 2
03:25 3
04:40 4
06:20 5 7時くらいまでは分析していた記憶がある
- - 椅子に座ったまま気絶
10:40 6 慌てて起きて分析の続き
11:15 7
11:55 8
- - お昼食べたり買い物したり掃除したり
16:20 9
17:15 10 18:00には終わり夜食と風呂
ここからレポート作成
06:00 レポートのひな形を書き終え安心して就寝。
- - 睡眠。
10:30 起床して誤字や抜けの確認作業
15:00 提出

筆者の記憶だと PEN-200 のときは性格の悪い環境での試験だったので、今回も捻くれたものを覚悟して受けました。......が、かなり素直な環境を想定したログ分析で杞憂でした。レポートを提出した次の日の夜には合格のメールが来たので、大きな波もなく試験終了。他の人の合格体験記を見ると結果がくるまで1週間近く間が空く人もいたようなので、個人差があるようです。

試験tips

試験に関する詳しいことは書けないので、最後にちょっとした試験のコツだけ書きます。技術面というよりもマインド面でのコツです。

  • 攻撃者が一本道で目標を達成するとは限らない
    • 言い換えれば、1つの行動の追跡にこだわりすぎると全体が見えなくなります
    • 内部まで横展開が進行したあとに唐突に足取りがつかめなくなっても、落ち着いてドメイン環境を見渡して痕跡を探しましょう
  • Phase で一つの目標だけが達成されるとは限らない
    • 「あーこの端末でこれやったんだ!」で勝手に納得すると、後で足元をすくわれる可能性があります
    • 「ログが読めてる!」とノッているときでも、一度全体を見渡して他にも何かされていないかを探してみましょう
  • ログが行動を完全に追跡しているとは限らない
    • 端末によっては監査設定があまく、ネットワークログやオブジェクトへのアクセスログを完全に記録してくれていないものもあります。
    • その場合は、見えているログから攻撃者が何をやっているかを埋め合わせて記述するしかありません。細かい部分は一度脇に置いて、先に進めましょう。
  • Phase のログを実行する場合は 0時01分10秒 のように少し中途半端な秒数から始めるのをおすすめ
    • 0時5分のようにキリのいい時間にやると、cronjob などのログに攻撃のログが混じるので滅茶苦茶見にくくなります。
    • 特に試験の開始前は、焦らずにどんなログが流れている環境かを分析するところから始めましょう

おわりに

以上、OSDA のレビューでした。弊社はOSCP合格者には上限まで資格奨励金が出ますがOSDAは0円なので天と地ほどの待遇差があり、弊チームからは『nmap は神スキルだけど Kibana でログ分析はハズレスキル』なんてネタにされていますが、 Elasticsearch + Kibana を触ったことない人やWindows Event logを全く見たことのない人にとって SOC-200 はとてもいいトレーニングですし、追放された先の多くのパーティで活躍できるスキルになると思います。環境準備して攻撃してログを見てリセットして......という環境を個人のVMで用意するのは面倒なので、SOC-200の研修を受講してサッと試す分にはおすすめです。また、SIEM や EDR 導入の話をすると「セキュリティにお金を1円もかけられない人もいるんですよ!!」というお話も出ますが、Elasticsearch + Kibana の分析環境は0円からSIEM + EDRを始めることができるので、「お金かけられないおじさん」にもおすすめです。*1

逆に運用経験がある人にとっては退屈な内容なので、そういう方々は SOC-300 が出るまで待ちましょう。
そのほか、より具体的な内容でも気になることがあれば twitter (今は X か....)まで気軽にDMしてください。それでは。

*1:もちろん0円だと限界も多いですが、とりあえずおすすめされた100 ~ 1000万円規模の製品だけ買って神様に祈るよりも、ログとして見えるもの, わかること, 限界などを把握したうえでその課題をクリアする製品を選ぶのでは防御の練度がまったく異なります。

OSINTのすてきな乱れ

  • 2023/06/18 騒動の元凶となったTweetについては本人から掲載許可をいただいております。あくまで本記事の目的は知識・用語の整理および以後の混乱を避けるための一提案であるため、本人への突撃などはご遠慮ください。
  • 2023/05/08 AIをArtifact Intelligenceと誤表記していたので修正

tl;dl

  • 筆者が"OSINT"について言及した結果、炎上にガソリンを撒いてしまった恐れがあるため用語の整理と筆者なりの考えをまとめた
  • OSINTという単語は『インターネットを使ってほにゃほにゃした』という非常に漠然としたコンテキストの元で使用される場面が散見され、聞き手にそのコンテキストが共有されていない場合は解釈に不一致が生じる
  • 少なくとも単発のアクティビティや公開情報からの情報収集という行為においては、OSINTという専門用語を持ち出さずとも適切な日本語を使用したほうが聞き手も理解しやすい

はじめに

本記事の投稿から約二か月ほど前、OSINT (Open-Source Intelligence) を題材としたつぶやきで界隈が盛り上がっていた。


時を同じくして、何の偶然かわからないが筆者もOSINT関連の話題をつぶやいており、騒動にガソリンを撒くようなかたちで話題を広げる事態となってしまった。


この結果は筆者としても本意ではないし、事態に加担しておいて「終息したしおーしまい」というのも不誠実な気がしてならない。筆者も本件を機会に改めてOSINTについてその言葉の定義を再確認し、「OSINTとは何か」という問いに対する自分なりの回答を捻りだしてみたので、備忘録としてその内容を書き残す。

なお、本記事は筆者なりの意見を多分に含み、一部の内容については間違っているおそれもある。「皆さんに最もらしく嘘を伝えたい」といった意図は全くないので、誤りのある内容についてはぜひ指摘していただきたい。

SNS 上で見られた論点と筆者なりの見解

炎上というのは「発信元が総叩きにあっている」という場合に限らず、「様々な意見を持っている個人が各々に発言した結果、マクロな視点で見たときに一つの大きな炎に見える」という構造をとっている場合がある。筆者の見立てでは本件もそのケースに該当するのではないかと考察しており、SNS(Twitter) で見られた言及を整理してみるとやはりいくつかの違った論点での指摘が見られた。これを独断と偏見で3つのカテゴリに分けたので、それぞれの命題に対して筆者なりの見解を述べていく。

Intelligence ≠ Collection


さて、これからOSINTについて考えるということは、まずその言葉の定義について確認しなければならない。
本記事を見ていただいている人の多くは、OSINTという単語を見聞きしたことがあるだろう。「本日のOSINTまとめです。」といってWeb記事のまとめを提出する人間や、「OSINTでSNSアカウント特定しました!」と言ってくる身内と遭遇した経験は少なからずあるのではないかと思っている。では、この文脈で語られているOSINTというワードは、果たしてOSINTの定義に沿ったものなのだろうか。


OSINTとは "Open-Source INTelligence" の略であり、その名の通りWebサイトやSNSといった公開情報から生成された "インテリジェンス" なるものである。OSINTはインテリジェンスを"情報の収集源"という観点で整理した一つの分類上の呼び名にすぎず、その他にも HUMINT (Human INTelligence) や SIGINT (Signal INTelligence) といった別の情報源から収集したインテリジェンスの呼び名が存在するが、本記事の本質から内容が反れるため今回は割愛する。

ここで疑問となるのが、先ほどから多用されている"インテリジェンス"とはいったい何者なのかということである。近年では AI (Artificial Intelligence) という言葉が一般人にも知れ渡り使用されるようになったが、おそらく"インテリジェンス"という言葉を単体で使用する人はいまだに少なく、意味をしっかり調べたことがあるという人はもっと少ないのではないだろうか。それもそのはずで、インテリジェンス (Intelligence)とは元来軍事で用いられる専門用語であり、日常で使われることはほとんどない。まずは米軍統合情報本部が公開している『Joint Publication 2-0: Joint Intelligence』*1から、その意味を確認してみるとしよう。PDFの冒頭には、こう書かれている。

Information on its own may be of utility to the commander, but when related to other information about the operational environment and considered in the light of past experience, it gives rise to a new understanding of the information, which may be termed “intelligence.”


情報はそれ自体でも司令にとって有用かもしれない。しかし、作戦環境で関連する他の情報や過去の経験と照らし合わせたとき、その情報に対する新しい理解が生まれる。これを "インテリジェンス" と言うのかもしれない。


日本語訳は筆者が書いたものなので、多少誤訳があるかもしれない。しかし原文を確認した方はおそらく同じような感想を抱くのではないだろうか。「用語解説のはずなのに説明が抽象的ではないか? 情報をいい感じに使ってもっと価値のある何かにすればええのか!?」と。では、内容がより明瞭になる Introduction まで読み進めてみよう。Introduction だけでも長く全文を載せることができないので、筆者がインテリジェンスを理解するうえで重要だと思う箇所だけ抜粋した。もし原文が気になる方は、PDFの Introduction を見ていただきたい。

a. 情報は将来の状況や条件について合理的な洞察を提供することで、司令の意思決定プロセスに貢献し最大の価値を発揮する。
(中略)


生のデータ(Raw Data)はそれ自体は比較的限定的な有用性しかもたない。しかし、データが理解しやすい形に処理されるとそれは情報(Information)となり、より大きな有用性を得る。情報の段階でも司令にとって有用かもしれないが、作戦環境に関する他の状況や過去の経験と照らし合わせたとき、その情報に対する新しい理解が生まれる。これを "インテリジェンス (Intelligence)" と言うのかもしれない。
(中略)


インテリジェンスは、最終的に情報とは2つの異なる特徴がある。インテリジェンスは将来の状況や情勢を予測することができ、行動指針(Courses of Action)をとることでどのような違いが生まれるか明らかにすることによって意思決定に貢献することもできる。


b. インテリジェンスは、作戦環境を理解しやすくさせるための評価および推定を司令に提供する。
(中略)


c. インテリジェンスは科学ではない。インテリジェンスアナリスト(分析者)は作戦環境を評価する際に不確実性を持っている。
(中略)


したがって、アナリストは自らの分析にどの程度信頼を持っているか(degree of confidence)を伝えることが重要である。
(中略)



d. インテリジェンスには、能力・プロセス・組織が含まれる。
プロセスには、収集, 加工, 抽出, 分析, 配布の工程が含まれている。
(中略)


インテリジェンスはそれ自体が目的ではない。作戦におけるインテリジェンスの関連性を向上させるために、マネージャーは消費者のニーズを予測し、インテリジェンスが効果的か、影響力があるかを検討しなければならない。
(中略)


作戦環境は絶えず変化するため、インテリジェンスは継続的な活動であることを留意する必要がある。

ここまで読み進めると非常に詳細に書かれているため、多くの方がより鮮明に"インテリジェンス"をイメージできるようになったのではないだろうか。筆者なりにまとめた"インテリジェンスとは何か"をまとめたものが以下である。

  • インテリジェンスとは: 以下の3つを含むものである。
    • 能力: 意思決定者に対して有効な"アウトプット(成果物)"を提示できることを指す。具体的には、データを収集し、情報へと加工し、分析してインテリジェンスへと昇華できるとともに、それが意思決定者に対する具体的な行動指針として貢献できていることである。サイバーセキュリティの文脈では、CISOに対してセキュリティ施策や予算への提言、SOCにIoC(Indicator of Compromise)やシグネチャの提供といったアウトプットが該当する
    • プロセス*2: 顧客・組織のインテリジェンス要求(Intelligence requirements)を理解・検討し、より要求に沿ったインテリジェンスが提供できるよう継続的に改善が行われている。
    • 組織: 上記が組織的に従事されている。
  • なぜインテリジェンスがあるのか
    • 刻一刻と変化し大量の情報が溢れている現場において、意思決定者は必要な情報だけを取捨選択し次の行動を決める必要がある。インテリジェンスは意思決定者を助け、組織がより最適な行動をとることを継続的にサポートできる
  • インテリジェンスはどのように生まれ、どのような特性を持つのか
    • 組織に所属する能力を持ったアナリストが、意思決定者のニーズをもとに改善を繰り返しながら行動指針に寄与する分析をすることで生成される。しかしインテリジェンスは科学ではなく不確実性を伴っているため、分析にはアナリストの評価・推定が含まれる。アナリストによる不確実性の評価は、信頼度として表現される。


少々遠回りとなってしまったが、このまとめを踏まえつつも『Joint Intelligence』の定義に基づきながら、「OSINTとは?」に対する筆者なりの説明一言で表現してみると、以下のようになった。

「組織・顧客のインテリジェンス要求を達成すること目的として公開情報を収集・分析し、 組織の情報戦に関わる意思決定に継続的に貢献すること」


さて、それでは冒頭の問いに戻ろう。Web記事のまとめやSNSアカウント特定は果たしてOSINTなのだろうか。筆者の見解としては、「OSINTを生成するための情報収集及び分析結果の一部ではあろうが、インテリジェンスの定義には沿っていないのでOSINTと表現すべきではない。」になる。つまり、元来のかっちりとした定義に基づいて"インテリジェンス(または、OSINT)"という単語を使用している人にとっては、昨今様々なコンテキストで使用されているOSINTは本来の意味からずれた別の何かとして映るのである。
本騒動においても、OSINTを生成するための活動を指して"OSINT"と表現している人が散見されたため、「情報収集(Open-Source Collection)というのはOSINTを生成するうえでの活動の一部ではあるが、それ自体はOSINTではないよ」という意味を込めて、このような本質的な事象について述べたアナリストがいたものと思われる。


ここまで長々と茶番をし続けてきたが、直近でSANSから出されたOSINTに関する記事でも同様の内容が書かれていることが確認できる。余力がある方は、是非一読してもらいたい。
www.sans.org


冒頭を抜粋すると、以下のように述べられているのが確認できるだろう。

Open-Source Intelligence (OSINT) is defined as intelligence produced by collecting, evaluating and analyzing publicly available information with the purpose of answering a specific intelligence question.


OSINT は、特定のインテリジェンス要求にこたえることを目的として、公開されている情報を収集・評価・分析することによって生成されるインテリジェンスと定義される。

OSINT のスコープ定義あるいは倫理との境界


本騒動は「OSINT をする過程で図らずして攻撃となってしまったり、法律に抵触するようなことがあるかもしれないので注意してくださいね」という発言内容がもとだったため、法と倫理に関する言及が最も多かったように感じている。

OSINTの定義は先に述べた通りであるが、筆者が調べた限りではそこに倫理や法といった概念は介在していない。そのため、OSINTと倫理に関する論点は、「"OSINT"を生成するにあたり、倫理に背く・法を犯すアクティビティというのはそれに含まれるべきではないのではないか」という命題に言い換えることができるのではないかと思う。(もし筆者が趣旨を間違って理解していたならば、申し訳ない。)

この論点に関して、「OSINTは倫理・法に背くアクティビティを含まない」という意見も散見された。しかし筆者の私見を述べるならば、「OSINTを生成するためのアクティビティには倫理・法に背くものも含まれる」というのがOSINTと倫理問題に対する回答になる。筆者の言葉で言い換えるならば、「己がインターネットをさまよって調査・分析した結果生成されたインテリジェンスであれば、それはすべてがOSINTに分類される」というような認識である。これは、上で引用させていただいた _roku_ さんの図が非常に参考になると考えており、筆者のOSINTに関する理解もまさしくこの通りである。OSINTを生成するためのアクティビティを大別すると、ターゲットに対して自らが直接関与した痕跡が残るActiveとそうでないPassiveの2つのタイプがあり、Activeの活動をやりすぎると倫理や法律の問題が絡んでくるという認識である。いくつか領域わけがされていても、ここに含まれるすべてのスコープがOSINTを生成するために必要なアクティビティである。

なお、これはあくまで「OSINTの定義的に倫理・法に背く活動がその生成過程で行われているものもある」というニュアンスで述べたものであって、決して犯罪を教唆するような内容ではないことに留意してほしい。しかしながら、あくまでサイバー空間における情報戦指南のような存在であるOSINTに求められるのは情報の正確性、蓋然性、証拠の確実性(再現性)である。インテリジェンスとしての価値を高めるための行動は倫理・法的に疑問が残ったとしても、最終的に生成されたインテリジェンスに倫理的な問題が絡まないのであれば、それは非常に価値のあるインテリジェンスとして享受している組織が多いのではないだろうか。少なくとも、筆者は倫理的に疑問がある手法は用いられていれど、そこから非人道的な言及をしたインテリジェンスが生成されているレポートは見たことはない。現実に、カンファレンスでの発表や有償インテリジェンスサービスのレポートを見ていても「おそらく法的に問題ある方法でIoCを取得しているな」というモノはちらほら存在する。だが、それに対して皆は生成されたインテリジェンスに感謝をしながら自組織のシグネチャに組み込んでいるのではなかろうか。だとすると、多くの組織は倫理・法的に問題のある活動を暗黙的に了承しているということに他ならない。

先ほどまでは「インテリジェンスと倫理」という観点で論じたが、では視点をもう少しミクロに落とし「OSINTを生成するまでのアクティビティと倫理」という観点からも考えてみよう。法や倫理に抵触しそうなアクティビティに対する言及にはどのようなものがあっただろうか。

A「不正アクセスはするな!」
B「許可なく脆弱性検査をするな!」

なるほど、たしかにアクティビティに対しては倫理・法的に問題があることはやめましょう、と説くことができそうである。(しかし、これはOSINTという文脈ではなく"調査活動"のようなニュアンスで語るほうが正確な気がしてならないが)
では、これらの行為がどのような法律に引っかかる恐れがあるのだろうか。おそらく、『不正アクセス行為の禁止等に関する法律』、通称『不正アクセス禁止法』が該当する。法律の該当部分*3を抜粋すると、以下の文面になると思われる。


不正アクセス行為の禁止等に関する法律
(中略)


第二条
4 この法律において「不正アクセス行為」とは、次の各号のいずれかに該当する行為をいう。
一 アクセス制御機能を有する特定電子計算機に電気通信回線を通じて当該アクセス制御機能に係る他人の識別符号を入力して当該特定電子計算機を作動させ、当該アクセス制御機能により制限されている特定利用をし得る状態にさせる行為(当該アクセス制御機能を付加したアクセス管理者がするもの及び当該アクセス管理者又は当該識別符号に係る利用権者の承諾を得てするものを除く。)
(中略)


三 電気通信回線を介して接続された他の特定電子計算機が有するアクセス制御機能によりその特定利用を制限されている特定電子計算機に電気通信回線を通じてその制限を免れることができる情報又は指令を入力して当該特定電子計算機を作動させ、その制限されている特定利用をし得る状態にさせる行為

要約すると「本人の許可なしに認証情報/脆弱性を使って操作をしてはいけない」という内容だろうか。たしかにこれは倫理的にも問題がある行為だし、内容としては妥当な法律であるかもしれない。

では、ちょっと別の事例を考えてみよう。あなたの所属するインテリジェンスチームでは「自組織に関連するサイバー脅威のIoCを収集し、信頼性の高いものをSOCに提供してほしい」というインテリジェンス要求を達成する必要があったとする。アナリストは自組織のネットワーク境界やインターネットから日本に関連するであろうサイバー攻撃関連のIoCを収集し、評価・分析をして継続的にSOCにインテリジェンスを配布することになるだろう。

日本にばらまかれるマルウェアには様々な種類のものがあるが、ここではAgent Teslaという情報摂取型のマルウェアについてとりあげてみよう。
このマルウェアは感染した端末のクレデンシャル情報を収集した後、他の感染者(攻撃者が独自で作成したものの場合もある)から認証情報を盗んでコントロール配下となったメールやFTPサーバに対して認証を行い、盗んだ情報を転送するといった動作をする。
news.sophos.com


例えば、以下の検体は日本のIPアドレスからANY.RUN というオンラインサンドボックスに投稿された、FTPサーバに対して情報を転送するタイプの例である。
app.any.run


ここで一つの疑問が生まれる。『意図的にオンラインサンドボックスマルウェアをアップロードした結果、他人の認証情報を勝手に使用してアクセスしてしまった場合は不正アクセス禁止法に該当するのだろうか?』と。

。。。筆者が文面を読む限りでは、このようなケースも「不正アクセス禁止法に該当する」のではないかと思われる。いきなり「逮捕!!」という事態にはもちろんならないとは思うが、不正アクセス禁止法非親告罪である以上、当人や当人を含んだ所属組織に恨みのある第三者によって「あの人、このサービスを使って他人の許可なく認証情報を入力して不正利用しましたよ!!」と告発されてしまったら、当人が貶められるなんてことは十分考えられるだろう。(筆者は法律の専門家ではないため、もしかしたら見当違いのことを話しているかもしれない。そうであったら申し訳ない。)

では検体をアップロードまではしなくとも、インテリジェンスで重要な再現性をとるために、ANY.RUN にある "Restart" ボタンを押してもう一度解析を行い挙動を確認してIoCを整理したとしよう。これは、どうだろうか? 同じく、VirusTotal にある Reanalyze ボタンを押した場合は? 。。。どちらも再度通信は飛んでいくため、アウトな気がしてならない。

「じゃあ細かい操作は一切せずに結果だけ確認すればいいではないか」という話であるかもしれない(そもそも論として、結果を収集するのみで独自で分析をしないという行為はすでにインテリジェンスではないのだが、一旦脇に置いておこう)。では他の誰かがインターネット上に情報を公開するのを待ち、その結果だけを受け取れというのは果たして誠実な行いなのだろうか。これは言い換えれば、「君がやると犯罪になるかもしれないけど、他の誰かがやったものの結果だけを閲覧する分には犯罪じゃないから、誰かがやるのを待ちなさい」という、ただただ実行犯を自分以外の誰かになりすつけるだけの言葉な気がして、筆者は倫理的な問題を抱えているような気がしてならない (筆者の倫理観が狂っているということもあるのかもしれないが)。ここまで疑心暗鬼になるとすべてをローカル環境で分析するしかなくなってしまうのだが、これが「外部のインテリジェンス要求にこたえるための活動のはずなのにそのインテリジェンスの詳細を外に出しにくい」というなんとも不合理な現実を生み出すのである。

これはあくまで一例であるが、そのほかにも権限設定があまいAPI keyや攻撃者が設置したWebshellなど、調査を深ぼりしていくうえで「これってどこまでやったら法で裁かれるんですか?」という場面にはたびたび遭遇する。現実問題、筆者も何度も直面した経験があるため、チームに「これ、やってもええと思いますか?」と議題を投げかけることがたびたびある。そのほかにも、「IPアドレスを入れるとサービスを調査しますが脆弱性検査まではしませんよ」と謡っておきながら、悪性パケットを送り付けているサービスも存在するかもしれない。「hogehoge はしてはならない」と論じるのは容易いが、実際のアクティビティが本当に「hogehoge」を含んでいないことを保証できるかというのは技術に対して深い造詣がなければなしえず、初~中級者にとっては注意喚起をされてもその境界は不明瞭のままであろう。殊更"倫理"に関しては、個人による事象の受け止め方の差が激しく、より一般論的に語ることが困難である。

守破離


ここまで散々倫理・法について述べてきたが、筆者は善悪問答がしたいわけでも倫理に関する哲学をしたいわけでもない。先で述べたかったことは、「OSINTを生成する以上、その生成過程においていずれ倫理・法的な問題に直面する」ということであり、これに疑問を呈する方は、おそらくそのインテリジェンスがどのようにして生成されてきたかについて無知でいられる人間だけであろう(少々、表現方法がよくない気がするが)。

しかしだからと言って、OSINTについて紹介や研修をする人間・組織が「OSINTは倫理や法の問題が付き物だから、ライン見極めながらどんどん調査をしていこうね」なんてことを無責任に唱えることはまずできない。特に不正アクセス禁止法もアウトの境界線が明瞭でない以上、日本では一歩道を外れたら違法になるようなOSINTという存在は、一般論的には制約をかけた状態で紹介せざるを得ないだろう。筆者もOSINTに関する研修を作成したことがあるが、外部の人間にも話す以上不幸があってはいけないと思い、ツールやサービスの紹介では注意事項を執拗に記述していた。このような背景が、「OSINTは倫理・法に背くアクティビティを含んではならない」と考えている人の多くにあるのかもしれない。ある意味、日本における"守"的なOSINTの考え方である。

しかしながら、組織・消費者のインテリジェンス要求に対して少しでも価値の高い答えを返そうとすると、"守"のみの考え方は厄介な"限界"として立ちはだかってくる。このあたりの課題感が、ちらほら見られた「倫理・法の遵守は無理がある」という"破", "離"側にいるアナリストの考えなのではないかと思われる。この課題に遭遇した場合、個人の判断で調査を継続するにはリスクが大きすぎるので「ここまでは調査しましたがここから先は法的にグレーゾーンになります。しかし、深ぼりすればより価値の高いインテリジェンスになると思うのですが調査を継続しますか?」といった具合で組織側の意思決定に委ねてもらうのが最善手になるのではないだろうか。情報処理安全確保支援士などの資格もこのあたりの倫理を縛ってくる一方で、活動の幅を広げてくれるような特権は何一つ与えてくれない。保守的な組織では活動が非常に制限されてしまっているため、真面目に取り組んでいるアナリストほど守的なOSINTに対する限界に嘆いているのではないかと思われる。

なお、本記事も「これがOSINTなんだ!!」といった"守"寄りの内容ではなく、"破"に向かっている捻くれた人間が書いているものである。一般論ではなく、話半分で見てもらうほうがよいだろう。

これからのOSINTの話をしよう

さて、話が少しずれたのでまた本題に戻そう。『Intelligence ≠ Collection』の節において、筆者なりのOSINTの定義とは「組織・顧客のインテリジェンス要求を達成すること目的として公開情報を収集・分析し、 組織の情報戦に関わる意思決定に継続的に貢献すること」であることと述べた。
しかしながら、界隈でここまで様々な意見が飛び交うことを踏まえても、OSINT という単語の解釈は個々人によって解釈に大きな開きがある。ここでは一旦「なぜここまで解釈の幅が広くなってしまったのか」という理由を整理し、それをもとにこのOSINTという単語をどう扱っていくべきか再検討を試みる。

なぜOSINTの解釈がここまで広いのか、に対する一考察

それが虚無ならば虚無自身がこのとほりで
ある程度まではみんなに共通いたします
(すべてがわたくしの中のみんなであるやうに
 みんなのおのおののなかのすべてですから)

まず、どうしてOSINTという言葉にはこんなにも解釈に違いがあるのか、筆者なりにいくつか仮説を立ててみた。

  • そもそも "Intelligence" という言葉の認識が多くの人に誤解されている。
  • 『公開情報』から調査したことを、広義的な意味で"OSINT"と紹介している人・記事がある
  • ネタ的なコンテキストで使われた"OSINT"がそのまま公的な場面で使われる

どれも当たらずとも遠からずな仮説だが、筆者の考えでは"OSINT"という言葉を使う人が増えたことが影響として大きいのではないかと考えている。少々乱暴な表現をするならば、『専門用語の認知度があがりすぎて非専門家がこのワードを多用することになった』ことが現在の事態に拍車をかけているのかもしれない。OSINTという言葉が少々キャッチーな言葉なので、使用することによって検索に引っかかりやすかったりすることもあるのだろう。『Joint Publication 2-0: Joint Intelligence』の冒頭だけを切り取って解説したようなWeb記事を見て、「公開情報をいい感じに使ってもっと価値のある何かにすればそれがインテリジェンスなのか!」といった少々異なる理解をしてしまった方もいるのかもしれない。

それとは別に、「OSINTで特定しましたw」のようなちょっとしたネットミームチックな表現を見て、「これもOSINTって言うんやな」と解釈をした人もいるのだろう。様々な理由が考えられるが、OSINT という言葉が様々なコンテキストで使われるようになった真髄には、その汎用性の高さが背景にあるのではないかと筆者は考えている。「公開情報を使っていい感じに何かしました」というふわっとしたニュアンスで、技術的に詳しくない相手に対してもそのイメージを伝える言葉として優秀なのだ。「〇〇というWebサイトで△△について調べて、発見した××をまた別のツールで...」なんてことをわざわざ言わなくても、「OSINTした」というだけで「あーなんかいい感じに調べたら見つかったんだろうなー」と相手が解釈してくれれば、それでコミュニケーション自体は成立するのである。本来の"OSINT"の意味からは乱れが生じていても、"ある程度まではみんなに共通"するイメージによって相手が都合のいいように解釈してくれる。そのような魔力が、このOSINTという言葉に備わっているのかもしれない。

その一方で、ある一定数の人間にとってOSINTという言葉は "みんなに共通" するイメージから逸脱してしまっている、というのが今回の騒動によって明るみになったことだろう。現に、元来の言葉の意味から大きく外れたものも「OSINT」の派生として解釈されているため、専門家にとってはコンテキストをきちんと把握しなければそれが自分が普段扱っているOSINTなのかを判断できない状況に陥っている。同じような騒動を繰り返さないためにも、「我々はOSINTという単語をどう扱っていくべきか」ということを今一度考え直す必要があるのかもしれない。

我々はOSINTをどう扱うべきか


筆者が考える "OSINT" という単語を使用する上で留意すべき事項は次の二点である。

  1. 単語の共通認識が確立されている組織内でのみ使用すること
  2. そもそもの使用を避けること

しかしながら、どちらの事項についてもこの記事を読んでいる人よりもOSINTという単語を雰囲気で使い続けている人に宛てているので、果たして本記事で言及することで現状が改善されるかというとそれは定かではない。もし上記を逸脱しているような使い方を確認した場合、ぜひあなたが警察として動いていただきたい。

まず一つは、OSINTというワーディングの使用に際して、それ含む専門用語の共通認識が確立されている組織でのみ持ち出すべきという点である。もっともインテリジェンスに携わる業務をしていれば、OSINTに限らずそれにかかわる専門用語は山のように出てくるわけであるが、解釈がブレる最たる例が推定確率言語といった信頼水準を表現するワーディングだろう。推定確率言語はインテリジェンスの信頼性を表現するうえで必要不可欠であるが、これに世界標準的なものは存在せず、どのようなワードで信頼性を表現しても間違いではない。しかし、使用するワードの認識が統一されていなければその信頼性の評価は真価を発揮しないのは明らかである。
en.wikipedia.org


そのため、インテリジェンスチームに所属するアナリストは「蓋然性が極めて高い」や「蓋然性が非常に高い」といった言葉を雰囲気で使い分けているわけではない。「信頼性が99.9%なら"極めて高い"を、80%以上程度ならば"非常に高い"を使用します」という取り決めを組織に認識させたうえで、チームのアナリストにもこの意味での使用を統一させているのである。

筆者が所属するインテリジェンスチームの場合、内部で使用される専門用語は『脅威インテリジェンスの教科書』にほぼ統一されており、意思決定者に語彙の詳細な意味を問われた場合は「教科書のP.〇にあるこの定義に沿っています」と返すことができるようにしている。インテリジェンスサービスによっては「弊サービスは以下のような確証度に基づいて推定確率単語を使用しています」といった共通認識をすり合わせるためのページを用意してくれているものも存在するだろう。
gihyo.jp


これは極端な例であるが、それでもインテリジェンスというものは用語集の準備や意思決定者とのコミュニケーションなどを組織的に取り決めて推進していかなければ、その共通認識をすり合わせること自体が困難なのである。もしかしたら組織内部でのコミュニケーションを円滑にするために、ある組織では一般とは少し異なる意味合いで解釈を統一している単語というのも存在するかもしれない。そのため、第三者同士がいきなり対面して「OSINTが~」なんて話をしても、最悪の場合「全く学習をしていないけれども専門用語を雰囲気で使っている」というケースも存在する以上、本人の意図通りに相手に内容が伝わるかはかなり怪しい。
ちなみに、筆者は「インテリジェンス業務やってます」と言った流れで「業務の一環で"OSINT"もやってますよ」と言った結果、対話相手に「ダークウェブを監視している人」として認識されたことがある。面倒なので訂正はしなかったが、おそらくその組織におけるOSINT業務というのは、ダークウェブをモニタリング・分析して得られたインテリジェンスが主となって回っているのだろう。その組織においてそれが"OSINT"だと定義されているとしても、筆者はそれが間違っているとは思わない。しかしながら、"OSINT"という言葉に対する理解と認識はその人の生活圏によって大きく異っているおそれがあり、例え自分が正しく言葉を使用していたとしても、異文化同士のコミュニケーションになりうるということは念頭に置く必要はあった。皆も筆者のような誤解を生まないためにも、共通認識が確立された同じ文化圏でのみ、インテリジェンスにかかわる用語を使っていただいたほうが賢明である。


そしてもう一つ、これを言うと元も子もないのかもしれないが、OSINTという単語をそもそも使用しないように心がけるということだ。よくよく思い返してみると、筆者はインテリジェンスチームに所属してからかれこれ1年半になるが、業務中に"OSINT"という単語が飛び交っていたことはおそらく1度か2度くらいしかない。アナリストは「〇〇について△△で分析した結果と、それに対する考察です」といった具合で非常に正確な言葉を使用するし、分析を終えたアナリストも「これ、ほんとうにインテリジェンスだったんかな~」という感想を漏らすことさえある。最終的に意思決定者にレポーティングする際は「OSINT」といった体裁を整えた文面を使用するが、フィードバックを終えていない段階で"インテリジェンス"という単語を土俵に出すのは、アナリスト側にとっても勇気のいる行動ではないかと思う。そういった背景があってか、筆者も"OSINT"という単語を持ち出すことは滅多にない。本年筆者がJSACに持ち出した講演のタイトルは「Investigation for Continuous Cyberespionage Based on Open Source (公開情報を基にした標的型攻撃の調査)」であって、情報収集とその分析手法について述べられてはいるが、果たしてインテリジェンスの定義を満たしているかというとそれは要議論であったため、そこに "OSINT" という文面は存在していないのである。*4(内部資料でも使用していない)


忘れてはいけないことだが、OSINTはれっきとした専門用語である。その道に詳しくない人に対して、そうやすやすと濫用すべき言葉ではない。「If all you have is a hammer, Everything looks like a nail (ハンマーしか持っていなければ、すべてが釘に見える)」 なんていう諺にあるとおり、人間は道具を手にすればなるべくそれを使ってみたくなるし、新しい言葉を覚えた日にはなるべくその言葉に当てはめてみたくなるものである。あなたがOSINTという言葉のハンマーを手にしているとき、「打とうとしているモノは果たして本当に釘なのだろうか」という思考は頭の片隅においておくべきだろう。特に、インテリジェンスを生成するための単発のアクティビティをOSINTと表現しているものについては、そっくりそのまま短い日本語で表現できるものが非常に多いのは事実である。「Googleで〇〇と画像検索して見つけた」, 「Shodanで〇〇というクエリで検索した」, 「URLhaus から〇〇にかかわるIoCの一覧を取得した」などである。こちらのほうが理解しやすいし、OSINT警察に突っ込まれることもなくなるだろう。特に公的な場ではさらなる乱れを生まないためにも、正確な単語をチョイスすることを推奨したい。


最後に、筆者は決して「OSINTという単語を俺の前で使うな」と主張したいわけではないことを補足しておく。筆者が伝えたいのは「OSINTというのはあくまで一般人が直感的に理解することが難しい"専門用語"であることを忘れてはいけない」ということであり、インテリジェンスアナリストやベンダーを咎める意図は全くない。
筆者も、『直近1か月分の、公開情報をもとに調査した敵対国に関する国際情勢とサイバー空間上での動向分析、および自社の対応にかかわる提言書です』と言われたら「なんのこと??」と頭にクエスチョンマークが浮かぶが、『Monthly OSINT Report』と言われれば「あーね」といった心持ちで文書に目を通すことができる。話し手と聞き手に用語への共通理解があれば、まどろっこしい言い回しをいい感じに表現できる便利な単語であることは揺るぎない事実である。


おわりに

ここまでOSINTについて論じてきて最後の最後にはしごを外すのも申し訳ないが、筆者は"OSINT"という単語を原理主義的なまでに正しく使うべきだとは思っていないし、究極的なところ雰囲気で使っている人がいても別にいいとも思っている。 要は"OSINT"という単語の存在によって言語コミュニケーションが円滑になり、なおかつ使用者が所属しているインテリジェンスチームが組織に対して価値のあるアウトプットを出し続けられさえすればそれでいいのだ。Shodanでの調査結果を「素晴らしいOSINTですね!」とCIOやCISOがコメントしたことに対して、「いやいやオンラインサービスを利用した調査自体はOSINTとは言わんのですよ!」と角が立つことを言わなくても、"ある程度まではみんなに共通"するものが伝わっていればそれでよいとさえ思う。

しかしこれはローカルに閉じた環境での話であって、このノリを世間一般に対して持ち出すと途端にコミュニケーションのミスや筆者のようなOSINT警察の発現につながることだろう。なぜなら、あなたの想像している"OSINT"と、別の誰かが知っている"OSINT"は似て非なるモノかもしれないからだ。『A Nice Derangement of Epitaphs (墓碑銘のすてきな乱れ)』を"異名のすてきな言い回し"と、聞き手がすてきな乱れによって解釈してくれる保証はどこにもないのである。
サイバーセキュリティの文脈で"インテリジェンス"という専門用語を持ち出す場合、果たしてそれが最も適した表現であるかというのは使用者側が今一度考えたほうがいいかもしれない。


そういえば、筆者がどんなことをしている人間なのか話すのを失念していました。『自組織に対する脅威の調査やそれに関連するシグネチャ作成および脆弱性のPoC検証といったセキュリティ技術・運用支援』と表現するには視点がミクロすぎるし、『多角的視点からの分析による、中長期的なセキュリティ施策および意思決定支援』と語ってしまうと抽象的すぎて何も伝わりません。。。そうだ、『脅威インテリジェンス』やってますと表現するのが一番しっくりきますかね。
......ここまでの駄文に付き合っていただきありがとうございました。

*1:『Joint Publication 2-0: Joint Intelligence』, https://irp.fas.org/doddir/dod/jp2_0.pdf

*2:もしプロセスや能力部分の内容をビジュアルに確認したい方がいらっしゃれば、『The Sliding Scale of Cyber Security』というWhitepaperを参考にしていただきたい。

*3:https://elaws.e-gov.go.jp/document?lawid=411AC0000000128

*4:ちなみに、同じようにJSACにて講演を行った瀬治山さんについても、タイトルは「公開情報により攻撃動向の予測を行う新たな試みと調査手法の共有」であり、OSINT という単語はabstract中にも用いられていなかった。

日本の標的型攻撃で利用される某国製RATの自動解析ツールの使い方

tl;dr

本稿は JSAC2023 で紹介したLODEINFOマルウェアトリアージツールの使い方をまとめたものです。有事の際はご参照ください。

はじめに

JPCERT さんから "LODEINFO" という日本に対する標的型攻撃で使用されるRAT(マルウェア)が報告*1されて早3年が経ちますが、2023年3月現在でも少しずつTTPsを変えながら継続して使用されています。このような背景からインシデントレスポンス対応者への一助として、下記のGithubにて暗号化されている通信を復号するためのツールを公開しました。

github.com

本ツールについては JSAC2023*2でも簡単に紹介しましたが、使い方には一切触れなかったのでどのように扱うのが効果的か把握できていない方もいらっしゃるかと思います。本稿ではこれまでわかりにくいREADMEだけ書いて放置していた解析ツールの使い方を簡単に紹介します。LODEINFO 関連のインシデントに対応している方の一助になれれば幸いです。

復号の基本原理

LODEINFO が C2 server との communication で使用するデータフォーマットおよびデータの変換方式は様々な記事、カンファレンスでまとめられているので好きなものを参考にしていただければと思います。今回は JSAC2023 で紹介されたPDFの画像を引用しながら説明します。

まず、LODEINFOマルウェアがC2 serverとやりとりするフォーマットはヘッダー部(前半部分)とデータ(後半部分)の2つのデータがそれぞれ異なる方式で暗号化された後、文字列として連結された状態で送信されています。なので、復号するためには固定長のヘッダーを切り分け、それぞれのデータごとに復号する必要があります。

LODEINFO データ構造

具体的には、以下のようなロジックで復号を行います

  • ヘッダー部分
    1. vigenere cipher (文字列のインデックスをベースにした換字式暗号)
    2. 一部の文字列を置換したBase64
  • データ部分
    1. 一部の文字列を置換したBase64
    2. データの一部にsingle byte XOR
    3. AES-256-CBC
    4. QuickLZ

これだけだとイメージがわかないと思うので、具体的な通信データのイメージを見せると以下の図のようになります。黄色部分が固定長のヘッダー部分の文字列なので、そこでデータを区切ってそれぞれに上記の復号処理をかけることで中身を見ることができるようになるわけですね。

具体的な通信でみられるデータ

python を使って通信を復号する

上記の復号ロジックを python のコードにしたものが decode_connection.py となります。同ディレクトリにある requirements.txt から必要なライブラリをインストールするだけで使用できます。*3

github.com

ただし、LODEINFO は検体ごとに異なるAESのKeyとIV, vigenere cipher keyを使用します。検体を解析してそれらの情報を取得し、KEY, IV, VIGENERE_KEY の3変数に設定してください。

コードの変更部分

変数が設定できたら、最後に通信として観測できたデータを SAMPLEDATA 変数へ入れましょう。あとは下記のようにただ decode_connection.py を実行するだけで、データが復号されるはずです。なお、client => C2 server 方向の通信であれば vigenere cipher の key は毎回変わるので、VIGENERE_KEY の変数は使用しません。C2 server => client 方向の通信には検体内部にハードコードされた vigenere cipher key を使用するため、変数に値を入れる必要があります。

#  KEY = a2b_hex("20AD7B28FE0D2D223C48A76E35EE0DA3AEA2B1175D69804605EC43EA4687F785")
#  IV = a2b_hex("8D5291164B7414118D0C8AC7C050FD1E")
#  VIGENERE_KEY = "zlApZbCgpp_"
#  SAMPLEDATA = "AB34bTyi5o_=w8VCUPIIRBvPp08lpwxFeug1tuEhYA2BB2MGCvH...(snip)"

❯ python decode_connection.py 
HEADER(sha512_128=b'e87d884fa9005a7c2963b7a41bca4ad2', payload_size=244)
BEACON(data_size=62, random_data_size=24, date=datetime.datetime(2022, 8, 18, 19, 11, 46), ansi='932', mac_addr='000C2932F71A', computer_name='DESKTOP-81OMVP8', xor_key='zlApZbCgpp_', version='v0.6.3', random_data=b'cV4dXd7e5tIKGmK8ZdHBtw..')

直接コードの変数に手を加える必要があるお行儀が悪いコードになっていて申し訳ありません。ゆくゆくは外部のyamlファイルなどに値を書く方式にしたいかなと思っています。ひとまずは、RATが行った通信を簡単に復号するためのPoCとして利用できるかなと思います。

IDAPython を使って暗号化に必要な情報を一括で取得する

前項では 『AES のKeyとIV, vigenere cipher keyを取得する』とサラッと書きましたが、復号に必要な情報を集めるためには LODEINFO 本体の静的解析が必須になります。つまり、アナリストがshellcodeを読み該当の領域を特定する必要があるのですが、リバースエンジニアリングに精通している人でなければこの作業を行うのは少々酷です。そこで、「スクリプトを使うことで復号に必要な情報を簡単に抽出しよう」という思想から作成したツールが下記の triage.py となります。

github.com

本ツールは IDAPython コードとなっており、IDA Pro を使える方ならば LODEINFO の暗号化された shellcode (BLOB ファイル)をIDA Proで開き、メニューバーから "File" -> "Script files..." の順にクリックして上記の triage.py を開くだけでOKです。実行後は自動的に復号された shellcode とその .idb ファイルが開かれ、検体のバージョン情報, AESのkeyとiv, vigenere cipher key などが Output 画面に表示されていることでしょう。この文字列をコピペして、先ほど紹介した decode_connection.pyに書き込めば通信が復号できるようになります。

triage.py 実行後

なお、「暗号化されたBLOB ファイルがわからない!」という方は、正規の署名付き実行ファイルとDLLの同ディレクトリにあるPE形式ではないファイルを探してみてください。例えば、LODEINFO v0.6.3 の場合は K7SysMon.Exe.db が該当します。(下記画像参照)

BLOB ファイル(K7SysMon.Exe.db)

2023年3月現在で観測している最新のバージョンでも動作することは確認していますので、IDA Proが使える方は活用してください。

おわりに

現在も日本で猛威をふるっている標的型検体のトリアージツールについてドキュメントを残しました。

一部のスクリプトはIDAPythonで書かれているため、IDA Proを持っていない人には使えないというのが現状の課題かなと思っています。もし Ghidra script 版や機能追加の希望があれば、Issueを立てていただけると次回ツールを作る際の参考やモチベにさせていただきます。

皆さんのインシデント対応が少しでも楽になりますように。

*1:https://blogs.jpcert.or.jp/ja/2020/02/LODEINFO.html

*2:https://jsac.jpcert.or.jp/archive/2023/pdf/JSAC2023_1_6_minakawa-saika-kubokawa_jp.pdf

*3:python でエラーが出る! という方は、python のバージョンを3.9くらいまであげてください。古いバージョンだとtyping回りでエラーとなります。3.7 もあと数か月でEoLなのでこの機会にあげてしまいましょう!!