Sterra Security Tech Blog

株式会社ステラセキュリティの公式技術ブログです

ARM環境でディスアセンブルを妨害するテクニック(32ビット編)

取締役CTOの小竹(aka tkmru)です。 ディスアセンブルを妨害するアンチディスアセンブルという耐タンパ性を高めるための技術があります。 本記事では、32ビットのARM環境(以下、ARM32)で有効なアンチディスアセンブルのテクニックを紹介します。

静的解析を妨害するアンチディスアセンブル

リバースエンジニアリングの方法の1つに、バイナリをディスアセンブル(逆アセンブル)した結果を読み解く静的解析があります。 ディスアセンブルというのは、バイナリを機械語からアセンブリ言語に変換することです。 静的解析では、アセンブリ言語の命令を読み解くことで、プログラムの挙動を明らかにします。

アンチディスアセンブル(Anti-Disassembly)は、静的解析を妨害するために、ディスアセンブルを正常に行えなくする技術です。 解析を逃れるために、攻撃者がマルウェアに用いることもあれば、チートを防ぐためにゲームに用いられることや、 不正なコピー防止のためにソフトウェア製品に用いられることもあります。

ARMでのアンチディスアセンブルx86/x64に比べ困難

x86/x64では、アセンブリ言語の命令は可変長です。 x86/x64の場合、命令が可変長であることを利用し、命令の途中のバイトを分岐先として解釈させるなどして、 命令間の境界をディスアセンブラに誤認させることで、比較的容易にアンチディスアセンブルを実現できます。

しかし、ARMの命令は固定長です。 ARM32では、命令の長さは32ビット(4バイト)で固定です。 例外として、16ビット(2バイト)のThumb命令セットがあります。 これは、プログラムのサイズを削減し、消費電力を低減するために設計された命令セットです。 Thumb命令を使用するには、動作モードを切り替える必要があります。 ARMでは、このようにほとんどの命令が固定長であるため、命令間の境界を誤認させることが難しく、アンチディスアセンブルを実現するのが難しくなります。

PLD命令を活用したアンチディスアセンブル

PLD(PreLoad Data)命令は、メインメモリからL1/L2キャッシュにデータを読み込む命令です。 メモリアクセスの高速化のために用意されています。 公式リファレンスには、次のシンタックスで利用できると記載されています。 レジスタで指定されたアドレスにオフセットを加算して、そのアドレスにあるデータを読み込みます。

PLD [レジスタ, オフセット]

PLD命令に指定されたアドレスを、IDA Proなどのリバースエンジニアリングツールは、データとして解釈します。 そのため、PLD命令にコードが存在するアドレスを指定すると、そのアドレスにある命令はディスアセンブルされません。 このように、PLD命令を活用して、アンチディスアセンブルを実現できます。 L1/L2キャッシュを前後で使用していなければ、PLD命令を挿入してもプログラムの動作に影響はありません。 PLD命令に指定できるアドレスにはアライメントの制限がない点、変なアドレスを読み込んでしまっても例外を発生させない点も良い点です。

PLD命令を挿入する

シンプルなHello, world!という文字列を出力するだけのプログラムにPLD命令を挿入し、IDA Pro、Ghidraでディスアセンブルしてみます。 PLD命令のオペランドには、次に実行する命令を指すPCレジスタを指定します。

#include <stdio.h>

int main() {
    __asm__ volatile(
        "pld [pc]\n"
    );
    puts("Hello, world!\n");
    return 0;
}

コンパイルと実行

x64のUbuntu 22.04でARM32のクロスコンパイル環境を構築し、QEMUというエミュレータを使ってコンパイルしたプログラムを実行してみます。 実行したいプログラムのアーキテクチャとPCのアーキテクチャが異なる場合は、QEMUのようなエミュレータを使わないと実行できません。

まず、aptコマンドを使って、コンパイラQEMUをインストールします。

$ sudo apt install -y gcc-arm-linux-gnueabihf qemu-user-static

インストールが完了したら、次のコマンドでプログラムをコンパイルします。 先ほどのプログラムはinsert-pld.cというファイルに保存してあるとします。

$ arm-linux-gnueabihf-gcc -marm insert-pld.c -o insert-pld

コンパイルが完了したら、QEMUを使って実行します。 環境変数QEMU_LD_PREFIXを使って、プログラムが使う共有ライブラリのパスを指定する必要があることに注意してください。 指定しないと、/ld-linux-armhf.so.3が見つからないというエラーが発生します。 次のように問題なく実行できることを確認できるはずです。

$ export QEMU_LD_PREFIX='/usr/arm-linux-gnueabihf/'
$ qemu-arm-static insert-pld
Hello, world!

ディスアセンブル結果の確認

IDA Proでディスアセンブルした結果を確認してみましょう。 狙い通り、アンチディスアセンブルが成功しています。 PLD命令のオペランドに指定されたアドレスをデータとして解釈しているため、そのアドレスにある命令はディスアセンブルされていません。

ディスアセンブル結果を確認できないだけでなく、Graph viewを表示できないことも確認できます。

Ghidraでもディスアセンブル結果を確認してみましょう。 意外なことに、Ghidraではアンチディスアセンブルが成功していません。 これは、PLD命令のオペランドに指定されたアドレスを解釈していないからです。 IDA Proほど気が利かない多機能でないことが良い方向に作用していると言えるでしょう。

オフセットを調整し、任意のアドレスの命令にアンチディスアセンブルを施す

PLD命令ではレジスタで指定したベースアドレスに対するオフセットを指定できます。 これを用いて任意のアドレスのコードにアンチディスアセンブルを施すことができます。 アドレスを調整して、PLD命令があるアドレスの直後にある命令に対してアンチディスアセンブルを施してみましょう。

#include <stdio.h>

int main() {
    __asm__ volatile(
        "pld [pc, #-4]\n"
    );
    puts("Hello, world!\n");
    return 0;
}

今回のプログラムも先ほどのプログラムと同様の手順でコンパイル、実行できます。 IDA Proでディスアセンブルした結果を確認すると先ほどとはアンチディスアセンブルの対象が異なっていることが分かります。

まとめ

この記事では、ARM32で有効なアンチディスアセンブルのテクニックを紹介しました。 PLD命令を活用することで、ディスアセンブルを妨害することができます。 この記事で紹介したテクニックを応用し、NOP Sledを組み合わせたり、PLD命令とディスアセンブラが解釈できないよう一部のバイトを壊したりすることで、 解析をより困難にすることもできます。応用例についても機会があれば紹介したいと思います。

また、今回紹介したテクニックは、Ghidraには全く効かず、GhidraはIDA Proよりも優位でした。 しかし、リバースエンジニアリングを行っていると反対にIDA Proの方がディスアセンブルの精度が高いことの方が多いです。 耐タンパ性を高める取り組みをする際は、複数のリバースエンジニアリングツールで検証することが重要です。

PLD命令は、64ビットのARMアーキテクチャ(AArch64、ARM64)では使用できません。 次の記事では、64ビットのARM環境で有効なアンチディスアセンブルのテクニックを紹介する予定です。

弊社のセキュリティ技術顧問サービスでは、 今回紹介したようなリバースエンジニアリングに関する技術を調査したり、耐タンパ性の向上に活用したりするコンサルティングも行っています。 ご興味のある方は、お気軽にお問い合わせください。

参考文献

パッチを当てるPythonスクリプトを生成するIDAプラグイン「genpatch」を作った話

取締役CTOの小竹(aka tkmru)です。

先月、genpatchというIDA Pro上で当てたパッチと同じパッチを当てるPythonスクリプトを生成するIDAプラグインを公開しました。 この記事では、作成した「genpatch」の使い方、仕組みを紹介します。

困っていたこと

スマホアプリが対象の脆弱性診断では、準備段階でリバースエンジニアリングを行い、パッチを当てることがあります。 SSL Pinning(Certificate Pinning、証明書のピン留め)をお客様側で無効化していただけなかった場合には、解析を行い、無効化するパッチを当てた上で、APIとの通信を診断します。 SSL Pinningは、使用するSSL証明書をアプリ内にハードコートし、通信時にSSL証明書がアプリ内のものか検証を行うことで、SSL通信の中間者攻撃を防ぐ仕組みです。 Burp Suiteなどのプロキシツールを使ってSSL通信を閲覧する際には、PCにインストールしたプロキシツールの証明書を使用しています。 そのため、SSL Pinningが実装されているアプリに対して、プロキシツールを使用して通信を閲覧しようとすると、SSL証明書の検証に失敗し、通信が行えません。

診断期間中に診断対象のアプリがアップデートされた場合、パッチを当て直す必要があります。 その際に、IDA Proを起動し、パッチを当て直す1のは面倒です。 また、IDA Proの操作に慣れていないチームメンバーにパッチを当ててもらうのも、大変です2。 そのため、IDA Pro上で当てたのと同じパッチを当てるPythonスクリプトを生成するプラグインを作成しました。

作ったツール

genpatchというIDA Pro上で当てたパッチと同じパッチを当てるPythonスクリプトを生成するIDAプラグインを作成しました。 genpatchが生成したパッチを当てるPythonスクリプトを使用することで、 繰り返しバイナリにパッチを当てる際に、Pythonスクリプトを実行するだけで済みます。 このプラグインPythonで実装しています。

github.com

インストール方法

リポジトリ内のgenpatch.pypatch_script_template.txtをIDA Pluginフォルダにコピーし、IDA Proを再起動するとgenpatchが使えるようになります。 Windowsの場合、コピー先のフォルダはC:\Program FilesIDA 8.x\pluginsです。 MacOSの場合、コピー先のフォルダは/Applications/IDA Pro 8.x/idaq.app/Contents/MacOS/pluginsにあります。

パッチを当てるPythonスクリプトを生成する

IDA Pro上でパッチを当てた後、Edit -> Plugins -> genpatchボタンをクリックすると、IDA Proで読み込んだバイナリがあるディレクトリにパッチスクリプトが生成されます。 スクリプトの名前は、解析中のバイナリに接尾辞 _patch.pyを付けたものになります。 例えば、バイナリ名が a.out の場合、パッチスクリプト名は a.out_patch.pyとなります。

Pythonスクリプトが正常に生成されると、以下のようなダイアログが表示されます。

生成したPythonスクリプトを実行する

コマンドライン第一引数にパッチを当てたいバイナリへのパスを指定して実行することで、パッチを当てることができます。

$ python a.out_patch.py <target_binary_path>

生成されたPythonスクリプトは次のようになります。16進数のデータ列を置換します。

#!/usr/bin/env python
# coding: UTF-8

import binascii
import os
import re
import sys

target_path = sys.argv[1]
target_data = None
with open(target_path, 'rb') as target_file:
    target_data = binascii.hexlify(target_file.read()).decode('utf-8')

# address: 0x100000ecb
# function name: __text: _main
# comment: Keypatch modified this from:   jz loc_100000EF6 Keypatch padded NOP to next boundary: 4 bytes
matches = re.findall('0f8425000000', target_data)
if len(matches) == 1:
    target_data = target_data.replace('0f8425000000', '752990909090')
else:
    print("Patch pattern isn't unique")
    sys.exit()

result_path = f'{target_path}_patched'
with open(result_path, 'wb') as result_file:
    if sys.version_info[0] >= 3:
        result_file.write(bytes.fromhex(target_data))
    else:
        result_file.write(target_data.decode('hex'))

print("Successfully generated patched binary to '%s'" % result_path)

おわりに

弊社ではこのように脆弱性診断中に遭遇した課題を解決するべく、適宜ツールを開発し、業界内に知見を共有していきます。 また、「genpatch」が脆弱性診断、マルウェア解析などリバースエンジニアリングを伴う仕事に従事するエンジニアに広く使われるよう育てていきたいと思っています。 ぜひ、気づいたことがあればフィードバックしてもらえるとうれしいです。 みなさまからのIssueやプルリクエストをお待ちしております。


  1. Unity製のスマホアプリではすべてのロジックがC++製の共有ライブラリに実装されるのでパッチを当てるのにIDA ProやGhidraを使う必要があります。Javaで実装されたAndroidアプリであればSmaliファイルを編集するだけで済みます。
  2. IDA Proのライセンスを用意するのも大変です。

アップロード機能の検証のためのファイルを作成するツール「dummy」を作った話

取締役CTOの小竹(aka tkmru)です。

dummyというファイルアップロード機能の検証用の静的ファイルを作成するコマンドラインツールを公開しました。 指定したテキストを書き込んだJPEGファイル、PNGファイル、PDFファイルを生成でき、PNGファイルに関してはサイズ(バイト数)の指定も行えます。 この記事では、作成した「dummy」の使い方、仕組みを紹介します。

アップロード機能の検証の際に困ること

