Entry

プログラミングメモ - 「危険なパスワードチェックとか」誤記の訂正とお詫び

2008年12月14日

今年書いたエントリをつらつら見直してたんですけれど,「qune: プログラミングメモ - 危険なパスワードチェックとか」の記述に誤りがあったので,訂正します。ごめんなさい。

memset() の呼び出しがなくなってる!これじゃメモリはクリアされません。つまり,スタックにはユーザが入力したパスワードが残っているということです。

qune: プログラミングメモ - 危険なパスワードチェックとか

こちらなんですけど,memset(3) の呼び出しはたしかになくなっているものの,インライン展開されていてメモリはクリアされていました。以下の部分です。

xorl %edx, %edx
movl $4, %ecx
movl %edx, %eax
rep
stosl
qune: プログラミングメモ - 危険なパスワードチェックとか

Cygwin gcc 3.4.4 では大丈夫ということでした。嘘ついて,ごめんなさい。

一方,こういう場合にいつでもメモリがクリアされるかというと,そういうわけでもないみたい。次のようなコードで,スタック上のメモリがクリアされるか,今度は VC6 で試してみました。

#include <windows.h>
#include <cstdio>
#include <cstdlib>

void
setpass(char *buf) {
    strcpy(buf, "foobar");
    return;
}

int
main(int argc, TCHAR* argv[], TCHAR* envp[]) {
    char buf[32];

    setpass(buf);
    ::puts(buf);
    ::memset(buf, 0, 32 * sizeof(char));

    return 0;
}

で,O2 オプションをつけてコンパイルしてみるとこんな感じに。

; Line 15
    lea     eax, DWORD PTR _buf$[esp+32]
    push    eax
    call    ?setpass@@YAXPAD@Z  ; setpass
; Line 16
    lea	ecx, DWORD PTR _buf$[esp+36]
    push    ecx
    call    _puts
; Line 19
    xor     eax, eax
; Line 20
    add esp, 40                 ; 00000028H
    ret 0
_main   ENDP
_TEXT   ENDS
END

VC6 の -Fa オプションは,ソースの行番号も示してくれるから分かりやすい。これを見ると,確実に memset() は呼ばれていないし,メモリがクリアされている形跡もありません。こっちを出すべきだった。ただ,今思ったんですけれど,この場合の memset() は main() の一番最後にあるもんなので,SOF(Stack Overflow)で攻撃するのは難しそうな感じもします。スタックが積まれている状態でも,同じように最適化されるのだろうか。それなら危険なんだけど。

アセンブリそれなりに読んでるんだけれど,まだまだスラスラとは読めてないなぁ……。ともあれ,失礼いたしました。

Trackback
Trackback URL:
Ads
About
Search This Site
Ads
Categories
Recent Entries
Log Archive
Syndicate This Site
Info.
クリエイティブ・コモンズ・ライセンス
Movable Type 3.36
Valid XHTML 1.1!
Valid CSS!
ブログタイムズ

© 2003-2012 AIAN