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

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


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

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

Ubuntu 10.04 LTS(Long Term Support) がリリースされましたね。

現在フル回転しているノートが 9.10 ですので、早速、 以下に書いてある通りにアップデートしてみました。

Ubuntu 10.04 LTSへアップデートを行うには - Ubuntu Japanese Wiki
https://wiki.ubuntulinux.jp/UbuntuTips/Install/UpgradeLucid

基本的には、アップデートマネージャを起動して、 アップデート(既存の9.10 を最新に)してから(10.04 に) アップグレードするだけでした。
あ、あと、Japanese Team のリポジトリを有効にする作業もあります。
(下の方に書いてあるので、うっかり忘れてしまうところでした。)

いずれにしましても、インストールDVDなどで立ち上げて云々する必要がなく、 いつもと変わりなく使用しながらアップデートできるというのは、 非常にありがたいと思います。

ただひとつ問題があるとすれば、その仕組みを理解せずに使っている自分でしょうか。 技術者の端くれとして、ちゃんと調べておこうと思います。

表面的に反省したところで、今回も、はりきってまいりましょう。

今回のお題 - セキュリティを考慮してシェルスクリプトを書く

システム管理を行っていますと、様々なスクリプトを作成する機会があると思います。

宿題の答えのように、cron で定期的に走らせる処理を記述することは、 わりと頻繁にありますよね。また、誰が行っても問題ないように、 一連の処理を行うコマンドとして記述することもあると思います。

それらは、わざわざ手間をかけて作成するのですから、当然、 それなりの頻度で使用されるはずです。

しかし、その割には、セキュリティを深く考慮して作成していないのではないか、 という気がいたします。

わたしも、当メルマガでほぼ毎回、 こうやればできますよ的スクリプトを紹介してきました。
しかしながら、紙面(?)の都合上、肝以外のところを省略したり、 あまり深く考えずにささっと書いてしまったりしていたように思います。

みなさまに見ていただくものであるにもかかわらず、 安直に書いたものを気軽に紹介してしまっていたなあと、 表面だけでなく反省しております。

PATH に注意する

まず気をつけるべきなのは、環境変数 PATH ではないでしょうか。

シェルスクリプトを作成する際には、スクリプトの中から、 99.99%くらいの確率で外部コマンドを呼び出しているのではないかと思います。

で、たとえば以下のように、chmod コマンドを呼び出す行が、 スクリプト内にあったとします。

  chmod 644 $file

これを実行しますと、環境変数 PATH のディレクトリを順番に探索して、 最初に見つかった、同名の実行可能なファイルを実行します。
実際、どれが呼ばれるか確認するには、 以下のように which コマンドを実行してみればわかります。

  $ echo $PATH
  /usr/local/bin:/sbin:/usr/sbin:/usr/bin:/bin:/usr/X11R6/bin:\
  /usr/local/sbin:/opt/jdk1.6.0_04/bin:/home/usu/bin
  $ which chmod
  /bin/chmod

上記の場合、/bin にある chmod が実行されます。

しかし、あるディレクトリが PATH の先頭に追加され、 そのディレクトリに chmod という名前のコマンドがありますと、 /bin にある chmod ではなく、その chmod が実行されてしまうことになります。

たとえば、カレントディレクトリに、chmod という名の、 実体が /bin/sh であるシンボリックリンクを作成します。

  $ ln -s /bin/sh chmod

そして、PATH の先頭にカレントディレクトリを加えて chmod を実行してみましょう。

  $ PATH=".:$PATH" chmod 644 foo
  chmod: Can't open 644

すると、実体が /bin/sh の方の chmod が実行されてしまいます。
ここで、カレントディレクトリに 644 というファイルを作成しますと、 それがシェルスクリプトとして実行されます。

  $ echo echo too bad! > 644
  $ cat 644
  echo too bad!
  $ PATH=".:$PATH" chmod 644 foo
  too bad!

おっと、上記は bash など sh 系の場合の実行例です。
tcsh などの場合では、setenv で設定してから実行する必要があります。

  (644 というファイルが作ってあるという前提で)
  $ setenv PATH ".:$PATH"
  $ chmod 644 foo
  too bad!

