最新

おおいわのこめんと (2006-01)


2006-01-01

[Misc] 新年

年頭のご挨拶を申し上げます。今年も一年よろしくお願い致します。

さて、年末何をやっていたかというと、

  • サンタクロースが来なくなって久しく、それ以来我が実家では毎年年末に 家族内のプレゼント交換会が企画されるようになっているので、 何年ぶりかにデパートのアクセサリ売り場を隅から隅まで歩いてみた。 ……すいません、年末最後の週の出勤が遅かったのはそれです(笑)。
  • 小学校の同期と突発的な忘年会@地元。「もっと面白いこと日記に書け」とツッコまれる。
  • 就職1年目のボーナス記念ということで、親へのプレゼントを買いにヨドバシカメラへ。 ほんとに最近のプロジェクタって手で持って帰れるのね。
  • ついでにプリンタのトナーを買う。さらに、1つ買おうと思っていたゲームがあったのだが、 ネット上でバグの評判が酷いのと、ゲーム売り場に行ってみたら見たこと無いくらいの 大混雑だったので、見送ることにした。まぁPS版は既に持ってるしねぇ。
  • 大晦日に突然実装がしたくなったので、研究のプログラムをがりがり書く。 「ネタ消滅?」の件、 実装が完了。すばらしい。
  • 恒例の「初日の出ツアー」は、 今年は天気予報が悪くて望みがほとんどない*1のと、 共同企画者 (大の浦和レッズファン) が 絶対に外せない予定が昼に入ってしまった *2ので、 365日順延。さて、海面からの初日の出が見られるのはいつのことか。

[Misc] 風邪

うー、頭いたい、鼻水とまらん……。

素直に寝ておけってことか?

[Comp] うるう秒

さて、世界中の日記/blogに一体何件の

Jan  1 08:59:59 bluereef kernel: Clock: inserting leap second 23:59:60 UTC

なる行が書き込まれたことでしょうか :-)

*1 去年はもっと悪かったのに強行した気もするけど(笑)

*2 犬吠埼を8時頃出発しても、開門には全然間に合わないのよね。

本日のツッコミ(全1件) [メッセージを送る]

とっち [飲みすぎましたか?w ]


2006-01-03

[Comp] akrさん: stack bias in SPARCv9

akrさんの天泣記(なんて読めばいいんだ?)から。……へー、こんなことになっているんだ。知らなかったなぁ。

Bias させることの意義として素人頭で思いつくこととしては、SPARCv9 の pointer offset の指定範囲は 4095 〜 −4096 なので、2047 バイトオフセットさせることで、実質的には 2048 〜 −6143 として使えるようになる、ということかな? ローカル変数は %fp から負のオフセットでアクセスされるので、きっとそういうことなんだろう。

でも、gcc-3.4.1 だと、

int x(int *);

void test(void) {
  int q[1024 / sizeof(int)];
  int q2[1024 / sizeof(int)];
  int q3[1024 / sizeof(int)];
  int q4[1024 / sizeof(int)];
  q[0] = 0;  x(q);
  q2[0] = 0;  x(q2);
  q3[0] = 0;  x(q3);
  q4[0] = 0;  x(q4);
}

とかいうコードを -mno-stack-bias の有無を変えてコンパイルすると、

        .file   "test.c"                         .file   "test.c"
        .section        ".text"                  .section        ".text"
        .align 4                                 .align 4
        .global test                             .global test
        .type   test, #function                  .type   test, #function
        .proc   020                              .proc   020
test:                                    test:
        !#PROLOGUE# 0                            !#PROLOGUE# 0
        save    %sp, -4096, %sp                  save    %sp, -4096, %sp
        add     %sp, -192, %sp                   add     %sp, -192, %sp
        !#PROLOGUE# 1                            !#PROLOGUE# 1
        st      %g0, [%fp+1007]        |         st      %g0, [%fp-1040]
        call    x, 0                             call    x, 0
        add     %fp, 1007, %o0         |         add     %fp, -1040, %o0
        st      %g0, [%fp-17]          |         st      %g0, [%fp-2064]
        call    x, 0                             call    x, 0
        add     %fp, -17, %o0          |         add     %fp, -2064, %o0
        st      %g0, [%fp-1041]        |         st      %g0, [%fp-3088]
        call    x, 0                             call    x, 0
        add     %fp, -1041, %o0        |         add     %fp, -3088, %o0
        sethi   %hi(4096), %g4         |         sethi   %hi(4096), %g1
        add     %fp, 2047, %g1         <
        xor     %g4, -16, %o0          |         xor     %g1, -16, %o0
        st      %g0, [%g1+%o0]         |         st      %g0, [%fp+%o0]
        call    x, 0                             call    x, 0
        add     %g1, %o0, %o0          |         add     %fp, %o0, %o0
        nop                                      nop
        return  %i7+8                            return  %i7+8
        nop                                      nop
        .size   test, .-test                     .size   test, .-test
        .ident  "GCC: (GNU) 3.4.1"               .ident  "GCC: (GNU) 3.4.1"

