いますぐ実践! Linuxシステム管理

[バックナンバーのトップへ] [Linux システム管理のトップへ]


いますぐ実践! Linux システム管理 / Vol.109 / 読者数:1095名

こんばんは、うすだです。

このメルマガは、たいてい、日曜と月曜の間の深夜に書いています。

事前に仕上げておけばよいのでしょうが、そんな計画性がわたくしにあるはずもなく、 深夜になってせっぱつまってから、油成分を多く含んだ汗をまき散らしつつ、 せっせと書いております。

しかし、毎週毎週、綱渡り的になんとか発行していることに、 われながらびっくりします。(たまーにお休みすることもありますけどね。)

過去に、よっぱらって気持ち悪くなり、今日はもう無理、 絶対書けない…と諦めかけたこともありました。

でも、ぎりぎりのところで、「ぎりぎりの神様」が助けてくれます。
仕事でもそうです。もうこれは納期に間に合わないよー! というときに、 「ぎりぎりの神様」が、ぱっとヒントをくれて、 逆転満塁ホームラン的に間に合うことが、よくあります。(だめなときもありますが…。)

よくはわからないのですが、「ぎりぎりの神様」という名称を思いついたときから、 自分には「ぎりぎりの神様」が見守ってくださっているのだ、 と思うようにしています。すると、最後まで諦めちゃいけない、 と自然に考えるようになることが多いのです。不思議ですね。

というわけで、今週も「ぎりぎりの神様」に助けられながら、 はりきってまいりたいと思います。

今週のお題 - コマンドをラップして使う

どんなに気をつけていてもバグをなくすことができないように、 どれほど気をつけていても、セキュリティホールをなくすことはできません。

一般的に普及しているツールやコマンド類であれば、 早急にパッチが提供されるかもしれません。 しかし、開発が止まっていたり、独自に作成したツールなどの場合、 パッチの提供すらままならない可能性があります。
(rsh や rlogin など、ポリシーがそうなっているモノもありますよね。)

とはいえ、ユーザのみなさんが普段使っていたり、 なんらかのサービスがそのコマンドを利用していますと、 使用禁止にするわけにもいきません。

そんなときによく使われるのが、 ラッパーと呼ばれるプログラムを用いる方法です。
ホンモノのコマンドを実行する代わりにラッパーを実行することで、 不正な引数や設定を(ラッパーにチェックさせて)事前に察知し、 不正な利用を防ぐことができます。

というわけで今週は、安全でないコマンドをラップして、安全に使う方法を、 ご紹介したいと思います。


まずは、引数をチェックするラッパーを、考えてみたいと思います。

以降では、wget コマンドを対象にしていますが、 wget に問題が多いとか過去に問題がよく発生していた、 というわけではありません。
引数に URL を指定できるというだけの理由で、今回使わせていただいているだけです。 念のため、釘を刺させていただきます。

で、ここでは、wget コマンド実行するために以下を満たす必要がある、 という制約を設けたいと思います。

  1. -q と -O オプションの両方が指定されていないと実行できない。
  2. -q と -O オプション以外のオプションを指定すると実行できない。
  3. URL の長さが 1024 以上だと実行できない。
  4. URL に '?' が含まれていると実行できない。

どう見ても実用的ではないですが、話を単純にするため、 ご容赦いただけますと幸いです。
では、ラッパーに、この制約のチェックを行わせてみたいと思います。

 

最初に、ホンモノの wget コマンドを、別の名前に変えてしまいます。
以下では、/usr/bin/wget を /usr/bin/.real_wget に変えています。

  # mv /usr/bin/wget /usr/bin/.real_wget

そして、/usr/bin/wget を、以下のシェルスクリプトにしてしまいます。

  #!/bin/sh
  /usr/bin/.real_wget $*

こうすることで、wget を実行すると、上記のラッパーが実行されます。
そして、ラッパーがホンモノの wget を実行します。