紙面の都合上、以降では bash の場合の実行例のみ示します。
tcsh 好きな貴兄は、脳内で変換してご覧いただけますと幸いです。

さて、このような意図しない動作を防ぐには、コマンドをすべて絶対パスで指定するか、 スクリプトの最初に PATH を設定する必要があります。
前者の場合は、以下のように絶対パスで chmod を指定します。

  /bin/chmod 644 $file

前者の方がカタいと思いますが、 そのスクリプトを別の環境で実行させる可能性がある場合、 パスが異なる(たとえば chmod が /usr/bin にある)と動作しなくなるおそれがあります。

ですので、ある程度の汎用さが求められるときは、後者がよいのではないかと思います。 たとえば、下記のように、冒頭で最小限的な PATH を設定してしまいますと、安心です。

  #!/bin/sh
  PATH=/sbin:/usr/sbin:/bin:/usr/bin
  export PATH
  ...中略...
  chmod 644 $file
  ...後略...

環境変数をむやみに信じない

次は、環境変数です。
まあ、PATH も環境変数ですが、PATH の破壊力(?)は強烈ですし、 超有名ですので、別格で扱わせていただきました。

それはさておき、環境変数というと、常に正しい値が格納されている、 と思いがちではないでしょうか。

ですが、環境変数は自由に変更できます。
ですので、環境変数の値をそのまま使用するのではなく、 常に疑う必要があると思います。

たとえば、とある処理を root だけが実行できるようにしたいとします。
その場合、スクリプトの中で、以下のように、環境変数 USER で確認していたとします。

  if [ "$USER" = "root" ]; then
      echo "You are the savior!"
      ...rootだけが許される処理...
  else
      echo "You are not the savior..."
  fi

普通に使用している場合は、スクリプトを実行するユーザ名が、 環境変数 USER に格納されていますので、問題ありません。
ですが、環境変数は自由に書き換えられますので、root だよと偽ることは簡単です。

  $ USER=root ./root_only.sh
  You are the savior!
  ...rootだけが許される処理の出力結果...

普通は、下記のように id コマンドで確認する方法が一般的だと思いますので、 上記は不自然ではありますが…。
(あくまでも例ということで、ご容赦くださいませ。)

  if [ "`id -u`" = "0" ]; then
      echo "You are the savior!"
      ...処理...
  else
      echo "You are not the savior..."
  fi

他にも、$HOME をそのまま使用してファイルの入出力を行ったり、 $PAGER の内容を確認せずに実行してしまったりなど、 ついうっかり信じてしまうことがあるように思います。

ですので、環境変数を使用する際は、その値が正しくない(かもしれない)という前提で、 必ずチェックするようにしましょう。

シンボリックリンクに気をつける

そして次は、シンボリックリンクです。

シンボリックリンクはとても便利な代物ですが、その便利さゆえに、 問題を起こすことが多いように思います。

たとえば、cron が root の権限で実行するスクリプトがあり、 その中で /var/log/foo/bar.log というファイルにログを出力する機能がある、 としましょう。(…ええ、するのだと思い込んでください。)

  mv -f /var/log/foo/bar.log /var/log/foo/bar.log.0
  echo "`date` : $command_result" > /var/log/foo/bar.log

上記では、/var/log/foo/bar.log を bar.log.0 に改名して残しておき、 あらためて /var/log/foo/bar.log に出力しています。

ここで、/var/log/foo のパーミッションが緩く、 一般ユーザがファイルを作成できてしまうとしましょう。
そして、bar.log を bar.log.0 に改名してから、 新たな bar.log を作成するまでの間の一瞬を突いて、下記を実行できたとしましょう。

  $ ln -s /etc/shadow /var/log/foo/bar.log

すると、bar.log の実体は /etc/shadow ですので、 スクリプトは shadow ファイルにログを出力してしまうことになります。

そんな一瞬の隙を狙ってシンボリックリンクが作成できるのかよ、 と思うかもしれません。ですが、 システムを故意に重くしてスクリプトの実行を遅らせておき、 ただひたすらにシンボリックリンクを作成しまくるようにしておけば、 その一瞬の隙をうまく突くことができるかもしれません。