という結果になってしまう。左側 (stack bias 有り)、最後の q4 の store やアドレス計算は、 [%fp-2065] で届くはずなのに、結果は右 (stack bias 無し) と同様なアドレス計算コードが 挿入されてしまっている……。勿体ないなぁ。


2006-01-06

[Work] 探さないでください(TM)

明日から1週間出張です。関係があるようで、実はまだ一度も参加したことのない学会なので、ちょっと楽しみ。

[Misc] C as scripting language

奥君が、なにやら面白そうなものを作っている……。まぁ本文のノリはネタなんだろうけど。 で、自分が作ろうとしていたものと35%位ネタが被っているので、ちょっとやられた気分(笑)。

ま、ネタとしてではなく研究上も必要なんで、どっちにしても作るけどね。


2006-01-16

[Work] 帰国

しますた。

行きの飛行機は遅れて結構大変だったのだが、 帰りは極めて順調で、予定の30分前に到着。 そのまま同乗者がいたのでスカイライナーで日暮里まで、 そこからJR京浜東北線で秋葉原へ。そのまま出勤して 企業の方との打ち合わせ。なんかスケジュールがムチャクチャだな(笑)。

……なんか職場に足を踏み入れて少ししたら、気分がすっかり仕事モードになってしまって、 時差ぼけも忘れて、帰りに旅行のトランクを引き摺って帰るのを忘れそうになった(笑)。

明日も打ち合わせなので、普通に(?)出勤する予定。

追記 (1/20)

というわけで、POPL 2006 に行ってきたわけですが、 会場がホテル併設の「劇場 兼 ホール」というような場所で、 ネオンサインが光っているという怪しい(笑)建物だったわけですが、 最終日ふと気が付いたところ、入り口の上にイカす掲示が……。

というわけで、自前の写真もあるのですが、まずはとりあえず POPL 公式ページをドゾー。

……現場で見てまじ吹き出しそうになりましたよ。


2006-01-25

[Security] hidden field に session ID を入れる CSRF 対策方法に対する反論に対する反論

ああ、禅問答のようなタイトル。

前から、「おさかなラボ」なるページで 高木浩光氏の推奨するCSRF対策は安全でない、との主張が 展開されていたので注目していたのだが、最近↑のページの再反論がでて、やっと僕の中では結論がでた感じ。

で、結論は、「やっぱり彼の主張は反論になってない」でよさそう。 正直、再反論の主張を見て、思ったような内容じゃなくてちょっとがっかり。

彼はずっと、「hidden フィールドはキャッシュから漏洩する」と主張していたので、 きちんと対策していてもそういうことが起こる状況想定を何か持っているのかと期待していたのだが、 再反論での主張は「たとえ Pragma: no-cache していても、cache のディスクに残る可能性はあるから駄目だ」 というだけだった……。

彼が見落としている、あるいは再反論の時点で意識から飛んでしまった点は2つあって、 1つめは、proxy のバグがある前提では、「Set-Cookie」ヘッダを含む あらゆるリクエスト・レスポンス情報が漏洩する危険性があるので、 たとえセッションIDを予測できない一時認証鍵を form に埋め込んだところで、 セッション鍵の漏洩を防げない、という点。 これは本質的で、特に彼の主張する「no-cache でもディスクに保存される」というセマンティクスを もつ cache においては、form の hidden の値はディスクに保存されるが、 session key をディスクに保存させないという状況は存在しないのである。 何故か彼は盲目的に Cookie は漏洩しないと思い込んでいるようだが、 Set-Cookie はレスポンスの一部である以上本文の一部である form のデータとは一組で扱われるし、 そもそも RFC2965 の Section 3.2.3 を見ればわかる通り、 Cache-Control: no-cache="Set-cookie2" か (彼が脆弱だと主張する) Cache-Control: no-cache を送出しない限り、Set-cookie はキャッシュに残り、 たとえ別のクライアントに対してであっても再送出されるのである。 *1

(余談) ちなみに、この Set-cookie をキャッシュする仕様、どんな使いみちがあるんか? と思うのは自然だと思うが、 RFC2965 には、「ログイン前の初期ページを要求した時点でセッションを expire させる Set-cookie を送出するケース」を 想定した記述がある。ま、普通は "Cache-Control: no-cache" と組み合わせて使え、ということですね。(余談終り)

ついでにいえば、Vary: Cookie ヘッダがついている (これは問題の form のあるページには付いているべき) レスポンスの返り値をキャッシュするためには、クライアントの送出した Cookie の値を一緒に保存しておかないと、 次回のリクエストの照合ができなかったりする。(そもそも no-cache の値をなぜ保存するんだ、という疑問は それが彼の置いた前提なのでおいておくとして。) さて、この状況でディスクから form の hidden 値だけが洩れて Cookie は洩れないシチュエーションって本当に考えられるのですか、というのが疑問。

(さらに余談) ちなみに、彼が言及している no-store 要求だが、これはサーバ側からの レスポンスの取り扱いの差異というよりは、リクエスト側で強い意味を持つヘッダのように思える。 リクエストの "Cache-Control: no-cache" は、基本的に「前の要求結果は欲しくないので、最新情報を取得してくれ」 と proxy にお願いするためのディレクティブである。一方、"Cache-Control: no-store" がリクエストに入っていると、 「この要求とその結果はディスクに保存しないでくれ」という要求を表している。さて、RFC2068 には "Cache-Control: no-cache" を持つリクエストに対する "Cache-Control: no-cache" の無いレスポンスを キャッシュしてはならないという記述はぱっと見て見当たらないような気がしてきたのだが、 見落としてるかな?……(さらに余談終り)

そして、「クロスドメイン脆弱性」を定義せずに使っている時点で どうか*2 と 思うのだが、クライアント側にバグと呼ぶに値する脆弱性があったら、 普通は form の値だけじゃなくて、cookie の値も漏洩していると思うのは、 自然かつ妥当だとおもうんけどね。 所詮は cookie は「自動送出される hidden パラメータ」なのであって、 form のパラメータ以上の安全性を仮定している時点で何かおかしい。 *3 で、当然ですが、セッション鍵が流出した場合、cookie 認証のみのページが1ページあれば、 あとは彼のページで列挙されているどんな対策を取っても破られます。どんな複雑な方法で一時鍵を製作しても、 問題のページから辿れば正規の一時鍵が取得できますから当たり前ですね。

やっぱりこの手のセキュリティの議論をする時に、 前提条件ははっきりさせないとマトモな結論は出ない、というのは だいぶ前にも書いたが、改めて確認しておきたい。 高木さんの前提は「XSS, Session Fixation, ブラウザのバグ, TCP/IP 盗聴」はないもの *4 としているのであって、その前提をひっくり返した反論を、その前提をひっくり返すだけの根拠を出さずに 述べても虚しさが残る。 もちろん、ブラウザ・キャッシュなどのバグに対してどれだけ頑強か、という主張を敢えて展開するのだ、というなら それは構わないが、その前提での議論としては現状の彼の主張は (特に自ら推奨する手法にも脆弱性が残るという点で)根拠が弱過ぎる。 そもそも、そんな物を前提にしたら大抵は「何やっても無駄」 *5 という結論になってしまう *6

ちなみに。高木対策案だが、hidden field の文字列がセッション鍵と同じ文字列である必然性ないセッション鍵が分からないと hidden field の値を推測・複製できない、ということだけがセキュリティ上の要件であり、 最も単純明解で即時実装が可能な方法で実装されたのがあの方式であると僕は理解している。 だから、別に「同じ文字列は気持ち悪い」という感情をどうしても抑えられなくて、 かつ SHA-1 とか簡単に使えるプログラミング環境を使っているのであれば、 HMAC 風味で適当な秘密の文字列と concat して SHA-1 とるとかして、 一方向性を持たせても一向に構わない*7。 セッション変数を使うのは問題に対して明らかに過剰で気に入らないが、 やりたければ完全乱数*8 にしてセッションIDに紐付けられたサーバ側セッション変数に保持しても要件は満たす。 ただ、所詮は cookie からのセッションIDの漏洩のリスクと同次元のリスクなので、 本質的にセキュリティレベルが上がっているわけではない。

追記 (2006-01-25)

やっとキャッシュ以外の脆弱性の話が語られたので 補足しておきますが、IE の標準設定以外に脆弱性があるのは当然の常識 (そもそも Active X を無条件に受け入れるとか、明らかな脆弱性があります) かと思います。 IE の非標準設定を許す前提では、何も(ローカルコンピュータのセキュリティすら)守れない、 という結論になります。これは IE というブラウザの大きな問題だと思いますし、 単独できちんと議論される問題だと思いますが、今回の話でいえば、 CSRF の特定の攻撃ができる設定だけが変えられて、Active X の項目とかは変わっていないという 前提は無理があります。

あと、当該ドメインに XMLHTTPrequest が送れ、レスポンスが受けとれる状態では、 別にその場で既存のセッションに乗っかって request を送り返せばいいだけですから、 どんなセッションキーを推測できない秘密の符丁を使っても正規のリクエストを送れます。 ですから、セッション鍵を盗む必要性が無くなり、他の対策も含めて CSRF 対策にならなくなります。 それも、スクリプト主導で入出力が両方できる(レスポンスに応じたリクエストを作れる) CSRF 発動状態というのは、ユーザが攻撃に気がついてセッションを閉じるまで *9、 本質的にセッション鍵が盗まれたのと同じだけの攻撃が可能ですから、 「セッション鍵が盗まれてないからより安全」とは言えなくなります。 「XSS とかがないのが前提です」というのも、要するに原理は同じです(微妙に惚けてたの修正)。 XSS がある状態では、たとえ tDiary のように session ID cookie がなくても受動攻撃を受けます。

*1 form のページと違うページでセットされることが多いのは事実だが、セキュリティ的に本質的な差異ではない。

*2 少なくとも FUD のうちの U は満たしてしまっている。

*3 未知の攻撃パターンを仮定した時には、あらゆるリクエストで自動送出される分だけより危険だ、とすら考えてもいい。

*4 この前提条件は高木氏自身が解説しているが、その妥当性は、これらは別途対策を要し、その対策をしないとどんな対策をしても CSRF と同等以上の脅威を原理的に防げないことが論証可能である、ということに依っている。

*5 proxy のバグに関しては、SSL を使って proxy には平文を1バイトたりとも触らせない、という結論はありか……。

*6 というか、それ以外の中途半端な結論は恐らく間違いである。

*7 正直、1月に1回くらいは、「SHA-1 くらいかけてもいいのになぁ」と思う一方で、 1月に30日くらい「あーでも本質的じゃないんだよなやっぱり」と思ってたりする。

*8 当然、この乱数は cryptographically secureか、 少なくとも セッションID以上に予測不可能な乱数 でなければならない。 この条件、/dev/random とかの存在を仮定して良ければ簡単だが、 スクリプト言語レベルで移植性を考えると結構厳しい。

*9 冷静に考えれば、これもセッション鍵盗聴の場合と同じなのですが。


2006-01-26

[Work] 今日のバグ

今日はめずらしくお仕事の経過でも張ってみる。

(gdb) bt
#0  0x401b0436 in __lll_mutex_lock_wait () from /lib/tls/libpthread.so.0
#1  0x401ad893 in _L_mutex_lock_26 () from /lib/tls/libpthread.so.0
#2  0x4007c8b8 in ?? () from /lib/tls/libc.so.6
#3  0x40063728 in ?? () from /usr/lib/libgc.so.1
#4  0x00000080 in ?? ()
#5  0x00000100 in ?? ()
#6  0x401a3e80 in ?? () from /lib/tls/libc.so.6
#7  0x00000080 in ?? ()
#8  0xbfffec54 in ?? ()
#9  0x401561af in pthread_mutex_lock () from /lib/tls/libc.so.6
#10 0x401561af in pthread_mutex_lock () from /lib/tls/libc.so.6
#11 0x4005cd95 in GC_generic_lock () from /usr/lib/libgc.so.1
#12 0x4005cdfe in GC_lock () from /usr/lib/libgc.so.1
#13 0x40052f95 in GC_malloc () from /usr/lib/libgc.so.1
#14 0x080519fe in fsc_alloc_block_full (type=0x8056d00, nelems=1, remainder=0, 
    flags=16) at fsc_alloc.c:30
#15 0x08051b10 in fsc_alloc_block_with_flags (type=0x8056d00, len=1, flags=16)
    at fsc_alloc.c:66
#16 0x08051c21 in fsc_alloc_block_library (type=0x8056d00, len=1)
    at fsc_alloc_inline.c:6
#17 0x0804b9ed in fsc_signal_handler (sig=14, info=0xbfffee48, p=0xbfffeec8)
    at signal.c:100
#18 <signal handler called>
#19 0x401ad8cc in pthread_mutex_trylock () from /lib/tls/libpthread.so.0
#20 0x40052f20 in GC_malloc () from /usr/lib/libgc.so.1
#21 0x080519fe in fsc_alloc_block_full (type=0x80570c0, nelems=0, remainder=1, 
    flags=0) at fsc_alloc.c:30
#22 0x0804a77e in FS_Fi_Pv_malloc (bn=0, n=1) at malloc.c:39
#23 0x08048f33 in FS_F_i_main () at /tmp/j1yUKVa3fl/fscbug-36.safe.c:158
#24 0x08048f66 in FG_main (FAva_b=134647720)
    at /tmp/j1yUKVa3fl/fscbug-36.safe.c:165
#25 0x08049304 in main (argc=1, argv=0xbffff3a4) at main_bootstrap.c:41

……。見事に再入してますな (^^;;

シグナル周りは単なる並列処理とも違って、この手の状況では必ずデッドロックするので 回避がめんどくさい。ロックの他にも色々と困る事情は山ほどあって、 Caml の実装とかでも中見ると安全に処理するためにいろいろやってるんだよねぇ……。 ちなみに今はとりあえず正しく動く状態にはなっている。


2006-01-27

[Work] [Comp] Embedded-C 公開

Fail-Safe C では各種データのサイズ (int とか long とか) や、 OS の各種定数 (SOCK_STREAM とか) は基底にある標準Cコンパイラ及び OS標準ABIに合わせることになっていて、 ある種の configure 処理が必要になっている。 *1

これまでは割と場当たり的に OCaml の native method 書いたり、その場しのぎの検出プログラムを書いたり、 これまたその場しのぎで cpp + sed で処理したりしていたのだが、どうせなら汎用のツールを作って きちんと処理してやろう、ということで、すこし開発時間を確保してツールを作ってみた。

というわけでできたのが、Embedded-C。 端的にいえば、ERB や EPerl の C 言語版。 1/6日に触れた 奥君の Large-C との関係は、 perl -e と eperl の関係とか、irb と erb の関係……ってこれじゃさっぱりわからないか(苦笑)。

例えば、

<%# #include <errno.h> #%>
#define EINVAL <%=d EINVAL %>
#define EFAULT <%=d EFAULT %>

というソースを処理すると、

#define EINVAL 22
#define EFAULT 14

という感じになる。"<%=d x %>" というのが、x を printf の %d フォーマットで出力する、 という意味になっている。もちろん文の埋め込みもサポートしているので、

<%# int fib(int i) { return i <= 1 ? 1 : fib(i - 1) + fib(i - 2); } #%>
int array[1000] = { <% { int i; for (i = 0; i < 1000; i++) printf("%d, ", fib(i)); } %> };

とかやれば、フィボナッチ数列で初期化された配列とか作れるし *2、 もちろん出力言語は C ヘッダじゃなくても、OCaml でも Perl でも text file でもなんでもいい。 この手の値の検知が必要な状況で、configure.in の M4 がメンドクサイ向きにはちょうどいいかも(笑)。

変数置換に特化した autoconf の *.in → * の出力部分と違って、 埋め込む出力自体をループや関数呼出を含む複雑な処理で生成できるので、 実はちょっと複雑なC言語プログラムとマクロ定義を書いてやれば、IDL モドキまで作れてしまう。 GCC の typeof 拡張演算子と sizeof 演算子をうまく使うと、 型のサイズと種類を見て、生成する処理を分岐して……… とかできてしまうので、 結構怪しげな物が書けることは、自分で作ってから気がついた :-)。

作ってみたら結構便利そうで、自分一人で使ってるのは勿体ないので、 公開してしまうことにした。 何か面白い使い方があったらぜひ教えて欲しい。

ちなみに、お仕事の本題の Fail-Safe C の方ですが、ここ数カ月極めて順調に開発が進んでいるんで、 単なる性能評価ベンチマークじゃない、実用的に意味のあるデモが作れそうな気がしてきている。 乞御期待(笑)。

*1 特に Linux とか、昔なら #define で定義していたような各種定数がことごとく enum になってて、cpp では値取れないんだよね……

*2 当然こんないい加減な fib だと fib(999) は終了しないけど(ぉぃ


大岩 寛 (おおいわ ゆたか) <yutaka@oiwa.jp.nospam ... remove .nospam> .

Copyright © 2005-2014 Yutaka OIWA. All rights reserved.
Posted comments and trackbacks are copyrighted by their respective posters.

記事の内容について (Disclaimer / Terms and Conditions)