BSD界隈四方山話

第92回DTraceの使い方 その12

セキュリティ

今回はコマンドの実行を捕捉してログファイルに出力するサンプルDスクリプトを取り上げます。内容は、"DTrace Dynamic Tracing In Oracle Solaris, Mac OS X & FreeBSD", by Brendan Gregg and Jim Mauro"のP.886から掲載されているスクリプトです。ソースコードは次のようになっています。FreeBSDでの実行向けに内容は多少書き換えてあります。

リスト watchexec.d
#!/usr/sbin/dtrace -s

#pragma D option destructive
#pragma D option quiet

inline string REPORT_CMD = "/usr/local/bin/reporter.sh";

dtrace:::BEGIN
{
    /*
     * Ensure this contains all the reporting commands,
     * otherwise this script will be a feedback loop:
     */
    ALLOWED[REPORT_CMD] = 1;
    ALLOWED["/bin/sh"] = 1;

    /*
     * Commands to allow.
     */
    ALLOWED["/bin/sh"] = 1;
    ALLOWED["/bin/ls"] = 1;
    ALLOWED["/bin/pgrep"] = 1;
    ALLOWED["/bin/pkill"] = 1;
    ALLOWED["/bin/cat"] = 1;
    ALLOWED["/bin/chmod"] = 1;
    ALLOWED["/usr/bin/basename"] = 1;
    ALLOWED["/usr/bin/grep"] = 1;
    ALLOWED["/usr/bin/head"] = 1;
    ALLOWED["/usr/bin/openssl"] = 1;
    ALLOWED["/usr/bin/ssh"] = 1;
    ALLOWED["/usr/bin/tput"] = 1;
    ALLOWED["/usr/bin/tr"] = 1;
    ALLOWED["/usr/bin/uname"] = 1;
    ALLOWED["/usr/sbin/chown"] = 1;
    ALLOWED["/usr/sbin/mountd"] = 1;
    ALLOWED["/usr/sbin/nfsd"] = 1;
    ALLOWED["/usr/local/bin/bash"] = 1;
    ALLOWED["/usr/local/sbin/nginx"] = 1;

    printf("Reporting unknown exec()s to %s...\n", REPORT_CMD);
}

syscall::exec*:entry
/ALLOWED[copyinstr(arg0)] != 1/
{
    /*
     * Customize arguments for reporting command:
     */
    system("%s %s %d %d %d %Y\n", REPORT_CMD, copyinstr(arg0),
        uid, pid, ppid, walltimestamp);
}

このDスクリプトの見どころは特定のコマンドは捕捉の対象からはずす処理をしているところと、捕捉したデータをログファイルに保存するために外部スクリプトを実行している点にあります。外部スクリプトは/usr/local/bin/reporter.shとして用意され、内容は次のようになっています("DTrace Dynamic Tracing In Oracle Solaris, Mac OS X & FreeBSD", by Brendan Gregg and Jim Mauro"のP.887に掲載されているシェルスクリプトです⁠⁠。

引数を/var/log/execlog.txtに追記するだけのシェルスクリプトです。

リスト reporter.sh
#!/bin/sh

echo "$*" >> /var/log/execlog.txt

このDスクリプトではsystem()という標準ライブラリ関数と同じ名前の関数を使って外部のシェルスクリプトを実行しています。このシェルスクリプトを経由してモニタリング内容がログファイルに出力される仕組みになっています。Dスクリプトからファイルにデータを出力する方法として参考になります。

このDスクリプトを実行すると次のようになります。Ctrl-Cが入力されるまでモニタリングを実施し、捕捉された内容が/usr/local/bin/reporter.shを経由してログファイルに出力されていきます。

 watchexec.dを実行中。Ctrl-Cでモニタリング終了
% sudo ./watchexec.d
dtrace: 1 dynamic variable drop

捕捉されたコマンドデータは随時ログファイル(/var/log/execlog.txt)に追記されていきますので、tail(1)でデータを見えるようにしておくと、次のような感じで記録されていく内容をチェックできます。

 記録されているログ内容を閲覧
% tail -f /var/log/execlog.txt
/usr/local/bin/fish 501 37978 25303 2017 Mar 21 18:05:18
/usr/bin/sed 501 37994 37978 2017 Mar 21 18:05:18
/usr/bin/sed 501 37995 37978 2017 Mar 21 18:05:18
/usr/bin/sed 501 37998 37978 2017 Mar 21 18:05:18
/usr/bin/awk 501 38096 37978 2017 Mar 21 18:05:18
/usr/bin/tr 501 38097 37978 2017 Mar 21 18:05:18
/usr/bin/sed 501 38098 37978 2017 Mar 21 18:05:18
/usr/bin/ssh-add 501 38099 37978 2017 Mar 21 18:05:18
/usr/bin/uname 501 38100 37978 2017 Mar 21 18:05:18
/usr/bin/seq 501 38102 37978 2017 Mar 21 18:05:18
/usr/bin/seq 501 38103 37978 2017 Mar 21 18:05:18
/usr/bin/seq 501 38104 37978 2017 Mar 21 18:05:18
/bin/hostname 501 38105 37978 2017 Mar 21 18:05:18
/usr/bin/tr 501 38106 37978 2017 Mar 21 18:05:18
/usr/bin/sed 501 38108 37978 2017 Mar 21 18:05:18
/usr/bin/awk 501 38109 37978 2017 Mar 21 18:05:18
/bin/hostname 501 38129 37978 2017 Mar 21 18:05:35
/usr/bin/tr 501 38130 37978 2017 Mar 21 18:05:35
/usr/bin/sed 501 38132 37978 2017 Mar 21 18:05:35
/usr/bin/awk 501 38133 37978 2017 Mar 21 18:05:35
/usr/bin/tail 501 38139 38138 2017 Mar 21 18:07:12
/bin/date 501 38141 38138 2017 Mar 21 18:07:18
/usr/sbin/wake 501 38146 38138 2017 Mar 21 18:07:40
/usr/sbin/fdwrite 501 38148 38138 2017 Mar 21 18:07:48
/usr/sbin/ppp 501 38150 38138 2017 Mar 21 18:07:52
/usr/bin/ppp 501 38150 38138 2017 Mar 21 18:07:52
/usr/local/sbin/ppp 501 38150 38138 2017 Mar 21 18:07:52
/usr/local/bin/ppp 501 38150 38138 2017 Mar 21 18:07:52
/Users/daichi/bin/ppp 501 38150 38138 2017 Mar 21 18:07:52
/Users/daichi/ttt/ppp 501 38150 38138 2017 Mar 21 18:07:52
/usr/sbin/pkg 501 38157 38138 2017 Mar 21 18:08:05
/usr/local/sbin/pkg 501 38157 38138 2017 Mar 21 18:08:05

watchexec.dは短いながらも、Dスクリプトの挙動を変更する値の定義、インライン文字列の定義、コメント、配列、system()関数の利用など、さまざまな機能がコンパクトにまとまっていて参考になります。実行されたコマンドの絶対パスを使って処理を切り分けているところなんかもDスクリプトっぽい部分です。侵入検知に利用できるスクリプトでもありますので、ぜひ一度実行してみてください。

ここに掲載したサンプルスクリプトは"DTrace Dynamic Tracing In Oracle Solaris, Mac OS X & FreeBSD", by Brendan Gregg and Jim Mauro P.886、P.8807より抜粋およびFreeBSD向けに内容を一部書き換えたものです(FreeBSDで実行した結果を掲載しています⁠⁠。

勉強会

第62回 4月28日(火)19:00~FreeBSD勉強会 エンジニアのための英会話入門 ~なぜ英語ができないのか~ br> 講師: 後藤大地(BSDコンサルティング株式会社)

FreeBSDの情報の多くは英語で入手できます。ほかの言語と比べると日本語は翻訳されたドキュメントが豊富にありますが、メーリングリストやフォーラム、ブログやTwitterなどを経由して最新の情報を得ようとすれば英語が必要になります。また、日本を含め世界中で開催されている*BSD関連のカンファレンスで使われているのも英語です。FreeBSDのエンジニアとやり取りしようとすれば、多くの場合は英語が使えた方が便利です。

日本は義務教育の間に英語を学びますが、いざそうしたやりとりをしようとすると尻込みしてしまう、そんな方が多いというのが現実でしょう。今回の勉強会では、そうした方に向けて、なぜ勉強したのに英語ができないのか、ちょっとでも英語ができるようにするには、まずどういったことを知ればよいのか、そういったことをご紹介しようと思います(英語ほとんどできない、という方でも大丈夫です。試しに勉強しに来てください :)

参加申し込みはこちらから。

第63回 5月23日(火)19:00~ FreeBSD勉強会

現在検討中です。

FreeBSD勉強会 発表者募集

FreeBSD勉強会では発表者を募集しています。FreeBSDに関して発表を行いたい場合、@daichigotoまでメッセージをお願いします。1~2時間ほどの発表資料を作成していただき発表をお願いできればと思います。

おすすめ記事

記事・ニュース一覧