ファイルアップロード機能を対象に脆弱性診断を行うとき、どんな画像をアップロードするか、いつも悩みます。 ペンテスターでなくともフリー素材ではないネットミームの画像や自分が食べた美味しいご飯の画像を業務で使用するのには少し気が引けるでしょう。 クライアント(顧客)のサーバにファイルをアップロードする脆弱性診断では、なおさらです。 そこで、誰が見ても悪い印象を受けない検証用の画像を作成するためにツールを作りました。

また、扱えるファイルのサイズに制限がある場合、その制限が有効になっているか確認したいときがあります。 その制限に引っかかるような大きいサイズのファイルを用意するのは少し大変です。 そういう場合にも対応できる、任意のサイズのファイルを作成できるツールが必要でした。

作ったツール

検証用の静的ファイルを作成する「dummy」というコマンドラインツールを作りました。 前述した通り、指定したテキストを書き込んだJPEGファイル、PNGファイル、PDFファイルを生成でき、PNGファイルに関してはサイズ(バイト数)の指定も行えます。 Pillowという画像処理ライブラリを使用したかったため、Pythonで実装しています。

github.com

使い方

インストール方法や各種パラメータの指定方法を紹介します。

インストール方法

pipコマンドでインストールできます。 Pythonの実行環境を整えた上で、次のコマンドを実行してください。

$ pip install git+ssh://git@github.com/sterrasec/dummy.git

ファイルを生成する

生成したいファイルのパスはオプションなしで指定できます。 また、生成するファイルの種類は拡張子によって自動で識別されます。 -tオプションでファイルに書き込むテキスト、-bオプションでバイト数を指定できます。 -bオプションはPNGファイルを生成するときのみ使用できます。

$ dummy -t abc -b 1MB test.png

指定したサイズの画像が生成される様子

-tオプション、-bオプションは指定しなくとも使用できます。 -tオプションでテキストを指定しない場合は、デフォルトの「dummy file」というテキストが書き込まれます。

$ dummy test.jpeg

デフォルトで生成される画像

どのようにして任意のサイズのPNGファイルを生成しているのか

小さすぎないバイト数を指定しない限り、「dummy」では任意のサイズのPNGファイルを作成できます。 これをどのように実現しているのか解説します。

PNGファイルはチャンクと呼ばれるデータブロックから構成されています。 IHDRや、IDATIENDなどのチャンクが知られています。 IHDRは、画像の幅や高さ、色深度、圧縮方式などの情報を持っています。 IDATは、画像データを持っています。 IENDは、PNGファイルの終端を表します。

独自のチャンクを作成することもできます。 チャンクは、チャンクタイプ、チャンクデータ、CRCという3つの要素から構成されています。 これらのデータを適切に挿入することで、PNGファイルの機能を損なわずにファイルを大きくすることができます。 「dummy」では、eXtrという無意味なデータ列から構成される独自のチャンクをIENDチャンクの手前に挿入することで、指定されたバイト数になるよう、データ量をかさ増ししています。

おわりに

「dummy」が脆弱性診断、QAに従事するエンジニアに広く使われるよう育てていきたいと思っています。 ぜひ、気づいたことがあればフィードバックしてもらえるとうれしいです。 みなさまからのIssueやプルリクエストをお待ちしております。

書籍「ポートスキャナ自作ではじめるペネトレーションテスト」が9/20に発売されます

取締役CTOの小竹(aka tkmru)です。

オライリー・ジャパンより拙書「ポートスキャナ自作ではじめるペネトレーションテスト -Linux環境で学ぶ攻撃者の思考(通称: カワウソ本)」が9/20に発売されます。本記事では構成、見どころを紹介します。

表紙はかわいいカワウソ🦦です!

本書の構成

次のように、6章の本編と2章の付録より、構成されています。 ポートスキャンの原理から、ポートスキャンによって見つけたサービスへの攻撃、 攻撃を成功させた後はさらなる被害拡大へと徐々にステップアップして理解できる構成になっています。

  • 1章:攻撃者はいかにしてシステムを攻撃するのか
  • 2章:Scapyでポートスキャナを自作し動作原理を知ろう
  • 3章:デファクトスタンダードのポートスキャナNmap
  • 4章:既知脆弱性を発見できるネットワークスキャナNessus
  • 5章:攻撃コードを簡単に生成できるMetasploit Framework
  • 6章:攻撃者はどのように被害を拡大するか
  • 付録A:ペンテスターが安全にキャリアを形成する方法
  • 付録B:ペンテスターと良好な関係を築く方法

1章では攻撃者がシステムを攻撃していくプロセスをUnified Kill Chainを題材に解説しています。 2章から6章では、Dockerコンテナの演習環境を用いて具体的なテクニックを学べます。 2章ではScapyを用いてポートスキャナとARPスプーフィングのexploit(攻撃コード)を実装し、ネットワークへの理解を深めます。 3章から5章ではNmap、Nessus、Metasploit Frameworkといったペンテストにおけるデファクトスタンダードのツールの解説をしています。 6章では、Linux環境で攻撃を成功させた後にさらに被害を拡大する、Post-Exploitationに使える技術について解説しています。

付録Aでは、誤解を招く行動を取れば逮捕されることもあるペンテスターが安全にキャリアを形成する方法を、 付録Bでは、ペンテストの依頼者の方やペンテスターの上司の方向けにペンテスターと良好な関係を築く方法をそれぞれ紹介しています。

こだわりポイント

説明の際には、ツールの紹介をするだけではなく、コーディングや脆弱性を攻撃する演習を設けることで、ツールの使い方だけを紹介しているマニュアルのような書籍にならないよう心がけました。 また、ツールの説明をするパートでは、業務でどのようにツールを活用しているのかを説明し、実務に役立つ知識を記載するように心がけました。 ツールは便利であるものの万能ではなく、結局は手を動かして脆弱性を検証する必要があるという脆弱性診断、ペネトレーションテストを行う上での本質に本書を通して触れることができます。 最後に頼りにできるのは、自分の手で行った作業だけです。 「ツールは役にたたない」というメッセージ性が強い書籍になったと思います。

Unified Kill Chainやレジデンシャルプロキシ、細かいPost-Exploitationのテクニックといったあまり日本語文献がないような概念、他の書籍では紹介していないようなマニアックなツールの機能を紹介し、初学者の方だけではなく実務に従事している方が読んでも楽しめるようにしました。 付録Bの「ペンテスターと良好な関係を築く方法」には、実務を行う上で遭遇するトラブルについて記載しており、こちらも実務をやっている方に、楽しんでもらえる内容だと思います。

攻撃者の思考を知ることはセキュリティエンジニアのみならず開発者にとっても大切です。 開発者は日々発見される、OSやライブラリなどの大量の脆弱性の対応を日常的に迫られていますが、 攻撃者の思考を分かっていなければ、何が脅威なのか分からず脆弱性のリスクレベルを評価できません。 開発者の方が読んでも楽しめるよう、攻撃手法だけでなく対策についても記載しています。 また、セキュリティエンジニアが当然のように使うものの、開発者の方には馴染みがない単語は平易な言葉に置き換えるよう心がけました。 例えば、「バイパス(Bypass)」は「突破」「迂回」といった単語に置き換えています。 開発者の方にも読んでほしいです。

表紙のカワウソ🦦が可愛いのでカワウソが好きな方にもおすすめです。

電子版はO'Reilly Japan Ebook Storeより購入できます

おわりに

本書の執筆にあたり、多数の方にご協力いただきました。 オライリー・ジャパンの方々、本書のレビューに協力していただいた皆様には、この場を借りて心からお礼申し上げます。

似た構成の本は世界中を探してもなさそうな、 初学者の方にも実務に従事している方にも面白いと思ってもらえる書籍に仕上がったと思います。 広く多くの方に読んでもらえるとうれしいです。

Nmapの日本語ドキュメントを更新した話&その方法の解説

取締役CTOの小竹(aka tkmru)です。

先日、Nmapというポートスキャナの日本語ドキュメントにコントリビュートしました。 この記事では、日本語ドキュメントの現状とコントリビュート方法の解説を行います。

デファクトスタンダードのポートスキャナNmap

Nmap(Network Mapper)は、セキュリティ業界でデファクトスタンダードのポートスキャナです。 ポートスキャンを行えるだけではなく、Luaスクリプトによって機能を拡張でき、多数の脆弱性を攻撃するためのスクリプトがデフォルトで含まれています。

1997年から存在するツールで、「マトリックス リローデッド」や「ダイ・ハード4.0」などの映画の中のハッキングシーンにもたびたび登場しており、セキュリティエンジニアであれば誰もが知る有名ツールです。 Nmapが登場した映画は次のURLにまとめられているので興味がある方は見てください。

nmap.org

日本語ドキュメントは古く役に立たない...

そんな有名なNmapですが、日本語ドキュメントは長年更新されていませんでした。 Nmapの最新バージョンは7.93ですが、日本語ドキュメントはバージョン4.501相当のものになっています。 そのため、コマンドライン引数に実際とは違うものが記載されているオプションが多数あり、それを鵜呑みにしていると、正しく使うことができないという状況です。

というわけで、コントリビュートしました!

以前より、時間を指定するオプションの引数が現在のバージョンではtimeなのに、millisecondsと日本語ドキュメントに記載されているのが気になっていました。例えば、スキャンに時間がかかるホストをスキャンした際に、一定時間経過したらスキャンを停止する--host-timeoutオプションの引数の説明がこれに該当します。timeは、<数値><単位>というフォーマットを意味します。例えば、30分と指定する場合は30m、10秒と指定する場合は10sというふうに記述します。

そこで、このような間違った説明が頻出する「タイミングとパフォーマンス」のページにコントリビュートを行い、引数の表記を正しいものへと修正を行いました。 該当コミットは次のURLです。 github.com

引数の説明が修正されている様子

コントリビュートするには

日本語ドキュメントにどのようにしてコントリビュートを行うのか解説します。 NmapにはNmap Man Page Translation FAQという翻訳に関するガイドラインが存在します。 NmapのドキュメントはXMLで文書を記述できるDocBook XMLというフォーマットで記述されており、そのフォーマットの説明が書かれています。

nmap.org

日本語ドキュメントのファイルはdocs/man-xlate/nmap-man-ja.xmlに、英語ドキュメントのファイルはdocs/refguide.xmlに存在します。 ファイルに変更を加えたら、作者にメールするか、プルリクエストを送ることで反映してもらえます。 上記ガイドラインには、メールするように書かれていますが、実際はプルリクエストでも大丈夫です。

まとめ

Nmapの日本語ドキュメントの問題点とコントリビュート方法を紹介しました。 日本語ドキュメントに問題を感じているものの、コントリビュート方法が分からなかった人も多いのではないかと思います。

今回、私が更新した部分はほんの一部で、まだまだ直さないといけないところが残されています。 世界平和のために、日本語話者のNmapユーザーのみなさんにコントリビュートしていただけるとうれしいです。


  1. 日本語ドキュメントが準拠しているバージョン情報については以前GitHubのIssueで問い合わせました。https://github.com/nmap/nmap/issues/2243

セキュリティ・キャンプ全国大会2023脅威解析クラスで講義を行います

取締役CTOの小竹(aka tkmru)です。

セキュリティ・キャンプ全国大会2023の脅威解析クラスにて「ポートスキャナ自作から始めるペネトレーションテスト入門〜Linux環境で学ぶ攻撃者の思考〜 」という題で講義を行うことになりました。 本記事では、セキュリティ・キャンプ全国大会2023というイベントと、そこで私が行う講義内容の紹介をします。

セキュリティ・キャンプとは

セキュリティ・キャンプは、将来の高度IT人材となり得る優れた人材の発掘と育成を目的としたイベントの総称です。 IT業界で活躍しているエンジニアなど*1が講師になり、学生の皆さんに講義を行います。 講義を聴講できるだけでなく、同世代の同じことに興味がある人たちと交流できるのも良いところです。 参加費は無料で経済産業省が共催しており、主催にIPA独立行政法人情報処理推進機構)もいるので安心して参加できます。

全国各地で2日間程度で開催される地方大会と都内で5日間程度開催される全国大会があり、私が講義を行うのは全国大会の方です。 2020年から2022年にかけてはコロナ禍の影響でオンライン開催でしたが、今年より以前の合宿形式に戻ります。 今年の全国大会は8月7日(月)~8月11日(金)にかけてクロス・ウェーブ府中にて開催されます。 全国大会は、日本国内在住で、日本国内の学校に在籍する13歳以上22歳以下の学生の方が対象です。

www.ipa.go.jp

私も学生時代に参加者として参加していました。 オンライン開催だった2020年と2021年にプロダクトセキュリティトラックにて以前講師を務めましたが、 参加者の皆さんと対面で行う講義はまだ行ったことがないので、直接皆さんにお会いできる今年のセキュキャン*2は楽しみです!

どんな講義をするのか

「ポートスキャナ自作から始めるペネトレーションテスト入門〜Linux環境で学ぶ攻撃者の思考〜 」という題で講義を行います。 講義紹介ページには次のように概要を記載しています。

