Help us understand the problem. What is going on with this article?

PHPでパスワード比較に==とか===使っちゃだめって知ってた?

PHPerの皆さん、重要な文字列を入力データと保管情報を比較するときに比較演算子("=="とか"===")使ってませんか?
これ実は使っちゃだめなので、気をつけましょう。

なぜだめなの?

(2020/8/31修正) 関数名をtypoしていたため修正しました。(正)memcmp・(誤)strcmpです。

PHPを含む多くの言語では、文字列を比較する際に内部で memcmp() を使います。
通常の(厳密なセキュリティを必要としない)ケースでは、比較演算子を使うことはまったく問題ありません。
パスワードなど絶対に推測されてはいけない文字列を比較する場合、この関数は脆弱といえます。
memcmp() は内部で1バイトずつ比較検証するため、応答時間をもとに先頭から何文字正解だったか推測できます。
このような攻撃を「タイミング攻撃」といいます。

どうすればいいの?

PHPでは、ハッシュ値を用いて文字列を比較する hash_equals() という関数が用意されています。
関数の説明にもきちんと「Timing attack safe string comparison」と書かれています。

https://www.php.net/manual/en/function.hash-equals.php

パスワードを扱う際の正しい実装

(2020/8/28追記) @anirfa さんのコメントをもとに追記しました。

ここまでは平文で保管された「重要な文字列」を扱う際の注意点でした。
たとえばパスワードなどの第三者から読み取らせてはいけない情報はそもそも平文で保管せず、ハッシュ化して保管すべきです。
PHPにはパスワード管理のために以下のような関数がありますので、そちらを使ってください。

実装をのぞいてみた

本当に比較演算子で strcmp() が使われてるかPHPソースコードをみてみましょう。

zend_string.h#L316-L335

zend_string.h
#if defined(__GNUC__) && (defined(__i386__) || (defined(__x86_64__) && !defined(__ILP32__)))
BEGIN_EXTERN_C()
ZEND_API zend_bool ZEND_FASTCALL zend_string_equal_val(zend_string *s1, zend_string *s2);
END_EXTERN_C()
#else
static zend_always_inline zend_bool zend_string_equal_val(zend_string *s1, zend_string *s2)
{
    return !memcmp(ZSTR_VAL(s1), ZSTR_VAL(s2), ZSTR_LEN(s1));
}
#endif

static zend_always_inline zend_bool zend_string_equal_content(zend_string *s1, zend_string *s2)
{
    return ZSTR_LEN(s1) == ZSTR_LEN(s2) && zend_string_equal_val(s1, s2);
}

static zend_always_inline zend_bool zend_string_equals(zend_string *s1, zend_string *s2)
{
    return s1 == s2 || zend_string_equal_content(s1, s2);
}

zend_string_equals->zend_string_equal_content->zend_string_equal_val->memcmpが呼び出されていますね。
※インラインアセンブラが使える場合の処理(zend_string.c#L396-431)の説明は割愛します

mediado
私たちメディアドゥは、電子書籍を読者に届けるために「テクノロジー」で「出版社」と「電子書店」を繋ぎ、その先にいる作家と読者を繋げる「電子書籍取次」事業を展開しております。業界最多のコンテンツラインナップとともに最新のテクノロジーを駆使した各種ソリューションを出版社や電子書店に提供し、グローバル且つマルチコンテンツ配信プラットフォームを目指しています。
https://mediado.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした