ラベル Security の投稿を表示しています。 すべての投稿を表示
ラベル Security の投稿を表示しています。 すべての投稿を表示

2012年2月10日

Sudo format string vulnerability

前置き

Sudo format string vulnerability ( CVE-2012-0809 )  というバグが、sudo コマンドには存在する。CVEが出ていることからも判るように、結構深刻なバグで、セキュリティ・ホールとしての性質を伴う。sudoのページによれば
運が良くても sudo はクラッシュし、
運が悪いと攻撃者に root 権限を掌握される問題が含まれているかもしれない
との事だ。

で、このバグ、何がどうなっているのかについては、『てきとうなメモ: [Linux][Security] sudo-1.8のバグ』が詳しい。とても詳しいので、そちらだけ見ておけばいいやと思っていたのだが、何箇所かから、
お前も書け
という圧力を食らったので、書くことにする。ただし、新しい情報がなにかあるって言うわけじゃない。

影響範囲

このバグは sudo の 1.8.0 で導入され 1.8.3-p2 で修正されました。なので、影響は 1.8.0 - 1.8.3-p1 と言うことになります。

で、商用 Linux distribution の中で、影響があるのはなさそうです。
Free distribution の中も含めると、Fedora16, OpenSuSE 12.1, Rawhide の3つが影響を受けているようです。
(http://rpm.pbone.net/index.php3 でどのdistributionがどのrpmを使っているのか、分かります)

ただし、それ以外のOSでも sudo は使っているはずです。それらが安全かどうかは判りません。一応、sudo のページには対応している各種OS用の置き換えバイナリは用意されているようです。

という訳で、ほぼ影響はない、と言うことなので、以下は笑い話として。他人の失敗は蜜の味 (^w^)。

攻撃方法

攻撃方法は次のとおりです。
  1.  ln -s /sbin/sudo /tmp/%s
    のようにして、sudu コマンドを「%s」というファイル名にすり替える
  2. /tmp/%s を実行する

%s は printf() 系処理が format 文として利用しているものであれば、大抵のもので問題が生じるようです。どれでどのような症状が出るのかは、CPUなどにある程度依存します。


こうすると、argv[0] 文字列の中に %s という文字列が含まれるようになります。


技術的概略

このバグは、すごく簡単に言うと printf() 系関数を2段階かけた事に起因したバグです。printf() 系関数を多段に使うことは、セキュリティを考慮したコーディングとしては非常にまずいもので、
絶対やるな
と言っても構わないぐらい、危険な行為です。

修正後も2度使っていますが、まぁ、これならしょうがないかな、という所にまで治っています。

実はもう一つ、例外処理が足りていない、と言う問題もあります。sudoだから発生する確率はあまり高くありませんが…仮想メモリシステムを使い切った状態だと危険ですね。

詳細

sudo-1.8.3-p1 の ./src/sudo.c の最後に次のような関数があります。デバッグログを出力するためのコードですが、ここに悪さの元が含まれています:

void
sudo_debug(int level, const char *fmt, ...)
{
    va_list ap;
    char *fmt2;

    if (level > debug_level)
 return;

    /* Backet fmt with program name and a newline to make it a single write */
    easprintf(&fmt2, "%s: %s\n", getprogname(), fmt);
    va_start(ap, fmt);
    vfprintf(stderr, fmt2, ap);
    va_end(ap);
    efree(fmt2);
}

通常、argv[0] は "sudo" という文字列へのポインタです。で、getprogname() は argv[0]を返すようになっています。
そこで、
     fmt = "%s"
   fmtの次の引数 = "hello"
のような場合について考えてみましょう。


    easprintf(&fmt2, "%s: %s\n", getprogname(), fmt);


この行を通った段階で fmt2 は


    fmt2 = "sudo: %s\n";



になります。で、その後:


    vfprintf(stderr, fmt2, ap);


という行を通ると、stderr には


    "sudo: hello\n";


という文字列が送りつけられることになります。
何も問題はありませんよね??

では、攻撃方法にあるように sudo コマンドに対してリンクを貼って './%s' という名前で起動したらどうなるでしょう?

argv[0] = "./%s"

になります。



    easprintf(&fmt2, "%s: %s\n", getprogname(), fmt);


この行を通った段階で fmt2 は


    fmt2 = "./%s: %s\n";



になります。で、その後:


    vfprintf(stderr, fmt2, ap);


という行を通ると、stderr にはまず、第1引数である "hello" が出るので:


    "./hello: 



…おや、困りました。後半の %s のための文字列へのポインタが引数として渡されていません。しかも vfprintf() はそんな事を知りません。しょうがないので、stack 上にある値をポインタと解釈してしまいます。

運がよいと、「Segmentation Violation」が発生します。で sudo はクラッシュします。あぁ、core を吐かないように設定しているといいんですが…。運が悪いと、coreファイルを持っていかれますが、そこには /etc/shadow の値が書いてあるかもしれません。
まぁ、意図的にやっている奴らは
確実に core 取得できるように
設定してから実行するよね。
はっはっはっ

まぁ、運良く大した情報が保存されていない core ファイルが出来上がることを祈るしかありませんな。


ちなみに。"%s" は上記のとおりですが、"%n" という楽しい引数がございましてな…これ、引数で渡したアドレスにそこまで書いた文字数を「書きこむ」んですわ… はっはっは …

判ったと思いますが、万が一これらのバージョンを使っていたら
血の涙を流してでも upgrade しろ!!

対策

1.8.3-p2 はこう変更されました。
void
sudo_debug(int level, const char *fmt, ...)
{
    va_list ap;
    char *buf;

    if (level > debug_level)
 return;

    /* Bracket fmt with program name and a newline to make it a single write */
    va_start(ap, fmt);
    evasprintf(&buf, fmt, ap);
    va_end(ap);
    fprintf(stderr, "%s: %s\n", getprogname(), buf);
    efree(buf);
}

えぇ、見ての通り printf は相変わらず2度使われています。

ただ、1度目は与えられたフォーマットと引数から、とりあえず buf という文字列を作るために、2度目はargv[0] と buf を fprintf() で出力するために使われます。

fmt は sudo のプログラム内で指定するフォーマット文ですし、fprintf() で使われるフォーマット文もプログラム内で指定するフォーマット文ですので、取り敢えず引数に %s などの危険な記号が含まれていても安全、とは言えるでしょう。


ただね。このコード、 buf == NULL だった場合を考慮していないんですわ。一応、glibc の場合 NULL を渡されると "(null)" という文字列を出しますけどね、これは必須ではない。たとえばSolarisは core dump するそうです。

環境によっては fprintf() の例外処理の定義が甘い所につけ込んだコードになる危険性は残されています。

2009年7月22日

Linux kernel zero-day exploit

備忘録。

対象2.6.30, 2.6.30.1
真の原因null pointer check をしていないコード & gcc optimization
修正コード2.6.30.2
demohttp://www.youtube.com/watch?v=UdkpJ13e6Z0
解説しているページ
原因となっているパッチhttp://mirror.celinuxforum.org/gitstat/commit-detail.php?commit=33dccbb050bbe35b88ca8cf1228dcf3e4d4b3554


問題はこの部分。
@@ -461,7 +476,8 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
{
struct tun_file *tfile = file->private_data;
struct tun_struct *tun = __tun_get(tfile);
- unsigned int mask = POLLOUT | POLLWRNORM;
+ struct sock *sk = tun->sk;
+ unsigned int mask = 0;

if (!tun)
return POLLERR;


まず、前提として理解しておくべきことは、C言語においては NULL Pointer へのアクセスの結果は「未定義」だということ。なのでコード的には何が起こっても不思議はない。当然、「未定義」以降に実施されるコードも未定義になる。

次に理解するべきことは、「未定義とはいえ、大抵のgccを利用する環境では NULL ポインタへのアクセスは SIGSEGV などを発生させる」事。つまり NULL ポインタアクセスを行えば、その段階でプログラムは停止するので、そこを通過したコードが持っているポインタは NULL ではない、と仮定して構わない事。どうせ、NULL だったら未定義なんだから何しても構わないし。結果として出力されるコードは論理的には必要な条件をすべて満たす結果として安全サイドに倒れたコードにはならない

以上のことを念頭において、先ほどのパッチを見る。
+ struct sock *sk = tun->sk;

このコードは tun が NULL だった場合、ユーザープログラムであれば SIGSEGV を発生させる。しかし、 kernel の場合はそのような割込の類は発生しない(正確にはしなかった)。

gcc は、「tun->sk を通過できたコードは、tun が NULL ではない、という保証が得られた、と言うことだ。その後 tun は変更されていない」と考えつつ、次のコードを見る。
  if (!tun)
return POLLERR;

で、続けてこう考えるわけだ。
「ふむ。ここまで来た段階で、tun != NULL は真であり、それ以降変更されていない。ならば
if (!tun) は常に偽だ。」
結果として上記のコードは全部なくなる。

結果として全体はこうなる:
static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
{
struct tun_file *tfile = file->private_data;
struct tun_struct *tun = __tun_get(tfile);
struct sock *sk = tun->sk;
unsigned int mask = 0;

poll_wait(file, &tun->read_wait, wait);
 :

POLLERR を返すパスはなくなり、エラーチェックが消失する。


エラーチェックが無くなれば、今度はこっちの問題を使って NULL pointer 近くのページに予め mmap しておいたコードを実行できてしまう。なにしろ、ユーザー空間は全て kernel から参照、実行可能だから。



ちなみに、2.6.18 base のはずの RHEL5.4 beta にはこれらのバグが存在した(NULL pointer check 関係の最適化がバックポートされた)が、それぞれ修正されているそうだ。

2007年3月24日

日本情報処理開発協会 馬鹿丸出し

大日本印刷が個人情報を大量に流出したのに、Pマーク取り消しはないのだそうだ。

Nikkei Net の記事だが、どうやら 日本情報処理開発協会 は自らの存在意義を否定したようだ。
ちなみにその存在意義を否定した集団自体の発表はこれ

憶測では、大日本印刷が扱っている業務量が多いために、それらに影響が及ばぬよう…と言うことらしいが、
  • 情報が漏洩しないはずの所が漏洩している段階で被害はすでに甚大である
  • 情報漏洩されては困る情報を大量に扱っていると言うことは、ごく短期間に問題が再発しただけで、被害は爆発的に広がるリスクを持っている
これらを考えるならば、「扱っている業務量が多い」ならばますますのこと、Pマークの即時取り消しが必要であろう。

また、大日本印刷に業務委託している企業は即刻、取引を停止し、そのことを公開することで、自らの顧客に対して、自分たちのセキュリティに関する意識の高さを示すべきだろう。でなければ、それらの企業や自治体も、個人情報などの扱いに関して、著しく意識が低い事を露呈しているだけだ。

最後に。「うちは、もはや信頼のならない Pマーク取得に向けての努力はいたしません」というのは、立派な営業トークになると思う。

2007年3月19日

ドキドキの向こう側…

久々に出た Bruce Schenier の新作!! つーても、原書は2003年に出ているのだが。相変わらずセキュリティについて判りやすく書かせたら、この人の右に出る人はいない。しかし同時に、どんどんコンピュータセキュリティから離れていってしまう気がする。

まぁ、本書自体の感想は上記のリンクにある私の蔵書リストに任せるとして(そういうサボり方をするんだ…)、この本にはちょろっと言及しているのに、結局そこから先、深彫りしていない項目が1つあるので、それについて書こう。これを本の感想の所に書くと、本の感想なのか何なのか判らなくなるから。


テロなどに襲われる理由の一つに憎たらしいからと言うのがある。もちろん、人によって何が憎たらしいのかは変わるものなのだが、少なくともアメリカ人の唯我独尊振りは世界中に知れ渡り、一部のアメリカ人自身、
「おれはあの我侭なアメリカ人が大嫌いだ」
と主張するぐらいには、唯我独尊である事は認めてもらってもいいだろう、とは思う。この我侭振りと、直接会った場合の人に対する接し方の柔らかさは、まさに田舎者のそれ、そのものと言ってもよいだろう。目の前にあるものが重要で、その外にどれほど広い世界があるのか知らない、という意味で。

個人的にはその田舎者っプリは大好きだったりするのだが、まぁそうは言っても、その田舎者っぷりを全力で出したキリスト教徒が、ユダヤ教とイスラム教どちらを大切にするかと言われれば、そりゃ旧約聖書のお膝元、ユダヤ教なのであって。オリジンを翻訳しちゃいけないなどと言う制約までついているコーランに載っている話を「コーランに載っている話」として聞いたことのあるアメリカ人なんぞ十人に一人いれば多いほうなわけで…。

そんなアメリカ人とイギリス人が勝手にイスラエルなんて国を作ったらそりゃ頭にくるでしょう。しかもそこにいる連中が「ここは昔っからおらの土地だ」なんぞと寝言を吐いたら、どつきたくもなると言うもので。それに対して「大概にしとけよ」と言うのならばともかく「その通りだ」なんぞと言うアメリカ人は…そりゃテロの標的になろうっていうもの。


Beyond Fear の p.320 にはこうある。
反米感情が強い国が多いことから、海外では、カナダ人を装うアメリカ人が多い。

p.332 だと
攻撃者に目をつけられる者にならないのも、防御の一策だ。…企業なら、広報活動に力を入れることと、基本的によき企業市民である事だろうか。国家なら、責任ある行動を世界に示すことかもしれない。評判の悪い方針をとらないというのもひとつの方法だ。

とある。

防御と言う点から考えるならば、投資対効果という点からすれば、これ以上の「テロ防止策」はないだろう。ブッシュの行動や、アメリカの無責任な行動を見るにつけ、まさにこの評判の悪い方針ばかり取る事が、アメリカ最大の防御能力の低さの表れ、と言わざるをえまい。


昔、初めてアメリカに住んだ頃。親に言われたのが、
「日本人の代表だと思って行動しなさい」
と言うことだった。私が無様なことをすれば、日本人全部が無様だと思われる。失礼なことをすれば、日本人全体が失礼だと思われる。だからそのようなことの無いようにしなさい、と。

まぁ、実際問題としては、自分が正しいと思えばなんと言われようと闘うというスタンスになんら変わることはなかったのだが。運よくこのスタンスは 「American Justiceのために闘う」というアメリカ人の感性に訴えるものがあったらしく、ものすごく受けがよかった。果たして彼らにとっての日本人像がよくなっ たのか悪くなったのかは、自信が無いが、少なくとも私という人間の「防御」という観点からは、圧倒的な効果があったことは間違いない。


アメリカのように強大なパワーを持っている国の国民は、国外にいようが国内にいようが、自分の行動が国家の評判を上下するのだ、というスタンスを持って行動しなければ、発生する反感も強大になる。自分たちがいかに親切であるか、説明できるようではダメなのだ。説明できると言うことは、所詮 Countable な頻度でしか親切ではない、と言うことだ。そういう人に限って傲岸不遜振りは説明できないが、それは Uncountable なぐらい傲岸不遜なのだ、と思わなくてはいけない。マザーテレサの偉業を説明しきることなど出来るだろうか?


このような観点がものすごく過小評価されているのが、残念でならない。

2007年3月1日

Solaris10 telnetd 脆弱性を突いた worm 発生

「パターン青! 使徒です!!」

というわけでは無いだろうが、Vulnerability Note VU#881872(Sunの管理番号では #102802)を利用した worm が発生したらしい。
このwormの攻撃対象は x86 と Sparc の両方のプラットホームだそうだ。kshを使っているらしい。

うーむ。いまどきどうしてこんなバグが…という気もするが、やはり弱点が露呈すると worm を作る人が出て、しかもそれが実際に効果を上げる事が出来る、という事は、世の中の多くの人が、いかにセキュリティを甘く見ているか、いかにセキュリティ被害コストを甘く見積もっているか、の表れでは無いだろうか?

それとも侵入される程度であれば、予定通りで問題は無い、という事なのだろうか?
root権限ごと持っていかれているのに???その割には、「口うるさい」のも事実だよね?

頼むから口で言っている要求レベル実際にお財布から出すコストで実装できるレベルが乖離しまくっている状態を認識できないような人・組織・会社・政府に IT インフラ実装のための予算を与えないで欲しいなぁ…。