脆弱性診断やペネトレーションテストで使われる技術のひとつにポートスキャンがあります。 セキュリティエンジニアがネットワークやインフラに対するネットワーク診断やペネトレーションテストを行う際には最初にポートスキャンを行います。 開いているポートがあれば、何かおもしろい情報が返ってこないか確認し、古いミドルウェアが動いていることがわかれば、脆弱性情報を調べて攻撃を試行します。
本講義では、ポートスキャナを自作し、動作原理について理解を深めた後、Dockerコンテナで構成されたLinux環境に対して演習を行い、脆弱性の発見/攻撃手法、端末に侵入後の攻撃者の思考について学びます。侵入後の攻撃者の活動のことを広義にPost-Exploitationと呼びます。

パケットを自由に操作できるようになっておくことや、PoC(Proof of Concept)のコードを素早く実装できることは、ペンテストに必要なスキルです。
例えば、Nmapに実装されていない特殊なプロトコルで通信するソフトウェアの脆弱性を調査したい場合は、プロトコルの仕様に従ったパケットで通信するためのツールを自作する必要があります。このような理由から本講義では、ポートスキャナの自作を行います。

攻撃者の思考を知ることは、マルウェア解析や通信監視業務に従事している人たちも含め、すべてのセキュリティエンジニアが知っておくべき内容であり、 セキュリティエンジニアを目指す初学者にとっても必要不可欠な知識です。 また、セキュリティエンジニアのみならず開発者にとっても大切です。 開発者は日々発見される、OSやライブラリなどの大量の脆弱性の対応を日常的に迫られていますが、 攻撃者の思考を分かっていなければ、何が脅威なのか分からず脆弱性のリスクレベルを評価できません。 脆弱性診断やペネトレーションテストに従事している講師が攻撃手法を解説し、攻撃者側の思考プロセスや、攻撃されないようにするにはどうすればいいのかといった防御側の手法までを解説します。

※本講義では、リバースエンジニアリングは行いません。

ペンテストツールの仕組みや、攻撃者が脆弱性を見つけた後、どのように被害を拡大していくのかについて学べる講義にしようと思っています。 「ツールをただ単に使うだけでは満足できない」「各脆弱性の攻撃方法ではなく、攻撃者の思考を知りたい」という方におすすめです。 ポートスキャナを自作するというアイデアは、私が学生時代に参加したセキュリティ・キャンプキャラバン in 大阪 2014での吉田英二さんによる「パケット工作」という題の講義のオマージュです。

応募お待ちしております!

エントリーの締め切りは5月15日で、応募課題の締め切りが5月22日です。 エントリーしておかないと応募できないので、とりあえずエントリーしておくことをおすすめします! エントリーはこちらからできます。 参加者の皆さんに現地でお会いできるのが楽しみです。 応募お待ちしております!

*1:自分で書くのは恥ずかしいですね...!

*2:セキュキャンはセキュリティ・キャンプの略称です。

VRヘッドセットからの通信をプロキシツールで確認する方法

取締役CTOの小竹(aka tkmru)です。

AndroidベースのVRヘッドセットでは、Android端末と似た方法でMITM(Man In The Middle attack)を行い、 プロキシツール上で通信内容を確認できます。 脆弱性診断の際には対象のアプリケーションとAPIサーバの通信を確認・編集する必要があり、MITMを行います。 また、アプリケーションを開発する際のデバッグにもMITMは有用です。 本記事では、ByteDances社製のPICO 4というVRヘッドセット(以下、VR端末)でMITMを行う方法を解説します。

USBデバッグを有効にする

VR端末でプロキシに関する設定を行うには、adbコマンドを多用します。 そのため、プロキシの設定を行う前にVR端末で開発者向けオプションを有効にし、USBデバッグを有効にする必要があります。 設定アプリを開き、「一般」>「デバイス情報」の順にメニューを操作すると表示される「ソフトウェアバージョン」を連続して7回クリックすると開発者向けオプションを有効にできます。

開発者向けオプションを有効にすると、設定アプリに「開発者」メニューが出現しています。 「開発者」メニューを開き、USBデバッグを有効にしてください。また、USB接続をファイル転送に使えるよう設定されていることを確認してください。

スクリーンショットは/sdcard/Pictures/Screenshots/に保存される

プロキシツールのCA証明書をインストール