ただ、これですと、ラッパーはなにもチェックしませんので、意味がありません。
ですので、上記1〜4のチェックを行うスクリプトに仕立ててみましょう。
/usr/bin/wget を、以下のスクリプトにしてみてください。

  #!/bin/sh
  check=0
  if [ $# -ne 4 ]; then
      exit 1
  fi
  if [ "z$1" = "z-q" -a "z$2" = "z-O" ]; then
      check=1
  fi
  if [ "z$1" = "z-O" -a "z$3" = "z-q" ]; then
      check=1
  fi
  if [ $check -eq 1 -a ${#4} -lt 1024 -a "z`echo $4|grep \?`" = z ]
  then
      exec /usr/bin/.real_wget $*
  else
      exit 2
  fi

チェック1〜4 を満たすためには、引数が4つである必要があります。
ですので、最初の if 文では、引数が4つあることを確認しています。
次に、2つ目と3つ目の if 文で、 チェック1と2を満たしているかどうかの確認をしています。 満たしていれば、変数 check に 1 を代入します。
そして、4つ目の if 文では、チェック1と2が満たされている(checkが1)場合に、 チェック3と4 を満たしているかどうか確認し、問題なければ、 ホンモノの wget(/usr/bin/.real_wget)を実行しています。

念のため、実際に実行してみましょう。

  % wget -q -O - 'http://www.usupi.org/cre/dcontent?user=kuri'

この場合、-q オプションも -O オプションも指定していますが、 URL に '?' があるため、実際には実行されません。

…回りくどい例で申し訳ありませんが、上記のようにすることで、 引数をチェックするラッパーを、噛ませることができます。


先ほどは、安全に実行するためにチェックするラッパーを作りました。
しかし、他にも、ラッパーの便利な使いかたが、いくつかあります。

たとえば、そのコマンドは普段あまり使われることがないため、 実行したことを知りたい、記録に残したい、ということがあるでしょう。
そんなときにも、ラッパーを使うと、簡単に実現できます。

たとえば、先ほどの wget のラッパーを、以下のようにしてみましょう。

  #!/bin/sh
  /usr/bin/logger -i -t wget -p auth.notice "options: $*"
  exec /usr/bin/.real_wget $*

この場合、引数のチェックは行われませんが、 logger コマンドを使って syslog にログを残せるようになります。 (syslog の設定にもよりますが。)

  % wget -O /dev/null http://www.yahoo.co.jp/

のように実行しますと、以下のようなログが syslog に記録されます。

  wget[PID]: options: -O /dev/null http://www.yahoo.co.jp/

また、ラッパーを以下のようにすると、メールで root 宛に通知することもできますね。

  #!/bin/sh
  echo "execute wget by $LOGNAME@$HOSTNAME with $*" | \
      /usr/bin/Mail -s "[wget] notice" root
  exec wget $*

やや脱線しますが、複数の OS や CPU 上で実行するときに、 ラッパーで実行するモノを切替えることもできます。

たとえば、Linux用のバイナリと、NetBSD用のバイナリがあるとします。
これを、ラッパーで切替えるには、ラッパーを以下のようなスクリプトにします。

  #!/bin/sh
  case "`uname -s`" in
      Linux)
          exec /opt/usu/bin/foo.linux;;
      NetBSD)
          exec /opt/usu/bin/foo.netbsd;;
      *)
          echo Unknown OS...
  esac

実行したマシンが Linux なら /opt/usu/bin/foo.linux を、 NetBSD なら /opt/usu/bin/foo.netbsd を実行します。

こうすることで、OS が違っても、同じ名前のコマンドを実行することができます。


以上、コマンドをラップする方法について、いくつかご紹介しました。

ラッパーは便利ですが、もしパッケージを操作する必要があるときには、 操作する前に、ラッパーを外してコマンドを元に戻すことを、 忘れないでくださいませ。

ちなみに、今回のネタは、以下の本からいただきました。

セキュアプログラミング - 失敗から学ぶ設計・実装・運用・管理
http://www.amazon.co.jp/exec/obidos/ASIN/4873111757/usupiorg06-22

ノウハウ的な本ではなく、考え方から教えてくれる、いい本です。
ちょっと読みにくい感じもしますが、興味のあるかたは、 一度本屋さんで立ち読んでみてください。

宿題の答え

先週の宿題は、

  シェルスクリプトや Perl スクリプトに、セットユーザID を設定して
  実行し、効果がないことを確かめてみましょう。

でした。