また、そもそも、一般ユーザがシンボリックリンクを作成できる、 という状況がないのではないか、とお思いかもしれません。
ですが、たとえば /tmp は、誰でもファイルを作成することができます。 そして、テンポラリファイルはたいてい /tmp に作成されますので、 そのような状況に陥る可能性は、けっして低くはないように思います。

ですので、決まったパスのファイルに入出力を行う際は、 ディレクトリのパーミッションに注意し、さらに石橋を叩くなら、 シンボリックリンクでないことを確認する必要があると思います。
後者に関しては、以下のようにすればよいでしょうか。

  mv -f /var/log/foo/bar.log /var/log/foo/bar.log.0
  touch /var/log/foo/bar.log
  if [ -L /var/log/foo/bar.log ]; then
      echo "/var/log/foo/bar.log: symbolic link!"
      exit 1
  fi
  echo "`date` : $command_result" > /var/log/foo/bar.log

touch コマンドで bar.log を作成しておき、 それがシンボリックリンクでないことを確認しています。 もしシンボリックリンクだと、 touch した時点でファイルの時刻が更新されてしまいますが、 その辺りは大目に見ていただけますでしょうか。
(そもそも、syslog を使えばよいのでは、という気もいたしますが…。 それ以外にまだ隙がありましたら、ご指摘いただけますと幸いです。)

おわりに

以上、シェルスクリプトを記述する際に、セキュリティ上気をつけるべきことを、 紹介させていただきました。

すみません、本当は、テンポラリファイルについて書こうと思っていたのですが、 存分に長くなってしまいましたので、今回は断念しました。

ですので、次回に、続きを紹介させていただこうと思います。
すみませんが、ご容赦いただけますと幸いでございます。

宿題の答え

前回の宿題は、

  sysstat が収集したその日の情報から、グラフを自動生成しましょう。

でした。

次の日の始めに実行されると仮定して、スクリプトを書いてみました。

#!/bin/sh
LANG=C
export LANG
[ -d /var/log/sa ] \
    && SADIR=/var/log/sa || SADIR=/var/log/sysstat
YDAY=`date --date=yesterday +%d`
INFILE=${SADIR}/sa${YDAY}
OUTFILE=${INFILE}_u.png
TMPFILE=`mktemp /tmp/sysstat-graph-XXXXXX`
trap 'rm -f $TMPFILE' 0 1 2 3 9 11 15
sar -u -f "$INFILE" | grep '^[0-9]' | grep -v idle > "$TMPFILE"
gnuplot << E-O-F
set terminal png
set output "$OUTFILE"
set xdata time
set timefmt "%H:%M:%S"
set format x "%H:%M"
plot "$TMPFILE" using 1:3 title "user" with linespoints, \
     "$TMPFILE" using 1:5 title "system" with linespoints, \
     "$TMPFILE" using 1:6 title "iowait" with linespoints
E-O-F

基本的には、前回の宿題のスクリプトと同様です。
前回は、入出力ファイルを引数から得ていました。ですが、今回は、 以下のように固定になります。

入力ファイル
/var/log/sa/sa昨日
(もしくは /var/log/sysstat/sa昨日)
出力ファイル
/var/log/sa/sa昨日_u.png
(もしくは /var/log/sysstat/sa昨日_u.png)

また、出力されるPNGファイルは、CPUの使用状況のうち、 %user, %system および %iowait をグラフで表したものになります。

このスクリプトを、 たとえば /usr/local/sbin/sar2png_u_yesterday.sh に保存したとしますと、 いつものように実行可能にしておきます。

  # chmod +x /usr/local/sbin/sar2png_u_yesterday.sh

これを、試しにコマンドラインで実行すると、 前日のログを元にグラフを作成してくれる…はずです。
たとえば今日が17日だったとすると、以下のように、16日のグラフが作成されます。 (前後の ls コマンドの実行は、ただの確認です。)

  # ls -l /var/log/sa/sa16_u.png
  ls: cannot access /var/log/sa/sa16_u.png: No such file or directory
  # /usr/local/sbin/sar2png_u_yesterday.sh
  # ls -l /var/log/sa/sa16_u.png
  -rw-r--r-- 1 root root 7777 May 17 00:59 /var/log/sa/sa16_u.png