プロキシツール上でHTTPS通信を見ようと思うと、プロキシツールのCA証明書をVR端末にインストールする必要があります。 まず、adbコマンドを用いて、プロキシツールから出力したCA証明書をVR端末内にコピーしてください。 Burp Suiteの証明書ファイルをPICO 4にコピーするコマンドは次のようになります。 他のプロキシツールをお使いの場合は、ファイル名を適宜変更してください。

$ adb push cacert.der /sdcard/Download/cacert.cer

通常のAndroid端末であれば、端末内の証明書ファイルを何らかのエクスプローラーから選択すれば、証明書のインストーラーが起動しますが、PICO 4の場合は証明書ファイルを選択しても「このファイル形式は現在サポートされていません」と表示され、インストーラーが起動しません。 そのため、adbコマンドからインテントを用いて、Androidデフォルトの証明書のインストーラーを起動します。 次のコマンドを実行すると、証明書のインストーラーを起動できます。

$ adb shell am start --activity-clear-top -a android.credentials.INSTALL

証明書のインストーラーが起動したら、VR端末内の証明書ファイルを選択してください。

インテントから起動される証明書のインストーラーの画面

VR端末内の証明書ファイルを選択すると証明書の各種情報を入力できます。 証明書の名前を指定し、認証情報を「VPNとアプリ」に使うよう選択してください。 OKボタンを押すとCA証明書がインストールされます。

証明書ファイルを選択した後のインストーラーの画面

プロキシツールのアドレスを指定する

VR端末から出る通信がプロキシツールを経由するように設定する必要があります。 AndroidにはデフォルトでプロキシのIPアドレス、ポートを指定する機能が備わっており、それを用います。 GUIの設定アプリから設定する方法とadbコマンドを用いて設定する方法の2つの方法を紹介します。

設定アプリから行う

通常のAndroid端末であれば、設定アプリ内の「ネットワークとインターネット」メニューでプロキシに関する設定を行えます。 しかし、PICO 4独自の設定アプリからはプロキシの設定を行うことができません。 そのため、adbコマンドからインテントを用いて、Androidデフォルトの設定アプリを起動します。 次のコマンドを入力するとAndroidデフォルトの設定アプリが起動します。

$ adb shell am start --activity-clear-top -a android.settings.WIRELESS_SETTINGS

ここからは、通常のAndroidアプリと同様の方法でプロキシを設定できます。 接続しているAPの詳細設定よりプロキシのアドレス、ポートを指定できます。

インテントから起動されるAndroidデフォルトのネットワーク設定画面

support.google.com

コマンドで設定する

adbコマンドを用いてプロキシのIPアドレス、ポートを設定することもできます。 次のようにadb shell settings put global http_proxyIPアドレス、ポートを指定し、実行してください。

$ adb shell settings put global http_proxy 192.168.100.10:8080

プロキシの設定を削除するには次のようにコマンドを実行してください。

$ adb shell settings put global http_proxy :0

設定を正常に行えているか確認

ここまでの設定に成功していれば、プロキシツール上にVR端末からの通信が表示されます。 プロキシを正常に設定できているかの確認にはブラウザから何らかのWebサイトへアクセスするのがおすすめです。

Androidアプリに対してMITMを行う場合は、APK内のres/xml/network_security_config.xmlに ユーザーが指定したCA証明書を信頼する旨を記述する必要があります。 そのため、他の第三者が開発したアプリではパッチを当てない限りMITMを行えません。 第三者が開発したアプリをプロキシの設定の確認に使用するには不適です。

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <base-config>
    <trust-anchors>
      <certificates src="system" />
      <certificates src="user" />  # ユーザーが指定したCA証明書を信頼
    </trust-anchors>
  </base-config>
</network-security-config>

developer.android.com

また、アプリ内の特定の証明書でしか通信できないように制限するSSL Pinning(証明書のピン留め)が実装されている可能性もあります。

おわりに

VR端末からの通信をプロキシツールで確認する方法を解説しました。 脆弱性診断時にはこのような作業を行い、対象のアプリケーションの通信内容を確認・編集しています。 当社はAndroidアプリの脆弱性診断に加えて本記事のようなVR端末のアプリに対する脆弱性診断も実施しております。 詳しくはフォームよりお問い合わせください。 本記事が脆弱性診断に携わるセキュリティエンジニアやVRアプリの開発者の方々の参考になれば幸いです。