BSD界隈四方山話

第93回DTraceの使い方 その13

セキュリティ

今回はセキュリティ的に実行を監視しておきたいユーザの動作をトレースするDスクリプトを取り上げます("DTrace Dynamic Tracing In Oracle Solaris, Mac OS X & FreeBSD", by Brendan Gregg and Jim Mauro"のP.889に掲載されているスクリプトです⁠⁠。

ユーザとグループ、それにパーミッションの設定を組み合わせることで特定のユーザにだけ実行を許可するといったようなことをさせることができるのですが、この仕組みだけで動きを実現しようとするとグループの数が増えまくることがあります。だいたいそのうち管理が面倒になってきて、穴のある設定をしてしまったりします。

DTraceを使うと、シンプルな設定にしておいて、かつ、特定のユーザ以外の処理を拒否するといったことを実現できます。これは結構便利な機能です。次のDスクリプトを見てください。

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

#pragma D option quiet
#pragma D option destructive

inline int ALLOWED_UID = 501;

dtrace:::BEGIN
{
	printf("Watching setuid(), allowing only uid %d...\n", ALLOWED_UID);
}

/*
 * Kill setuid() processes who are becomming root, from non-root, and who
 * are not the allowed UID.
 */
syscall::setuid:entry
/arg0 == 0 && curpsinfo->pr_uid != 0 && curpsinfo->pr_uid != ALLOWED_UID/
{
	printf("%Y KILLED %s %d -> %d\n", walltimestamp, execname,
	    curpsinfo->pr_uid, arg0);
	raise(9);
}

このDスクリプトは、スーパーユーザ(UIDが0)またはUIDが501のユーザのみがsetuid(2)システムコールを使ってスーパユーザ(UIDが0)になることを許可するという処理をします。UIDが0または501以外のユーザがスーパーユーザになろうとするとそのプロセスは終了させられます。raise(SIG)は現在実行中のプロセスに指定したシグナルを送信するというもので、raise(9)で現在実行中のプロセスにKILLシグナスを送信して処理を終了するということになります。

setuid(2)というシステムコールはたとえばsu(8)コマンドで別のユーザになるときに呼ばれます。つまり、setuid(2)システムコールを捕捉しておくと、指定したユーザ以外がsu(8)コマンドでrootに成ろうとした場合に処理を強制的に終了させることができるわけです。あるユーザに特定の処理を実行する権限は与えたいものの、それ以外の処理は拒否したいといった場合にこうしたスクリプトが使えます。

 nosetuid.dを実行
# ./nosetuid.d
Watching setuid(), allowing only uid 501...

上記のようにDスクリプトを実行しつつ、別のターミナルでたとえばUIDが501のユーザがsu(8)コマンドでスーパーユーザになろうとしても何もいつもと違うことは起こりません。

 UID 501のユーザはsu(8)コマンドでスーパーユーザになろうとしても問題ない
% id
uid=501(daichi) gid=20(staff) groups=20(staff),0(wheel),5(operator),501(daichi)
% su -l
Password:
# id
uid=0(root) gid=0(wheel) groups=0(wheel),5(operator)
#

今度はUIDが501以外のユーザで同じ処理を行おうとすると、パスワード入力後に何事もなかったかのようにsu(8)コマンドが終了してしまいます(FreeBSDの場合su(8)コマンドでスーパーユーザになるにはwheelグループに所属していることが前提になります⁠⁠。

 UID 501以外の一般ユーザはsu(8)コマンドでスーパーユーザになろうとしても処理が続かない
% id
uid=1001(sasaki) gid=1001(sasaki) groups=1001(sasaki),0(wheel)
% su -l
Password:
% su -l
Password:
%

Dスクリプトを実行したターミナルを見てみると、対象となる処理を捕捉して強制終了を実施していることがわかります。

 許可していないユーザのsetuid(2)を捕捉してプロセスを終了している
# ./nosetuid.d
Watching setuid(), allowing only uid 501...
2017 Mar 27 13:13:33 KILLED su 1001 -> 0
2017 Mar 27 13:14:23 KILLED su 1001 -> 0
2017 Mar 27 13:14:27 KILLED su 1001 -> 0

こんな感じでシステムコールの捕捉とユーザIDでの切り分けを実施してあげれば、特定のユーザだけ処理を許可してそれ以外のユーザの処理は終了させるといったことができるわけです。アドホックなやり方だとは思いますが、一時的に権限を与えておきたいといったような場合なんかは簡単に処理を実施できますし、便利でわかりやすい機能です。

※ ここに掲載したサンプルスクリプトは"DTrace Dynamic Tracing In Oracle Solaris, Mac OS X & FreeBSD", by Brendan Gregg and Jim Mauro P.889より抜粋したものです(FreeBSDで実行した結果を掲載しています⁠⁠。

勉強会

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

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

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

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

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

現在検討中です。

FreeBSD勉強会 発表者募集

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

おすすめ記事

記事・ニュース一覧