問題ないようであれば、あとは cron に登録するだけです。
たとえば、以下の内容のファイルを、 /etc/cron.d/sysstat_graph などという名前で保存してしまいましょう。

  30 0 * * * root /usr/local/sbin/sar2png_u_yesterday.sh > /dev/null

そうしますと、毎日夜中の12時半に、グラフを作ってくださいます。
あとは、WWW 経由で見られるようにするなど、 セキュリティに考慮しつつさらに仕込んでみてくださいませ。

 

はい、もちろん、方法を書いただけでは無責任ですので、 わたくしも各所のマシンに仕込んでみました。いまのところ問題ないようです。

で、わたくしのノートにも仕込んでありますが、 フタを閉じてサスペンドしている最中は記録されませんので、 いつ電源が入っていたのか、グラフから一目瞭然となっています。 ちょっと興味深いなと思いました。

今回の宿題

今回の宿題は、

  隙のあるスクリプトを作成して、一瞬の隙を突いてみましょう。

です。

本題のシンボリックリンクのところで、一瞬の隙を狙えば可能、 的なことを書きました。

やはり、「実践!」と言っている以上、実際に確認して経験することで、 脳ミソに刻み込む必要があるのではないかと思います。
ですので、実際に試してみたいと思います。
(もちろん、shadow ファイルは破壊しません。(しないでください…。))

あとがき

そうそう、肝心の Ubuntu 10.04 の使用感について書いてませんでした。

売りと思われる高速起動に関しては、わたしの環境では、 特に速いと感じられませんでした。(計測していませんので思い込みかもしれません。)

ですが、Firefox などのアプリの起動が、やけに速く感じられます。
アップデートにより余計なものが淘汰されただけなのかもしれませんが、 年々重くなりがちなこの世の中で、逆に軽くなるというのは、 ありがたいことなのではないかという気がしております。

 

また、Google 日本語入力の Linux(Ubuntu)版が公開されていますので、 そちらも試してみました。

mozc
http://code.google.com/p/mozc/

その名も、「Mozc(もずく)」…。(よいネーミングなのでしょうか…?)
…はさておき、以下の手順の通りに行いますと、Ubuntu のパッケージがもれなくできます。

Linux Build Instructions - mozc
http://code.google.com/p/mozc/wiki/LinuxBuildInstructions

数日前から使ってみていますが、今のところ問題は発生していません。
体感速度もまったく問題ない感じです。
(Windows 版では、候補一覧のウィンドウが消えない現象や、 入力途中で勝手に選択されたりといった現象が、ときどきありました。)

基本の Anthy ですと、おかしな変換をすることがたまにありましたが、 Mozc さんではその頻度が少ないように思います。
今はまだなにも設定できないのですが、個人的には設定する必要を感じていませんので、 このまま恩恵にあずかっておこうと思います。

 

あ、あと、某日経Linux の連載ですが、予想に反して(?)続いています。
毎月の原稿にはアタフタしていますが、 編集の方からごめんなさいとか言われていませんので、 しばらくは続けていただけそうな気配です。
(ちなみに、Xに関する初心者向けの連載です。 Xなら余裕だと思っていた自分が浅はかでした。 毎回わからないことだらけで調べまくりです。)

ただ、読者の方々の反応が、今のところさっぱりわかりません。
もし 日経Linux を購読されている貴兄がいらっしゃいましたら、 お気軽にご意見等をメールしていただけますと、感謝感激です。

あ、もちろん、当メルマガに関するご意見ご感想ご質問叱咤激励なども、 お気軽にお送りくださいませ。
(こちらも感謝感激します。普段、驚くほどメールが来ませんので…。)

 

今回も、ここまで読んでいただき、誠にありがとうございました。
次回は、6月6日(日) の未明にお会いしましょう!

 

「いますぐ実践! 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/ (栗日記ブログ)
http://usupi.org/k/ (モバイル栗日記)


[バックナンバーのトップへ] [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

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本