このメールは, announce-jp に流れた Subject: ANNOUNCE: FreeBSD Security Advisory: FreeBSD-SA-00:53.catopen From: FreeBSD Security Advisories Date: Wed, 27 Sep 2000 17:48:35 -0700 (PDT) Message-Id: <20000928004835.B030B37B424@hub.freebsd.org> X-Sequence: announce-jp 553 を日本語訳したものです. この勧告の中で紹介されている WWW サイト http://www.FreeBSD.org/ および FTP サイト ftp://ftp.FreeBSD.org/ には, 日本のミラーサイトが存在します. ミラーサイトを利用するには, http://www.FreeBSD.org/ を http://www.jp.FreeBSD.org/www.freebsd.org/ に, ftp://ftp.FreeBSD.org/ を ftp://ftp.jp.FreeBSD.org/ に, それぞれ置き換えてください. ネットワークの混雑を緩和するため, まずはミラーサイトの利用を 考慮するようお願いします. ミラーサイトに関する詳細は http://www.FreeBSD.org/handbook/mirror.html (英文) http://www.FreeBSD.org/ja/handbook/mirror.html (日本語訳) に, また, 過去の日本語版セキュリティ勧告は http://www.FreeBSD.org/ja/security/ にまとめられています. 原文は PGP 署名されていますが, この日本語訳は PGP 署名されていません. パッチ等の内容が改竄されていないことを確認するために PGP のチェックを 行なうには, 原文を参照してください. 日本語訳は FreeBSD 日本語ドキュメンテーションプロジェクト (doc-jp) が参考の ために提供するもので, doc-jp は その内容についていかなる保証もいたしません. 日本語訳についてのお問い合わせは doc-jp@jp.FreeBSD.org までお願いします. --(ここから) ============================================================================= FreeBSD-SA-00:53 Security Advisory FreeBSD, Inc. トピック: catopen() may pose security risk for third party code 分類: core モジュール: libc 告知日: 2000-09-27 影響範囲: 修正日前の FreeBSD 5.0-CURRENT, 4.x および 3.x 修正日: 問題 1: 2000-08-06 (FreeBSD 5.0-CURRENT) 2000-08-22 (FreeBSD 4.1-STABLE) 2000-09-07 (FreeBSD 3.5-STABLE) 問題 2: 2000-09-08 (FreeBSD 5.0-CURRENT, 4.1-STABLE および 3.5-STABLE) クレジット: 問題 1: 内部セキュリティ監査中に発見 問題 2: Ivan Arce FreeBSD に固有か: NO I. 背景 - Background catopen() および setlocale() は, たとえば非英語圏のユーザ向けに 地域化された書式 (localized format) でテキストを表示する際に 使われる関数です. II. 問題の詳細 - Problem Description このセキュリティ勧告で述べる問題は 2 つあります. 1) catopen() 関数は内部バッファの境界チェックを正しく行なって いなかったため, ある環境変数に特殊な設定をすることで, 間接的にバッファオーバフローを引き起こせる可能性があります. そのため, catopen() を使用していて高い権限で動作している アプリケーションは, 権限を持たないローカルユーザによって 任意のコードを実行するのに利用される危険性があります. 2) catopen() と setlocale() 関数は, 地域化されたデータや メッセージカタログを読み込む際, システムファイルの代わりに 任意のファイルを使うことができます. 攻撃者は 特殊な書式指定文字列を含む有効なロケールファイルや メッセージカタログファイルを作成し, そのファイルを使って セキュリティ上の弱点を含む高い権限を持ったアプリケーションを悪用し, 高いユーザ権限で任意のコードを実行できる可能性があります. 2 番目の弱点は Core-SDI の Ivan Arce が元々発見した問題とは 若干異なるものです. 彼によって発見された問題は 複数の UNIX オペレーティングシステムが影響を受けるもので, 異なる環境変数に関係します. FreeBSD はその問題の影響を 受けないのですが, Core-SDI セキュリティ勧告の発行後, 上記問題 2 が FreeBSD に発見されました. これは弱点を持つアプリケーションに 対して同じ影響を与えるものです. FreeBSD ベースシステムには, この両方の問題によるセキュリティ上の弱点は 存在しないと考えられています. また, この弱点を含む サードパーティ製のプログラム (FreeBSD Ports Collection を含む) も 現時点で発見されていない, ということに注意してください. そのため, 大部分の FreeBSD システムには, この弱点による 影響はないと思われます. III. 影響範囲 - Impact setuid/setgid された (FreeBSD ports/packages を含む) サードパーティ製ソフトウェアには, ローカルから高い権限のアクセスを 奪うために悪用できるセキュリティ上の弱点が存在する可能性があります. ただし, そのようなソフトウェアは現時点で見つかっていません. FreeBSD ベースシステムには, これらのバグによるセキュリティ上の弱点を 持つプログラムは存在しないと考えられています. この問題は, FreeBSD 4.1.1 の公開前に修正されました. IV. 回避方法 - Workaround 上記問題 1 は, 弱点を悪用するのにコーディング上の欠陥を必要と しないため, 問題 2 よりも深刻です. (静的リンクおよび動的リンクされた) catopen() 関数を使っていて 高い権限を持ち, 再構築や潜在的な危険を最小化するために権限を制限する 必要のあるバイナリを発見, 検査するユーティリティが提供されています. 2 番目の問題の影響を受けるバイナリを検出することは不可能ですが, 提供されているユーティリティは, 潜在的にセキュリティ上の 弱点と「なり得る」, 静的リンクされた setlocale() 関数を 使っているバイナリも報告します. 報告されるバイナリのほとんどは 実際にセキュリティ上の弱点を持っていないと思われますが, 万全のセキュリティを期すためには, それらすべてを再コンパイルすべきでしょう. FreeBSD システムに含まれるバイナリもまた, このスクリプトによって 弱点を持つ可能性があると報告されるかも知れませんが, それは セキュリティ上の問題となるものではありませんのでご注意ください. 静的リンクされたバイナリで, セキュリティ上の弱点を持っているか, もしくは潜在的なセキュリティ上の弱点を持つ可能性があると報告されたものは, 可能ならばこの弱点を修正するために libc を再コンパイルして, 修正パッチを適用した後のソースコードから再コンパイルすべきです. 動的にリンクされたバイナリは, 下に述べるように修正パッチを適用して libc を再コンパイルするだけで修正されます. 暫定的な措置として, 報告されたすべての setuid もしくは setgid バイナリを 削除するか, setuid/setgid されているファイルから高い権限を取り除くか, あるいはファイルの許可属性を適宜制限することを考慮してください. もちろん, 報告されたファイルのいくつかはローカルシステムの正常な運用に 必要なものであるかも知れません. その場合は適切なユーザグループを設定して そのバイナリから "o+x" のファイル許可属性ビットを取り除き, そのバイナリを 実行可能なユーザを制限すること以外に明確な問題回避方法はありません. 1) 次の場所から 'scan_locale.sh' および 'test_locale.sh' スクリプトを ダウンロードします. ftp://ftp.freebsd.org/pub/FreeBSD/CERT/tools/SA-00:53/scan_locale.sh ftp://ftp.freebsd.org/pub/FreeBSD/CERT/tools/SA-00:53/test_locale.sh 以下は fetch(1) コマンド使った例です. # fetch ftp://ftp.freebsd.org/pub/FreeBSD/CERT/tools/SA-00:53/scan_locale.sh Receiving scan_locale.sh (337 bytes): 100% 337 bytes transferred in 0.0 seconds (1.05 MBps) # fetch ftp://ftp.freebsd.org/pub/FreeBSD/CERT/tools/SA-00:53/test_locale.sh Receiving test_locale.sh (889 bytes): 100% 889 bytes transferred in 0.0 seconds (1.34 MBps) 2) md5 チェックサムを検査し, 下の値と比較します. # /sbin/md5 scan_locale.sh MD5 (scan_locale.sh) = efea80f74b05e7ddbc0261ef5211e453 # /sbin/md5 test_locale.sh MD5 (test_locale.sh) = 2a485bf8171cc984dbc58b4d545668b4 3) システムに対して scan_locale.sh を実行します. # sh scan_locale.sh ./test_locale.sh / このスクリプトはシステム全体を検査し, 悪用される危険性のある catopen() 関数, もしくは潜在的なセキュリティ上の弱点となり得る setlocale() 関数を使っていて, setuid もしくは setgid されているバイナリを 探します. たとえばそのバイナリを, セキュリティ上の弱点を悪用できる ローカルユーザの誰かが高いユーザ権限を得る目的で実行できるかどうかなど, ローカル環境がどのようなセキュリティ上の危険に晒されるのかについて, スクリプトが報告するバイナリ一つ一つについて (たとえば 'ls- l' や その他のツールで) 確認すべきでしょう. このスクリプトで検出できる setlocale() 関数を利用した (つまり 問題 2 と関係する) バイナリは, 静的にリンクされたバイナリのみです. 動的にリンクされたバイナリは高い確率で信頼性のおけない結果となるため 報告されません. setlocale() を利用していると報告されたバイナリの 大部分は, 実際にセキュリティ上の弱点が存在しない可能性があります. したがって, このスクリプトで報告されたからといって, それは セキュリティ上の弱点が存在する証拠にはなりません. しかし, 万全の セキュリティを期すためには, それらすべてを再コンパイルすべきでしょう. 4) 該当するバイナリを削除するか, ファイルの許可属性を適切に制限します. V. 解決策 - Solution セキュリティ上の弱点を持つ FreeBSD システムを, 修正日以降の 4.1-STABLE もしくは 3.5-STABLE にアップグレードするか, 現行のシステムのソースコードに修正パッチを適用して再構築してください. その後, セクション IV に書かれているように scan_locale.sh スクリプトを 実行し, このスクリプトが報告する, 静的リンクされたすべてのバイナリを 確認します. これらのファイルは削除するか, 再コンパイルするか, あるいはこのセキュリティ上の問題に対する安全性を高めるために 権限を制限すべきです (静的リンクされたバイナリには, 単に libc 共有ライブラリを再コンパイルしただけでは修正の効果がないためです). 現行のシステムに修正パッチを適用するには, 以下の修正パッチを ファイルに保存して, root 権限で次のコマンドを実行します. cd /usr/src/lib/libc patch < /path/to/patch/file make all make install 修正日以前の FreeBSD に対する修正パッチ: Index: msgcat.c =================================================================== RCS file: /usr2/ncvs//src/lib/libc/nls/msgcat.c,v retrieving revision 1.21 retrieving revision 1.27 diff -u -r1.21 -r1.27 --- nls/msgcat.c 2000/01/27 23:06:33 1.21 +++ nls/msgcat.c 2000/09/01 11:56:31 1.27 @@ -91,8 +91,9 @@ __const char *catpath = NULL; char *nlspath; char *lang; - long len; char *base, *cptr, *pathP; + int spcleft; + long len; struct stat sbuf; if (!name || !*name) { @@ -106,10 +107,10 @@ } else { if (type == NL_CAT_LOCALE) lang = setlocale(LC_MESSAGES, NULL); - else { - if ((lang = (char *) getenv("LANG")) == NULL) - lang = "C"; - } + else + lang = getenv("LANG"); + if (lang == NULL || strchr(lang, '/') != NULL) + lang = "C"; if ((nlspath = (char *) getenv("NLSPATH")) == NULL #ifndef __NETBSD_SYSCALLS || issetugid() @@ -129,13 +130,22 @@ *cptr = '\0'; for (pathP = path; *nlspath; ++nlspath) { if (*nlspath == '%') { + spcleft = sizeof(path) - (pathP - path); if (*(nlspath + 1) == 'L') { ++nlspath; - strcpy(pathP, lang); + if (strlcpy(pathP, lang, spcleft) >= spcleft) { + free(base); + errno = ENAMETOOLONG; + return(NLERR); + } pathP += strlen(lang); } else if (*(nlspath + 1) == 'N') { ++nlspath; - strcpy(pathP, name); + if (strlcpy(pathP, name, spcleft) >= spcleft) { + free(base); + errno = ENAMETOOLONG; + return(NLERR); + } pathP += strlen(name); } else *(pathP++) = *nlspath; } else *(pathP++) = *nlspath; @@ -186,7 +196,7 @@ MCSetT *set; long lo, hi, cur, dir; - if (!cat || setId <= 0) return(NULL); + if (cat == NULL || setId <= 0) return(NULL); lo = 0; if (setId - 1 < cat->numSets) { @@ -212,8 +222,8 @@ if (hi - lo == 1) cur += dir; else cur += ((hi - lo) / 2) * dir; } - if (set->invalid) - (void) loadSet(cat, set); + if (set->invalid && loadSet(cat, set) <= 0) + return(NULL); return(set); } @@ -225,7 +235,7 @@ MCMsgT *msg; long lo, hi, cur, dir; - if (!set || set->invalid || msgId <= 0) return(NULL); + if (set == NULL || set->invalid || msgId <= 0) return(NULL); lo = 0; if (msgId - 1 < set->numMsgs) { @@ -318,7 +328,7 @@ off_t nextSet; cat = (MCCatT *) malloc(sizeof(MCCatT)); - if (!cat) return(NLERR); + if (cat == NULL) return(NLERR); cat->loadType = MCLoadBySet; if ((cat->fd = _open(catpath, O_RDONLY)) < 0) { @@ -351,7 +361,7 @@ cat->numSets = header.numSets; cat->sets = (MCSetT *) malloc(sizeof(MCSetT) * header.numSets); - if (!cat->sets) NOSPACE(); + if (cat->sets == NULL) NOSPACE(); nextSet = header.firstSet; for (i = 0; i < cat->numSets; ++i) { Index: setlocale.c =================================================================== RCS file: /home/ncvs/src/lib/libc/locale/setlocale.c,v retrieving revision 1.27 retrieving revision 1.28 diff -u -r1.27 -r1.28 --- locale/setlocale.c 2000/09/04 03:43:24 1.27 +++ locale/setlocale.c 2000/09/08 07:29:48 1.28 @@ -129,7 +129,7 @@ if (!env || !*env) env = getenv("LANG"); - if (!env || !*env) + if (!env || !*env || strchr(env, '/')) env = "C"; (void) strncpy(new_categories[category], env, ENCODING_LEN); $hrs: announce-jp/FreeBSD-SA/00:53,v 1.3 2000/10/11 15:33:30 hrs Exp $