パスワードの判定にstrcmpを使うべきでない理由

Last Modified: Wed Apr 7 10:54:30 UTC 2010

strcmpを使ってパスワードを判定すると、タイミング攻撃 (timing attack) にやられる危険性があることの説明 (約20分)。


まとめ:

パスワードなどの文字列を strcmp関数 (およびそれに類する関数) を使って判定すると、 その判定にかかる時間を測定することで、パスワードが推測できてしまう場合がある。 これをタイミング攻撃 (timing attack) という。

この例では、36種類の文字を使った8文字分のパスワードを推測するのに、

の試行が必要なのに対して、 しかかからない。タイミング攻撃を成功させてしまうと、 重要な情報が漏洩してしまう危険性がある。 これを防ぐためには、なるべく実行時間に差が出ないようにする プログラミング上の工夫が必要である。

現在は、コンピュータの性能が上がってきていることもあり、 以前に比べてタイミング攻撃は難しくなっている[要出典]。 またネットワーク上からパスワードを入力する場合は、ネットワークによる遅延があるため タイミング攻撃はより難しい。しかし、攻撃者に十分な時間が与えられている場合、 これらの攻撃は依然として有効である。

問題:

新山がこの動画で食べているモノは何でしょう?


a.c

/* a.c */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>

#define DISALLOW_TIMING_ATTACK 1

int check_passwd(const char* s)
{
  const char secret_passwd[] = "foo123ab";
  int i;
  int result = 1;
  for (i = 0; i < sizeof(secret_passwd); i++) {
#if DISALLOW_TIMING_ATTACK
    /* don't let them guess the password! */
    result &= (s[i] == secret_passwd[i]);    
#else
    if (s[i] != secret_passwd[i]) return 0;
#endif
  }
  return result;
}

static const char passchar[] = "abcdefghijklmnopqrstuvwxyz0123456789";

int main(int argc, char* argv[])
{
  if (argc < 2) return 1;
  char* passwd = argv[1];
  int passlen = strlen(passwd);
  char* buf = malloc(passlen+1+1);
  strcpy(buf, passwd);

  int j;
  for (j = 0; j < strlen(passchar); j++) {
    struct timeval tv0, tv1;
    buf[passlen] = passchar[j];
    gettimeofday(&tv0, NULL);
    int i;
    for (i = 0; i < 10000; i++) {
      check_passwd(buf);
    }
    gettimeofday(&tv1, NULL);
    int d = ((tv1.tv_sec - tv0.tv_sec) * 1000000 +
	     (tv1.tv_usec - tv0.tv_usec));
    printf("%s: %d\n", buf, d);
  }

  return 0;
}

Yusuke Shinyama