たとえば、以下のシェルスクリプトを用意します。

  #!/bin/sh
  [ $# -ge 1 ] && touch $*

引数に指定されたファイルを touch するだけのスクリプトです。

これを、たとえば suidtest.sh という名で保存したら、 chmod コマンドでセットユーザID を設定します。

  % chmod u+rwxs,go+rx suidtest.sh
  % ls -l suidtest.sh
  -rwsr-xr-x 1 usu adm 35  6月20日 01:34 suidtest.sh*

上記では、所有者が usu さんで、ちゃんと s がついていますね。
では、自分とは違うひとに実行してもらいましょう。

  % id
  uid=10001(test) gid=99(nobody) 所属グループ=99(nobody),10000(test)
  % ./suidtest.sh /tmp/suid-test
  % ls -l /tmp/suid-test
  -rw------- 1 test nobody 0  6月20日 01:23 /tmp/suid-test

ここでは、test さんに実行してもらいました。
すると、touch コマンドで作成されたファイル(/tmp/suid-test)の所有者は、 usu さんではなく、suidtest.sh を実行した test さんです。
というわけで、セットユーザID が有効でないことがわかります。

Perl スクリプトの場合はどうでしょうか。
確認のため、以下のような Perl スクリプトを用意しました。

  #!/usr/bin/perl
  while($#ARGV >= 0) {
      my $fname = shift;
      open(TEST, ">$fname") && close TEST;
  }

先ほどのシェルスクリプトと同等ですが、touch コマンドを呼び出さず、 open してすぐ close するようにしています。
これを、同様に suidtest2.pl とかいう名にして、 test さんに実行していただきましょう。

  % ./suidtest2.pl /tmp/suid-test2
  Insecure dependency in open while running setuid at ./suidtest2.pl \
  line 4.

危ないよ、と叱られてしまいました。
セットユーザID が設定された Perl スクリプトには、 さまざまな制限がかかっているようです。

というわけで、みなさんも、Ruby とか Python とかなんでも構いませんので、 いろいろ試してみてくださいまし。

今週の宿題

今週の宿題は、

  ホンモノのコマンドを実行されないようにする方法を考えましょう。

です。

せっかくラッパーに差し替えても、 移動させたホンモノのコマンドのほうを直接実行されてしまいますと、 元も子もありません。
ホンモノのコマンドを直接実行されない方法を、考えてみてください。

あとがき

わたしが、World Wide Web なるものに遭遇したのは、 入社して少し経過したころ−たしか 1994年の秋くらいだったと思います。

当時、わたくしは、アナログ専用回線で会社をインターネットに接続し、 物珍しさから、各社のホームページなどを拝見しておりました。

しかし、ひとの作ったものを見るだけでは、面白くありません。
ですので、会社のインターネットサーバ上で WWW サーバを立ち上げて、 HTML を書いたり、CGI を動かしたりしていました。
(ちなみに、いずれも会社非公認でした。今では考えられないですね…。)

とはいえ、そういったことを独学でやるには、今日の多忙なビジネスマンには、 なかなか難しいことではないかと思います。
しかしながら、やはり、自ら実践しないと糧にならないというのは、 今も昔も変わりません。さあ、困りましたね。どうしましょう。

…というわけで、前置きが長すぎですね、すみません。
超久しぶりに、メルマガをご紹介したいと思います。

--------------------------------------------------
レンタルサーバーでHPを持っている方へ
HPでCGIを動かしてみませんか?

10日間の無料講習テキストをお送りします。
http://www.searchman.info/cgi_perl/index_rak.html
--------------------------------------------------

いまどきは Ajax とか MT とか Rails とか、 抽象化された土台を使うのが流行っているようですが、 や・は・り! 基本は CGI だと思います。

サーチマン佐藤さんが、FTP によるアップロードから、 CGI を動かすまでの一連の手順を、手取り足取り…かどうかはわかりませんが、 すべて無料で教えてくださいます。

CGI くらい書けるようになりたいけど、勉強する時間や勇気がない、 などという貴兄は、これを機会に、登録してみてください。
ステップメールですので、しまった出遅れた! ということはありません。
登録したら、ちゃんと1日目からはじまります。

「実践無くして、向上無し!」(by 発想源)ですので、 是非自らの手で CGI を動かしてみてくださいませ。

 

今週も、ここまで読んでいただき、ありがとうございました。
それでは、また来週に、お会いしましょう!

 

「いますぐ実践! Linux システム管理」の解除は、以下からできます。
http://www.usupi.org/sysad/ (まぐまぐ ID:149633)

バックナンバーは、こちらにほぼ全部そろっています。
http://www.usupi.org/sysad/backno.html

「栗日記」−栗の絵描いてるばっかりじゃなく、なんか作らなきゃー。
http://www.usupi.org/kuri/ (まぐまぐ ID:126454)
http://usupi.seesaa.net/ (栗日記ブログ)


[バックナンバーのトップへ] [Linux システム管理のトップへ]

トップ

バックナンバー
    [日付順] [目的別]

プロフィール

▼ リンク

独学Linux
Linuxデスクトップ環境に関する情報が満載です。 メルマガもありますよ。
Server World
CentOS 6をサーバとしたときの設定例が、これでもかというくらいたくさん載っています。 CentOS以外のディストリビューション(Fedora, Ubuntu)も充実しています。
LINUXで自宅サーバーを構築・導入(Fedora9)
Fedora9のインストールの仕方から管理方法まで、詳しく載っています。 SearchManには情報がもりだくさんです。
マロンくん.NET
〜サーバ管理者への道〜
Linuxをサーバとして使用するための、いろいろな設定方法が載っています。 マロンくんもかわいいです。 なんといっても、マロンくんという名前がいいですね!!
日経Linux
今や数少なくなってしまったLinuxの雑誌。ニュースやガイドもあります。
Linux Square − @IT
@ITが提供する、Linux の情報が満載。 載っていない設定方法はないんじゃないでしょうか。
gihyo.jp…技術評論社
Linuxに限らず様々な技術情報が満載のサイト。 SoftwareDesign誌も、 ソフトウェア技術者は必見です。
SourceForge.JP Magazine
Linux に限らず、オープンソース関連の記事が網羅されています。
ITmediaエンタープライズ:Linux Tips 一覧
Tips というより FAQ 集でしょうか。わからないことがあれば覗きましょう。
IBM developerWorks : Linux
開発者向けですが、勉強になりますよ。
Yahoo!ニュース - Linux
Yahoo!のLinuxに関するニュース一覧です。
栗日記
システム管理とかと全然関係ありませんが、毎日栗の絵を描いています。
システム管理につかれちゃったとき、癒されたいときに、ご覧ください。:-)
WEB RANKING - PC関連
ランキングに参加してみました。押してやってください。

▼ 作ってみました

Add to Google

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本