質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
セキュリティー

このタグは、コンピューターシステムの安全性やデータの機密性に関連したトピックの為に使われます。

暗号化

ネットワークを通じてデジタルデータをやり取りする際に、第三者に解読されることのないよう、アルゴリズムを用いてデータを変換すること。

Q&A

9回答

12892閲覧

SSLを利用したWebサービスでログインパスワードを安全に保存するには?

hojo

総合スコア195

セキュリティー

このタグは、コンピューターシステムの安全性やデータの機密性に関連したトピックの為に使われます。

暗号化

ネットワークを通じてデジタルデータをやり取りする際に、第三者に解読されることのないよう、アルゴリズムを用いてデータを変換すること。

6グッド

15クリップ

投稿2016/09/26 08:19

編集2016/10/06 02:16

安全なパスワードの保存を行う為に暗号化はどこで行うべきですか?(旧タイトル)

Webサービスで安全なパスワードの保存を行いたいとします。

パスワードをSHA256などによって暗号化することはよくある話だと思います。しかし、このSHA256を利用して暗号化する場合、暗号化はサーバサイドで行うべきか、クライアントサイドで行うべきか悩んでいます。

サーバサイドで暗号化を行う場合、入力されたパスワードが暗号化されないままサーバに届くことになります。(SSLの話ではありません)

その後、アプリケーションサーバの手によってデータベースにパスワードを保存する際にはSHA256によるパスワード暗号化を行った上で保存することになるわけですが、アプリケーションサーバにはパスワードがそのままの形で届いてしまっていることに変わりありません。

我々が利用しているアプリケーションサーバはセキュリティ的に問題無いから大丈夫だ!とサービス運営者が主張したところで、サーバの権限を奪われる可能性はゼロではありませんし、それ以前にアプリケーションサーバの運営者はパスワードが直接届くような環境でアプリケーションを日々保守していたりするわけです。

また、アプリケーションサーバがGETやPOSTに対するログを取るように設定されていた場合、送信されたパスワードは暗号化されることなくログファイルに記載されることになります。

つまり、サーバサイドでSHA256によるパスワード暗号化を行う仕様の場合、暗号化されないままアプリケーションサーバに届くパスワードを運営は安全に管理してくれるだろうと信用する形でサービスを利用することになります。

これはなんかダメなんじゃないかなっていう気がするんです。

これを回避するためJavascriptなどを利用してクライアントサイドでパスワードを暗号化してからアプリケーションサーバに暗号化されたパスワードを送る方法をとれば、このような心配事は無くなります。

しかしその場合、SHA256で使用するSaltキーなどはどのように設定すれば良いのでしょうか?そのままjavascriptのソースファイルに暗号化キーであるSaltキーを記述してしまって良いのでしょうか?

なんとなくSaltキーの情報が漏れていることはあまり良くないことのような気がしています。しかし、SHA256は復号化が不可能な暗号化なので、一度暗号化されてしまったものを復号化することは不可能だと思います(そうですよね?)

だから安全だと言い切れるのでしょうか?
何か嫌な感じがします。

どうにかSaltキーの情報を隠蔽したいと思っていますが、クライアントサイドで暗号化を行う以上、隠蔽することは不可能なのではないかと思っています。本当にこのSalt隠蔽問題は気にしなくても良いことなのでしょうか?

何か考え方がおかしいのかもしれませんが、こんな私に何かアドバイスいただけたらと思います。

追記(2016/09/26 18:30)

質問がダラダラとした文章になり、分かりにくいようですので質問を変えさせていただきます。

SSLによる暗号化通信を前提としたWebサービスで入力フォームなどによってユーザが入力するパスワード文字列をサーバサイドで暗号化する場合、そのパスワードの安全性が保障されません。

なぜなら運営がパスワードを安全な形で管理しているかわからないし、暗号化していたとしても暗号化する前のパスワードをアクセスログに残している可能性なども考えられるためどこからパスワード文字列が漏れるかわからないからです。

しかし、クライアントサイドでパスワードを暗号化した場合は、アプリケーションサーバにパスワードが届いた地点ですでに暗号化されているため、パスワードの文字列が漏洩する心配は無くなります。

漏れたとしても暗号化後のハッシュ文字列だから元のパスワードが漏れるより安心できると考えられます。

そのため、クライアントサイドでSHA256によるパスワード暗号化を行った上でサーバサイドにパスワードを送る方法をとったほうがユーザにパスワードの安全性を保証することができるのではないですか?

この考え方は正しいですか?

またクライアントサイドでSHA256によるパスワード暗号化を行った場合、ハッシュを生成するために必要なSaltキーが必要になりますが、Saltキー隠蔽することは可能ですか?不可能な場合、Saltキーが漏洩していることでどのような問題が起こりますか?

追記(2016/10/01 18:06)

ここまでの流れとして、質問者(私)が認識したことをまとめてみます。

  • SSL/TLSを利用したhttpsプロトコルの利用は必須
  • SHA256は暗号化ではなく、ハッシュ生成のアルゴリズム(関数)である。
  • Saltはキーではない
  • 常識的にシステムを構築していればSaltは漏洩は気にしなくて良い
  • サーバサイドでのパスワードのハッシュ化は必須である
  • クライアントサイドで生成したパスワードハッシュをそのままDBに保存してはならない
  • パスワードのハッシュが漏洩した場合、元のパスワードを総当たりで突き止めることができる(オフラインの場合?)
stereo_code, htsign, zico_teratail, kaz.Suenaga, SASAHARA, phpbeginners👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tanat

2016/09/26 11:14

追記部分を読んでの質問です。 サーバ側の処理を信頼できないとした場合、 そもそもパスワードが漏れようが漏れまいがクラックされてしまうところまで考えないといけないレベルの話になってしまいます。 そのため、質問の焦点が 「パスワード文字列そのものが漏洩するかどうかであり(例えばパスワードの使いまわしをしていて、パスワードの文字列自体が漏れるのが嫌だ)、パスワードを使ってその脆弱なシステムになりすましログインできるかどうかではない」 であるように解釈したのですが、この解釈は正しいですか?
hojo

2016/09/30 23:00

お返事が遅くなってすみません。 質問の焦点としましては「より安全なパスワードの保存方法を知りたい」です。 すなわち 「パスワード文字列そのものの漏洩を防ぐ」こととに加え「脆弱なシステムになりすましログインできることも防ぐ」というような、可能な限り安全かつ現実的な方法を求めています。
退会済みユーザー

退会済みユーザー

2016/09/30 23:52

クライアントサイドで暗号化したパスワードは「複雑化されたパスワード」なだけで送信された「パスワード」をそのまま保存したら「平文のパスワード」と変わらないだろう・・・桁数が多いだけで
hojo

2016/09/30 23:58

おっしゃる通りです。そのような回答を幾つか頂いております。
guest

回答9

0

クライアント側: パスワードからハッシュ値生成
クライアント->サーバ通信: ハッシュ値
サーバ側: ハッシュ値
サーバでの判断: 送られたハッシュ値と保存しているハッシュ値を比べる

このような方法を考えていて、これなら、ハッシュ値が漏れても安心だと言いたいのですね(Saltをどうするかは別として)。さて、もし、この方法を使っているシステムでハッシュ値が盗まれた場合、盗んだ人達は簡単に利用者のなりすましができてしまいます。盗めたのはハッシュ値だけで、システムの完全乗っ取りまではできなったとしてもです。クライアント側の処理は何でも可能です。つまり、パスワードからハッシュ値をわざわざ生成しなくても、初めからハッシュ値をサーバに送ればログインできてしまいます。これってPass-the-hashという脆弱性の一種になると思われます。

なお、一般的なサーバにパスワードそのものを送る仕組みの場合は、ハッシュ値が盗まれてもログインは不可能です。なぜなら、サーバ側で必ずハッシュ化処理をしてしまうため、ハッシュ値を送っても無駄だからです。SHA256のような安全な暗号学的ハッシュ関数で暗号学的にランダムに生成されたSalt値を使ってハッシュ化しているかぎり、ハッシュ値だけが盗まれたとしても、そのハッシュ値になるサーバへ送るべきパスワードを調べ上げることはほぼ不可能(現実的じゃない時間が必要)になるため、攻撃者はログインすることはできません。

でも、パスワードをサーバに送りたくない…では、どうするか…。となると、他に取れる手段は公開鍵認証しかないかとかと思います。クライアント証明書認証や、SSHの公開鍵認証で使われている仕組みです。サーバに登録するときに渡すのは公開鍵のみです。盗まれようが何しようが、痛くもかゆくもありません。クライアント側にある秘密鍵はクライアント側から出て行くことはありません。クライアントに保存された秘密鍵をパスフレーズで暗号化していれば、さらに安全です。(公開鍵認証の仕組みについては、長くなるので省きます)

公開鍵認証の一番の難点は、公開鍵を登録するときに、その公開鍵が本人なのかどうかです。これは別の方法で担保する(メールを送る、SMSを送るなど)しかないでしょう。ただ、うまく公開鍵さえ登録できれば、あとは通信を盗み見られようが、登録された公開鍵が漏洩しようが、秘密鍵はクライアントからは出て行きませんので、安全と言えるのでは無いでしょうか。

使い道が限られますが、あるデータを保存・管理するようなシステムであれば、もう一つ手段があります。利用者のデータをクライアント側で暗号化して、サーバ・クライアント間の通信やサーバ上のデータは常に暗号化された状態にし、クライアント側で復号化するという方法です。Passpackというパスワード管理サービスはこの方法を用いていると自称しています(私はそのサービスの利用者ですが、それが本当かどうかまでは知りません。ですので、漏れても良いものしか登録しないようにしています)。この仕組みであれば、サーバ側ではどんなにがんばっても、復号化された状態のデータを見ることはできません。

投稿2016/09/26 15:54

raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hojo

2016/09/30 23:35

丁寧でとてもわかりやすい回答ありがとうございます。 なるほど「公開鍵認証」ですか。Webサービスで公開鍵認証を使うということは、つまりSSLとは他に新規アカウント作成すると同時に秘密鍵のダウンロードが行われ、その秘密鍵をブラウザに登録してもらうことで初めてウェブサービスにアクセスできるといった仕様になるということになりますよね? セキュリティがものすごく重要になってくるサービスならこの方法をとることでユーザに安心感を与えることができるかもしれませんが、さすがにサービスの利用の敷居が高くなってしまうのでこの方法は「より安全度の高い方法」として認識させていただきます。(ありがとうございます!)また、passpackが取っている手法についてもとても興味深いものでした。 その他の回答でも同じ質問をさせていただいているのですが、クライアントサイドでパスワードのハッシュを生成し、サーバに送信した後サーバサイドにて再度「パスワードのハッシュのハッシュ」を生成してデータベースに保存するという手法を先ほど思いついたのですがこちらについてはどう思われますでしょうか? ぜひご意見いただきたいと思っております。
pack

2016/10/01 02:47

回答者に対して、お一人ずつ同じような質問を書いておられますが、それはマルチポストです。 もうすでに、議論の内容において、かなりの重複が見られます。 コメントで、また重複した質問をすれば、さらに悪化するだけです。 そういったのは、全ての回答、コメントを、一度ご自身で整理した後に、改めて質問があれば、新たに質問を作り直した方がいいでしょう。
raccy

2016/10/01 02:49

公開鍵での秘密鍵配賦について、内部の職員が対象であれば、秘密鍵が入ったICカードやUSBキーなどを配るというのもあります。ICカードだとカード読み取り機が必要になるし、USBキーだと抜き差しの繰り返しで壊れやすいという欠点はあるのですが。 外部向けであっても、実際に重要なサービスでは公開鍵認証を使っている物があります。動作保証するブラウザがFirefoxのみだったり、設定も面倒だったりと結構敷居が高くなりますが、安全性確保という意味では仕方が無いのかなと思っています。 ハッシュ化したのをさらにハッシュ化はotnさんと同じ意見ですね。それほど意味があることではありません。そもそも、現在のインターネットにおいては「パスワードは使い回さない」ことが前提であるため、生パスワードが漏れても被害はそのサービスのに限定されると考える場合が多いようです。そういう点で、生パスワードが漏れても、一段階目のパスワードが漏れても、結局被害は一緒になると考えるようです。それよりは、生体認証や二段階認証などを採用し、パスワードが漏れる、または、他で漏れた(使い回しの)パスワードで使われる、といった自体でもログインを防ぐことに焦点を向けています。
hojo

2016/10/01 03:07

>> pack 申し訳ございません terataillのコメント欄が各回答に分離してしまっているので このような形になってしまいました。 少し収拾がつかなくなっている気がするので 改めて質問を分割して投稿しようかと考えております。
pack

2016/10/01 07:42 編集

「重複問題」は、回答者側の欲もあるんですけどね。 こうして回答が林立したりするのも、teratailの抱える問題の一つだとは思います。 私も評価いらないですし、言ってることは同じですし、あちこち回答を飛んでコメント読むのも面倒なので、こちらに乗っからさせていただきます。 また長くなってしまい、すみません。 「ブルートフォース攻撃」については、解りにくいかもしれませんが、私の方でも書いてありますので、また不明な点があれば、続きはこちらで。 hojoさんは、LastPass、1Passwordなどパスワードマネージャーを利用した事はありますか? hojoさんの発想って、これなんですよね。 多分、ご本人も気づかれていないだろうなと思いながら、見てましたが。 完全に独立したクライアントアプリと、1WEBサービスの1機能という意味で、違いはありますが。 「使いまわされたパスワード」も、見方を変えて、一段レイヤーを上げれば、マスターパスワードなんですよね。 教科書的な考え方とは、違う発想ができるのは、とても素晴らしい事だと、私は思います。 私は、LastPassを利用しています。 他の方のコメントにあった " ただ、平文パスワードが長く複雑になるというメリットはある。全ユーザーに「長く複雑なパスワード生成器」と強制的に使わせているのと同じなので。 " LastPassのようなパスワードマネージャーには、まさにそのような事を自動でしてくれる機能がついています。中身の仕組みとしては、違いますが。 こんなニュースもありました。何か、似てると思いませんか? http://japan.cnet.com/news/business/35065969/ ご興味がおありでしたら、こういったのも調べてみてください。 https://twitter.com/ockeghem/status/780047115489685506 これも、つまりは「マスターパスワード」を突破されるという事ですよね。 世の中には、様々な認証方式、セキュリティ対策があります。 多分、hojoさんの知ってる範囲は、100あるうちの2~3くらいではないでしょうか。 他にどんな方法があるのか。調べてみてください。Passpackの話も出てきましたね。 裏側を詳しく知らなくても、ユーザー側からの視点で十分です。 こちらは、オンラインバンキング。 https://bizstation.bk.mufg.jp/service/ea.html 各サイトごとにID、パスワードを登録して、ユーザーがそれぞれを管理するなんていう方法は、今もうすでに、時代遅れになりつつあると思っています。 Slackの「Magic Link」 Yahoo Account Key なんてのも、出てきましたね。 OpenID SAML認証を使用したシングルサインオン も、今後どんどん増えていくでしょう。 hojoさんの言う " 今の方法で完璧だとは全く思っておりません。 より安全なパスワードの保存方法が存在するのであれば、そちらの方法を採用するべきだと思っています。 " 「今の方法」ではなく、「hojoさんが知ってる範囲の方法」です。 そんなに、いきり立つ必要はありません。 サーバー側で保存する方法だけでも、入門書に書いてある以外に様々あります。 サイト毎に、セキュリティに対しての格差があり、その格差が、どんどん広がっているのも事実ですが。 私も含めてですが、hojoさんの思いついた事は、遠い昔に先人たちが通ってきた道です。今回の案は、私も考え方としては、いいなと思っています。 もし興味があるようでしたら、そうした歴史を知る事から、まずは始めてみてください。 とても、長い道のりですが。 この先、どんなものが出てくるのか、そういったのは、とても面白いですよ。 その先で、セキュリティの専門家になり、新たな発想、発明があるかもしれませんね。 私の回答でも出てきました、日本には、徳丸浩先生というセキュリティの大家がおられます。名前は聞いた事があるのではないでしょうか。 そういった方を、ウォッチしているだけでも、大変勉強になりますよ。
kaz.Suenaga

2016/10/01 08:22

> packさん おっしゃっていることは一面の真実なんですが、もう一面の真実として、自分に合った良い師と巡り合う、ということもこういったQAサイトの醍醐味だと思いますよ。 技術的には同じことを説明されていても、自分の理解につながりやすい説明も、よくわからない説明もありますよね。 また、議論というか質問の深化をさせやすい方・やりにくい方もいらっしゃいます。 同様の回答が複数上がってしまうのは回答者側のエゴとして仕方がないところと思いますが、それぞれに対してコミュニケーションをとってみる、というのは、そのやり取りが重複したとしてもいい結果につながるかと思います。 できればそうやって並立した議論を、質問者さんがまとめて質問を追記・更新することで、後からの閲覧性が高まるといいですね。
hojo

2016/10/01 10:00 編集

未だにいろいろ整理がついてないのですが、皆さんの回答を読んで理解したことを質問にまとめさせていただきました。また、タイトルについても変更させていただきました。(まだ認識が足りないと思うのでもう一度読み直して追加しようと思います) また、以下ついて質問させていただいてもよろしいでしょうか? httpsを利用してクライアントサイドでパスワードのハッシュを生成し、サーバサイドでも「パスワードのハッシュ」のハッシュを作成してDBに保存することが、クライアントサイドでランダムパスワードを生成することと同じ意味になる理由がわかりません。 また、上記と同じ方法でサーバサイドでもクライアントサイドでもハッシュ化を行い、httpsを利用したWebサイトのクライアントでパスワードのハッシュを生成することは、元のパスワードを特定されないことの保証につながると思っていたのですが、こちらの認識が誤っているのか未だに認識できていません。(kazさんが「1つの解になります」とおっしゃっている様ですがこれは保証されるという意味で受け取っていいのでしょうか)
hojo

2016/10/01 09:45

また、オンラインではレインボーテーブルを利用したパスワードの特定が困難であることに対し、オフラインの場合は総当たりでの特定が可能になってしまうというような話があったと思いますが、こちらについてはオンラインの場合サーバサイドで生成したハッシュに関してはどういったアルゴリズムを利用してどのようなSalt文字列を使われているか調べる術がない上、複数回ログインを試みた場合にアカウントをロックまたは数分間のログインを禁止する仕組みが備わっていることが一般的なWebサービスのログインの仕組みになっているために総当たりができないという認識でよろしいでしょうか?
hojo

2016/10/01 09:56

もう一つ追加で質問なのですが「httpsを利用していれば通信経路から情報が漏れることはない」と決めつけた認識をしていたのですが、これについては誤りだったりするのでしょうか?
pack

2016/10/01 10:11

kazさんの回答にもありましたが、今回のhojoさんの追加対策では、どんな課題に対するものですか? 具体的な攻撃手法の話は、まずは置いておいた方が良さそうな気がします。 このクライアント側でのハッシュ化する方式を入れる事で、何が改善されると思いますか?
kaz.Suenaga

2016/10/01 11:42

> (kazさんが「1つの解になります」とおっしゃっている様ですがこれは保証されるという意味で受け取っていいのでしょうか) どこの範囲での保証かにもよるんですが、基本的に「保証」とまではいえません。 「保証」とまで言えるようなレベルに持ち込むには、元のパスワード文字列を画面上で入力させないところまでやらなければ難しいでしょう。 そのあたりを説明するには長くなりますので、私の回答の方に追記しておきます。
pack

2016/10/01 11:50 編集

多分、hojoさんは、kazさんの回答の一部だけ取り出して見ているように見受けられます。 私が、先ほどのと合わせて3つほど、質問をしますので、hojoさん、順番に答えてください。 そうすれば、kazさんの言っている事も、理解できるのではと思っています。 よろしくお願いします。
hojo

2016/10/01 21:00

質問に関してkazさんの回答欄の方に記載させていただきました!お付き合いいただき、本当にありがとうございます!
pack

2016/10/03 16:32 編集

こちらのコメントは、質問の整理ができて、みなさんからいただいた回答を十分に理解できた後に見てくださいね。 せっかくいただいた回答を、十分に咀嚼できていないまま、次々と議論を進めてしまっているように見受けられましたので、まずはそこに注力しましょう。 何度も言いますが、hojoさんの案を、全面的に否定している訳ではありません。 LastPassの話は、独立したネイティブアプリ(ブラウザ、サーバーとの連携はしていますが)と、hojoさんの1WEBサービスの1機能という意味で、大きな違いがあります。 もしかしたら、質問する場所を間違えたのかもしれません。 アプリ制作の方で質問したら、また違う議論になったかもしれません。 Windows、MacOS、iOS、Androidなど、ネイティブアプリの世界は、私も無知ですので、何か答えられる事はありません。 ネイティブアプリの世界では「はっ?何言ってんの?常識でしょ。帰んな」と一蹴されて、終わりかもしれません。 https://code.msdn.microsoft.com/windowsapps/NET45-WinRT-0652a18f http://michisugara.jp/archives/2013/ophcrack.html クライアントサーバモデルとは、違う世界の話です。 hojoさんの案は、これを、Webの世界、ブラウザで実行されるJavascriptに持ってこようとしたという話なんですよね? 大まかに見れば、やってる事は同じです。どこかの段階で、ハッシュ化して秘匿化してるという意味で。 最初のうち、クライアントだけという話になっていましたが、それは間違いだと気付きましたよね。DB側は必須ですね。 では、なぜクライアント側のJavascriptでやって無いのか?なぜ広まっていないのか?そもそも、できるのか? それを、hojoさんは聞きたかったんですよね? 少し確認してみましたが、私の環境(Windows)で、1passwordのChrome拡張をインストールして、実行してみました。 Chrome拡張は、HTML、CSS、Javascriptで出来ていますので、全てソースの中身を見る事が出来ます。 1passwordは、今まで使った事がありません。 すると、Chrome拡張は、このようなメッセージを返して、エラーとなります。 Looking for the 1Password helper The 1Password helper must be running for the extension to work properly. これは、つまりどういう事かというと、Windows版のデスクトップアプリを入れないと動かないという事です。 Chrome拡張単独で動いている訳ではなく、デスクトップアプリと連携して動いています。 競合となってる、LastPassも同じ仕組みと考えて、間違いないでしょう。 ちょっと1passwordのでは、処理名が判らなかったので探せませんでしたが、LastPassのChrome拡張のJavascriptでは、 AES.hex2bin(SHA256(f)) などの処理が書いてありました。 で、そのAESやSHA256が、Javascriptの他の箇所で定義などがされているかというと、そうではありませんでした。 つまりは、その辺りの処理は、helperを通して、デスクトップアプリが担当しているのではと想像できます。 たぶん、デスクトップアプリがハッシュ化して暗号化までしてくれてるのでしょう。そこまでしてから、ネットワークに流しているのではないかと。 ちょっとここは、私も十分に説明できないです。推測を含んでいます。 ブラウザのJavascriptエンジンだけで、出来てしまうのですかね? Passpackを利用されてるraccyさん、何かご存知でしたら、援護願いたいです。 iOSのクラッキングの話も出しましたが、多分この質問に対する落としどころは、こういったネイティブアプリとの違いではないかなと、私は思っています。
pack

2016/10/03 14:33 編集

原始的なクライアントサーバーモデルにおいては、クライアントはただの受付窓口ですからね。 そもそもクライアントでは、「処理」を行っていない。 要求を受け取って、サーバーに渡し、サーバーからの応答を返すだけ。 もっとも素に近いログインフォームというのは、HTMLであり、もっと言えば、プロンプトだけですから。 コンピュータの概念図に当てはめれば、入力装置であって、演算処理装置ではない。 最近でこそ、Javascriptで、バリデーションを掛けたりしますけど、「クライアントに処理を委譲する」という事は、その分セキュリティリスクにもなり得る訳ですよね。 バリデーションにしたって、クライアントでやったからと言って、サーバー側でのDB前でのチェックは、無くす事が出来る訳ではない。 今回の話は、それと同じだと思います。 場合によっては、処理機構を持たない事の方が、安全だったりするんですよね。 航空宇宙産業において、「枯れた技術」の方が重宝されるのも、似たような話かなと。 ブラウザ、OS、ネットワーク、メモリ、CPU、記憶装置、それぞれの中継装置において、「ほころびを見せないように」という、hojoさんの発想自体は、否定する所は無いかなと思っています。
pack

2016/10/03 14:10 編集

ちなみに、raccyさんもおっしゃっていた、SSHの鍵交換方式においては、サーバー側で生成した乱数のハッシュ値と、クライアント側で生成した乱数のハッシュ値の比較が行われており、この辺との比較も面白そうですね。 私もあと、SSLについても、もっときちんと理解しないといけないです。 kazさんのブログも、勉強になります。
zico_teratail

2016/10/04 04:11

みんな話が長い。長文過ぎる。 シンプルにストレッチング(クライアントで作ったハッシュをサーバでさらにハッシュ化)すれば、とりあえず質問者さんの抱えている心配は消えるでしょう。 あとraccyさんの「パスワードは使い回さないのが前提なんだから生パスワードが漏れても被害はそのサービスのみに限定される」というご意見は極論&理想論すぎます。実際はパスワードを使い回す人が多いのだから、ユーザに合わせて現実的な対策をすべき。
pack

2016/10/04 16:39 編集

> zico_teratailさん 度々の長文、失礼しました。 「セキュリティ」は、底なし沼ですからね。 迂闊に、そこに片足を突っ込んでしまった質問者さんも、簡単には抜け出せないでしょうね。 私も、素人で迷い込んでしまったんですけどね。
guest

0

クライアント側でハッシュ値を求めたとして、サーバー側のデータベースには何を格納するつもりでしょうか?クライアントから送られたハッシュ値をそのまま格納するのであれば、パスワードを平文で送って平文のままデータベースに格納するのと同じ脆弱性を抱えることになります。
クライアントから送られたハッシュ値をさらにハッシュ化して格納するのであれば、平文のままパスワードを送ってサーバー側でハッシュ化するのと同じです。

投稿2016/09/26 16:06

otn

総合スコア84529

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hojo

2016/09/30 23:22

クライアントサイドでパスワードのハッシュを生成し、サーバに送信した後サーバサイドにて再度「パスワードのハッシュのハッシュ」を生成してデータベースに保存した場合はどうでしょうか?
otn

2016/09/30 23:46

仕組み的には平文のままパスワードを送ってサーバー側でハッシュ化するのと同じことです。 単に平文パスワードが長く複雑になっただけと同等。 ただ、平文パスワードが長く複雑になるというメリットはある。全ユーザーに「長く複雑なパスワード生成器」と強制的に使わせているのと同じなので。
hojo

2016/10/01 03:01

「パスワード文字列をそのままサーバに送る」ことと「パスワードのハッシュをサーバに送る」という違いが「平文のままパスワードを送ってサーバー側でハッシュ化するのと同じ」ということについてもう少し意見をいただいてよろしいですか? 質問文にも記載しましたが「パスワード文字列をそのままサーバに送る」ということは「アプリケーションサーバにパスワード文字列が届く」ということになり、アプリケーションサーバが届いたパスワードを適切に抹消しなければ、パスワード文字列の漏洩を保証することは出来ないと思っています。 反面、クライアントでパスワードのハッシュを生成しパスワードのハッシュをアプリケーションサーバに送る方法をとれば、パスワード文字列の漏洩がなされないことを保証することができると思っています。 もちろん「クライアントがパスワードハッシュを送っているかわからないじゃないか」という意見もあると思うのですが、ブラウザの通信内容を確認すれば確認可能ですし、webサービスであればhtml,css,javascriptを開いてコードを確認することもできます。 そのため「平文のままパスワードを送ってサーバー側でハッシュ化するのと同じ」とは思えなかったのですがどうでしょうか。
pack

2016/10/01 07:04 編集

「責任が、どこにあるか」、ですね。 自社のサイトAのみに限定した場合、クライアント側でハッシュ化してようがしてまいが、通信途中で盗まれたとしたら、盗んだものをそのまま送れば、突破できる訳ですから。 その時点で、自社がすでにアウトです。 次に、サイトAでパスワードが漏えいして、他社サイトBで被害が出た時、その責任は、サイトBから見て、サイトAにありますか?ユーザーにありますか?サイトB自身ですか? サイトAから漏れた事を、サイトBは立証できますか? 結局は、パスワードを使いまわしたユーザーの責任です。 対策を怠った、サイトBにも責任はあります。
pack

2016/10/01 06:37

今回の策は、「自社を守る。自社のセキュリティを向上させる事に寄与していないのでは」という見方です。
pack

2016/10/01 06:57 編集

二段階認証などの対策は、自社で漏れても、仮に他社で使い回されてて、それが漏れて自社に持って来られても、対策出来るようにそれぞれのサイトが力を入れて、頑張ってる訳です。 他のサイトに文句を言った所で、誰も保証してくれません。 ユーザーの自己責任と突っぱねていては、信用されません。 自社は、自社で守る。その為の施策に全力を注ぐべきです。
otn

2016/10/01 12:01

「パスワードを平文で送ると漏れないか心配」ということですが、「ハッシュ化したパスワード」を「パスワード*」と呼ぶことにすれば、「パスワード*を平文で送るので、パスワード*が漏れないか心配」ということになりますよ。正しいパスワード*をサーバーに送れば認証されるので、パスワード*が漏れると大変ですよ。 「パスワード」は漏れては駄目だが、「パスワード*」はいくら漏れてもかまわないと思っているのなら間違いです。
zico_teratail

2016/10/04 04:16

>平文のままパスワードを送ってサーバー側でハッシュ化するのと同じ 同じではないですね。 「GETやPOSTに対するログを取るように設定されていた場合」の心配をひとつ減らせるのだから。 ただしpackさんのご意見は現実的で傾聴に値します。
guest

0

そのため、クライアントサイドでSHA256によるパスワード暗号化を行った上でサーバサイドにパスワードを送る方法をとったほうがユーザにパスワードの安全性を保証することができるのではないですか?

この考え方は正しいですか?

端的に言うと間違っています。SSL/TLSの話ではないと思っているのであればなおさら間違いです。

パスワードを保存する際に、

  • クライアントサイドでパスワードをハッシュ
  • 通信経路上をハッシュがそのまま通過
  • サーバサイドで受け取ったハッシュをそのまま認証に利用

となるわけで、通信経路上の盗聴を行うことで、ハッシュアルゴリズムも何も関係なく「そのハッシュ」を奪取すれば良いことになり、事実上、平文のパスワードをネットワーク上を流し平文を保存しているのと同義になります。


セキュリティを考慮する場合、「安全」と言っても「何に対するどういう安全か」を1つ1つ定義して、それに対してどのような対策をとるかを検討する必要があります。

質問者さんがおっしゃっている「サーバサイドでどう管理されているかわからないし、どう漏洩するかもわからない」というのであれば、そもそもそのサービスを利用することをやめるべきでしょう。

一般に、

SSL/TLSを利用することで

  • 通信経路上を流す通信の暗号化
  • 通信の相手の真性の担保

サーバサイドで暗号化した状態で保存することで

  • 漏洩時の解読の難易度を高める

異なるサービス間で同じパスワードを使いまわさないことで

  • 漏洩時の被害範囲の縮小

といった安全を得ることができます。

現状の質問をみると、漠然と不安がある、といった状況と大差なくみえます。
少し攻撃者側の手法を知ったうえで、それに対してどの部分のどういった安全をどう担保するか、といった視点で検討してみてはいかがでしょうか。


■ 2016.10.01. 17時過ぎの追記

守る対象を

  • パスワードとした元の文字列
  • サービスの利用にあたっての本人確認に利用される情報

どちらと考えるかで、対処は変わってきますね。

パスワードとした元の文字列の保護が課題の場合

質問者さんがおっしゃるように、通信経路上をそのまま流れることを避けることが優先事項となりますね。
クライアントサイドでハッシュ(もしくは何らかの対応付けされる文字列でいいわけですが)生成の上で、通信経路をそのハッシュ文字列を流す、というのは1つの解になります。

この観点でこの手法は、パスワードマネージャ等のソフトウェアを使って各アカウントのパスワードをランダム発行し管理するモデルとそう変わらない手法とも言えます。
パスワードマネージャの管理パスワードが「元のパスワード」と考えられます。
通信経路上を流れる文字列はそのサービスでしか利用していない、しかも何らかの計算ロジックに基づかないランダムな文字列なので、元のパスワード文字列は保護されます。

しかしこの場合、クライアントサイドでどう入力するかにかかわらず、通信経路上にその「ハッシュ文字列」を流せさえすればそのサービスのアカウントとしてはなりすましができることになります。
「本人確認に利用される情報」が「パスワード文字列」から「ハッシュ文字列」に置き換わっただけで、サービス側がその「ハッシュ文字列」を使える人はそのアカウントの利用者と解釈するわけです。

この手法によって安全性が向上する可能性を見込めるのは、

  • 複数のサービスで同一のパスワードを使いまわしている状況

のみです。
つまり、課題が「パスワードに入力した文字列をどこでハッシュするか」ではなく「複数のサービスで同一のパスワードを使うことを避ける」ということに置き換わります。

サービスの利用にあたっての本人確認に利用される情報の場合

本来サービス提供者が考えるべき保護の対象はこちらになってきます。
すると、まず第一に出てくる検討課題は「何をもって認証とするか」になります。

  • パスワード認証
    • 多元要素認証(ワンタイムパスワード的なものを含む)
  • コールバック認証
  • クライアント証明書による認証

など、様々な認証手法が候補になります。

これらの中でパスワード認証は、暗号化における共通鍵のように「サーバサイド、クライアントサイドで同一の認証情報を持ち、その一致をもって認証とする」手法です。
その時点で、その認証情報(つまりパスワード)とその伝送手段は、サーバサイド、クライアントサイドそれぞれで秘匿すべき情報になります。
言い方を変えると、サーバサイド、クライアントサイドそれぞれの認証情報の保護を疑うことを前提にした場合、パスワード認証では認証として充分と言えません。

そこを疑う場合は認証手法の変更を検討すべきです。

その他、コメント内へのコメント

ただ、少なくともクライアント側でパスワードをハッシュ化していれば「元のパスワード文字列がこのサービスから漏洩することはない」ということは保証できるのではないでしょうか?

これは上で説明したあたりですね。

(もしかしたらハッシュから元の文字列を復元する方法などがあるのかもしれませんが、もしそのようなものをご存知でしたら是非教えていただきたいです!)

これは他の方もどこかで触れていましたが、要するに総当たりで解析することをいかに効率よくやるか、という課題で、レインボーテーブルなどの手法を利用することで効率よく元の文字列を見つけ出すといった手法が作られています。

また、攻撃者の視点に立つと「特定の人物に成りすましたい」という場合よりも「誰でもいいからのっとれるアカウントを探す」という場合が多いので、ハッシュから元のパスワードを導くよりも、既にわかっているパスワードとハッシュの組み合わせに一致する文字列を使っているユーザーを探し出す、ということになるでしょう。
もっともこの場合も、いちいちハッシュからの一致を見つけ出すよりも、特定のよくあるパスワードを入力して、アカウント側をリストに沿って入力していく、というリバースブルートフォースと呼ばれる手法をとる方が現在は主流でしょう。
参考) http://securityblog.jp/words/reverse_brute_force_attack.html

このあたり、他の方もおっしゃっていましたが徳丸さんという方が非常に多くの情報をWeb上に残しておられますので検索してみるといいかと思います。
また、 体系的に学ぶ 安全なWebアプリケーションの作り方 という本を書かれていますので、こちらはこの件に関わらず必読かと思います。

おまけ

なんとなく、SSL/TLSについて、どのような手法なのかを理解されていない部分があるのかなと感じます。
SSL/TLSで利用している通信経路の暗号化、という部分は、質問者さんがおっしゃっている通信経路上をテキストが流れる際の充分な保護になります。
つまり、適正なSSL/TLSサーバ証明書が利用されていれば、入力ポイントからサーバに到着するまでの通信内容は保護されます。
つまり、パスワード文字列を入力し、流すことを安全にできます。
サーバサイドで受け取ったそのパスワード文字列を、そのままDBに保存するのであればパスワード文字列の漏洩につながりますが、ハッシュを保存するのであればサーバ上に素のパスワード文字列が残ることはありません。

つまり、

  • パスワードは暗号(ハッシュ)化してDBに保存しています

というのが

「われわれはこのようなセキュリティ対策を行っているので安心して利用できます」と主張する

ことそのものになります。

SSL/TLSについては以前 自分のブログ で数ページまとめたことがありますので、よろしければそちらをご覧ください。


■ 2016.10.01. 21時過ぎの追記

raccy さんの回答のコメント欄からの派生です。

(kazさんが「1つの解になります」とおっしゃっている様ですがこれは保証されるという意味で受け取っていいのでしょうか)

どこの範囲での保証かにもよるんですが、基本的に「保証」とまではいえません。
「保証」とまで言えるようなレベルに持ち込むには、元のパスワード文字列を画面上で入力させないところまでやらなければ難しいでしょう。

この続きです。

SSL/TLSの経路保護等、別の疑問も生まれてきているようですが、一旦そちらまで考え始めると混乱しかしないと思いますので、「クライアントサイドでハッシュすること」にテーマを絞ります。

画面上でパスワード文字列を入力すること自体で発生するリスク

Webシステムを前提とした場合、XSSなどの攻撃手法を利用することにより認証のためのサーバへの通信を発生させる前に画面上に入力された文字列を奪取し攻撃者のサイトにそのデータを送り込むことが可能です。

また、クライアントサイドのPCのセキュリティ状態まで考慮に入れれば、どのような画面設計、通信仕様にしたところで、なんらかの箇所で入力が発生しさえすれば、元の文字列の奪取は可能でしょう。
※キーロガー、とかを調べるとわかるかと思います。

というように、保護対象をある程度限定しないとこの議論はその箇所に影響する別の要素を持ち込むことでセキュリティの綻びが発生しうるため、その箇所だけで納得いく回答を得るのはなかなか困難かと思います。

立場をサービス提供サイドと特定し、ユーザーサイドのPC環境は安全と仮定したうえで、クライアントサイドでハッシュ処理を行うことは、元のパスワード文字列を受け取らないという意味で、保護している、と言えるとまでは言えると思います。

サービスの認証情報の保護という観点ではリスクが増すともいえるかも

ここまでは「パスワード文字列の保護」についてでしたが、ここからは「サービスの認証情報の保護」の観点で考えます。

仮にこのサービスで利用されているパスワードが他サービスで使いまわされているパスワードで、その他サービスで漏洩した場合、そのパスワードを利用してこのサービスのパスワード入力画面に打ち込めばなりすましログインが可能になることを考えると、なりすましに利用できる文字列の可能性が

  • ハッシュ:漏洩の危険度は低い
  • パスワード:漏洩の危険度は(他サービスも含めることで)高い

という2種類となることで、トータルでの危険度は増している(ハッシュの漏洩によりなりすませる分)、とも考えられます。

  • 元のパスワードをハッシュするロジックは公開されている(クライアントサイドでやるということはそういうことになります)
  • サーバに送り込むべき文字列はハッシュ

ということは、元のパスワード、ハッシュのいずれかがわかればいい、ということになることはご理解いただけますか。

その他、全体的な整理

パスワードをクライアントサイドでハッシュし、サーバサイドにはそのハッシュを送るとした場合、サーバサイドでは「ハッシュ」こそがそのユーザーの「認証情報」として扱われる。

  • つまりこれは、「通常のパスワードよりも長くランダムな文字列をパスワードとして設定した」ことと同義となる。
  • 同じ前提で、通信経路という観点でみれば、通信経路を流れるハッシュがわかれば認証できる、ということになる。

これで「よし」の場合

  • サーバサイドでのそのハッシュ方法などとは関係なく、「通信経路上を元のパスワード文字列を流さないこと」が課題だったことになる。
  • それであれば、パスワードマネージャなどを利用し、使いまわしたりせずにサイトごとに長いランダムなパスワードを生成したものをパスワードとして設定するのと同義。
  • ただしこの場合は「ユーザーサイドのパスワード管理の問題」となるため、サービス提供サイドの技術要件としてフォローする箇所は少ない。
    ※なくはない。パスワード要件として充分に長い文字列を設定可能とする、など。

そうではなく「認証情報の保護」が課題だった場合

  • クライアントサイドでハッシュすることによって見込める認証情報の保護レベルの向上はほぼない。
  • サーバサイドでDB等に認証情報を格納する際、受け取ったハッシュをさらにハッシュして保存するなどすることでより安全に保存することはできますが、これは「平文のパスワードをハッシュして保存するとより安全」というのと同義。
  • 元のパスワード文字列の漏洩を気にするのであれば、使いまわさないなど別のレイヤーでの対応が必要。

→ おそらく、課題設定とその対策が一致していない。

投稿2016/09/28 13:43

編集2016/10/01 12:23
kaz.Suenaga

総合スコア2037

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hojo

2016/10/01 02:19 編集

質問の追記に記載したのですが「SSLによる暗号化通信を前提としたWebサービス」での話となっております。しかし「クライアントサイドで作成したハッシュをサーバに送る手法は、平文のパスワードをネットワーク上を流し平文を保存しているのと同義になります。」という点については正しく認識していなかったので新しい発見につながりました。ありがとうございます! もちろん『「サーバサイドでどう管理されているかわからないし、どう漏洩するかもわからない」というのであれば、そもそもそのサービスを利用することをやめるべきでしょう。』というのはごもっともだと思います。 サービスを利用するということは、そのサービスの運営や企業を信頼するということになる側面は必ず存在すると思います。 しかし、クライアント、サーバ間においてのデータの扱いにおいてより信頼できる方法を取っているサービスが存在する場合、その信頼は「根拠ある信頼」になるため、違った意味を持つと個人的に思っています。 もちろん、ブラウザがサーバに対してどのようなデータを送信しているのかまで調べてサービスを利用する人は少ないと思います。しかし、たとえ調べる人がいなくても、企業がユーザに対して「われわれはこのようなセキュリティ対策を行っているので安心して利用できます」と主張することはできると思います。もちろん確認することができない部分についてのセキュリティに関しては信頼するしかないのですが...。 ただ、少なくともクライアント側でパスワードをハッシュ化していれば「元のパスワード文字列がこのサービスから漏洩することはない」ということは保証できるのではないでしょうか?(もしかしたらハッシュから元の文字列を復元する方法などがあるのかもしれませんが、もしそのようなものをご存知でしたら是非教えていただきたいです!) もちろん、「元のパスワード文字列がこのサービスから漏洩することはない」ということが保証されたとしても、そのハッシュが漏れることによってなりすましが可能になってしまうのであればその他の問題が出てきますので、今の方法で完璧だとは全く思っておりません。 より安全なパスワードの保存方法が存在するのであれば、そちらの方法を採用するべきだと思っています。 回答に対する返信が「追加の質問」ではなく「感想的」になってしまって申し訳ございません。今回この質問を投稿してから「パスワードの保存方法とセキュリティに関して想像以上に複雑だった」ということがわかりました。 様々なユーザ様から返答をいただいておりますので質問は引き続き続行しますが 何か気になる点がございましたらご指摘お願いいたします。
pack

2016/10/01 07:54

" クライアント側でパスワードをハッシュ化していれば「元のパスワード文字列がこのサービスから漏洩することはない」ということは保証できる " これを言おうとすると、その前には、「仮に、途中経路でハッシュ値が漏れた場合に」が付きますよね。 「途中経路でハッシュ値が漏れた」それが起きてる時点で、すでにアウトなんです。 クライアントを偽装して、同じ値を送れば、自社を突破されてしまいますから。 「途中のハッシュ値が漏れても、すぐに不正ログインは起きません」まで言えれば、信頼向上につながりますが、今回の策では言えないですよね。
pack

2016/10/01 08:02

「うちの銀行は、預金を泥棒に盗まれても安心ですよ。万が一盗まれたとしても、あなたがよその銀行に預けてる預金は安全ですから」と言われても、「ダメじゃん」ってなりますよね。
kaz.Suenaga

2016/10/01 08:05

ちょっと返答が長くなったので、回答に追記しますね。
kaz.Suenaga

2016/10/01 08:14

> pack さん おっしゃるとおり、トータルでセキュリティを考えた場合、どこかにほころびがあればすべて崩壊するものですね。 そのため、セキュリティの議論をする場合には常に「保護対象は何か」を起点にしないと議論が発散してしまいます。 今私が追記した回答もそうですが、大抵の場合その保護対象を明確にした時に課題そのものの認識が変化することになります。 - 保護対象は何か - その保護対象は誰が(どこが)保護すべきものなのか - どのようなリスクがあるのか - そのリスクに対する保護手法を検討した場合、何がその手法を無効化する要素なのか といった構造的、段階的な掘り起しが必要になりますね。 その議論をせずに結果だけ出すのであれば確かに「ダメじゃん」で終われるのですが、それだと「そもそも間違った課題」であることに気づけずに終わってしまうので、いろいろ前提をつけてあげるのがいいかもしれませんね。
pack

2016/10/01 12:35

> kazさん hojoさんに下記のような、質問をして、順番に答えてもらえればと思ったのですが、どうでしょう? kazさんのおっしゃっている、「課題」が明確になるのではと。 ここで、hojoさん戻ってくるの待ってるのもキツイので、何かいい方法があるといいのですが。 質問1. このクライアント側でのハッシュ化する方式を入れる事で、何が改善されると思いますか? 質問2. hojoさんのサイト自身に対しては、何か効果は見込めますか? 質問3. 私packは、hojoさんと、kazさんの二つのサイトを利用しています。 管理が面倒なので、二つのサイトで、共通のIDパスワードを利用しています。 kazさんのサイトは、セキュリティがズブズブで、SSLも利用しておらず、DBに生パスワードを保存しておりました。 どうやら、kazさんのサイトから、アカウント情報が漏れたようです。 hojoさんのサイトに不正ログインされないか心配です。 そのクライアントでのハッシュ化は、そのような不正ログインに対する有効性がありますか? 質問4. 私packは、SNS依存症で、10以上のサイトに登録しています。 hojoさんのサイトで、そのような対策がされているという事は、hojoさんのサイトで使ったパスワードを使い回しても、大丈夫という事でしょうか? 質問5. では私は、どうすれば、よろしいでしょうか? A.「パスワード使いまわさないでください」 がkazさんのいう 課題が「パスワードに入力した文字列をどこでハッシュするか」ではなく「複数のサービスで同一のパスワードを使うことを避ける」ということに置き換わります。 という事ですよね?
kaz.Suenaga

2016/10/01 12:42

> packさん はい、おっしゃってることで合っています。 こういった「質問」は思考プロセスになるので、非常にいい聞き方ですね。 質問1~5をたどったうえで、再度質問1・2を考えてみてもらえるとよさそうです。 この手は、先に次の質問が見えてしまっていると思考がゆがむので、本当は小出しに出したいところですが、そこまでの手間をかけるのもなかなかつらいですよね^^;
pack

2016/10/01 12:44

そうなんです。 小出しにしようと思いましたが、いかんせん、このシステムでは…
hojo

2016/10/01 20:54

お付き合いいただき有難うございます。質問の回答をさせていただきますね! 質問1. このクライアント側でのハッシュ化する方式を入れる事で、何が改善されると思いますか? 回答: Webサービスを作った人が、このサービスからパスワード文字列が漏れることはないとユーザに保証することができる...。と思っていました。しかし皆さんの意見をまとめるとDBから漏洩したパスワードのハッシュを手に入れたクラッカーは、レインボーテーブルという手法を使うことでパスワード文字列を解析可能ということなので、今では間違っていたのかもしれないと思い始めています。(この認識であってますか?正しければ正しい、間違っていたらどこが間違っているかしてきいただきたいです。)また、補足として、DBから情報が漏れたということはパスワードのハッシュ以外の情報も漏れている可能性が高いため、パスワードのハッシュよりも重要なデータが漏れた場合のことも考えると話のややこしさが増してしまうので、漏らしてはならないデータを持ち合わせないwebサービスに限定した場合の回答ということにさせていただきます。 質問2. hojoさんのサイト自身に対しては、何か効果は見込めますか? 回答: 上記の回答と同じにはなるのですが「パスワード文字列が漏れることはない」とユーザに保証することができること思っています。また、アプリケーションサーバで動いているプログラムを保守している人間がパスワード文字列を直接扱うことがなくなるため、セキュリティリスク(いちいち「パスワードをログに保存してたりしないよね?」などの確認をしなくて良くなる)を抑える事ができると思っています。また、パスワードを直接アプリケーションサーバに送る方法をとった場合、クラッカーが何らかの手法を使ってアプリケーションサーバのメモリ内部を監視するような事があった場合に(そんな事ができるかわかりませんが)アプリケーションサーバにパスワード文字列が直接届いていると、アプリケーションが一時的にパスワードをメモリに格納するため、そこから情報漏洩してしまうということも考えられるのかな?と思いました。パスワードのハッシュを生成してからサーバに送るような手法を取っていれば漏れてしまったとしてもそれはパスワードのハッシュなのでそのようなありとあらゆる問題について検証すべき項目が減少すると思っています。 質問3. 私packは、hojoさんと、kazさんの二つのサイトを利用していま...(略 回答: 正直なところ、この問題については対処不能だと思っています。クライアントサイドでのハッシュ化は何の意味もありません。そのため「異なるサイトで同じIDとパスワードを利用するユーザに責任がある」ということは納得しているので、このような事態が発生した場合にhojoのサイトが責められることはないと思っています。しかし、銀行のような一般的なwebサービスよりもセキュリティを重視しなければならないシステムの場合には責任を問われ、会社の信用を落とすようなことがあるのかもしれません。そのようなサービスを私が作っていた場合には多段認証などのシステムを導入したりする必要があるのかもしれません...と思っています。(ツッコミどころがあったら指摘をお願いします!) 質問4. 私packは、SNS依存症で、10以上のサイトに登録していま...(略 回答: 質問3の回答でも述べた通り「異なるサイトで同じIDとパスワードを利用するユーザに責任がある」ため、パスワード使い回しによる被害は自己責任だと思っています。しかし、Webサービスによっては被害が第三者に及ぶ可能性があるため、そういったサービズについてはやはり多段認証やその他のシステムを導入するべきだと思っています。 質問5. では私は、どうすれば、よろしいでしょうか? 回答: 未だに理解できないことがあります。packさんやその他の回答者さんにお聞きしたいのですが、httpsを利用してクライアントサイドでパスワードのハッシュを生成し、サーバサイドにて再び「パスワードのハッシュ」のハッシュを作成してDBに保存するという手法をとった場合、クライアントサイドでのハッシュ生成がランダムパスワードを生成することと同じ意味になる理由が未だにわかりません。私は、クライアントサイドでのハッシュ生成は質問2の回答のメリットが得られると思っています。クライアントサイドで生成したハッシュをそのままDBに保存することが危険であるということは認識しました。そのため、今ではクライアントサイドとサーバサイドの両方でハッシュを生成するのが良いのではないか?と考えています。というわけでpackさんがどうすれば良いか、どうしてもらいたいかの回答は「クライアントサイドでパスワードのハッシュを生成し、サーバに送った後、サーバサイドにてパスワードのハッシュのハッシュを生成してDBに保存することは、サーバサイドにパスワード文字列を直接送ってもらい、ハッシュを生成してDBに保存することに比べて、前者にメリットがない理由を教えていただきたい」になります。
pack

2016/10/01 23:44

> hojoさん、回答ありがとうございます。 5つの質問に対する答えを、まずは順番に明確にしていきましょう。 他の回答者さんにもいろいろ聞きたい事があると思いますが、ちょっとだけ我慢してくださいね。 kazさんの言うように、「議論が発散してしまいます」ので。 まず、答えを考えるにあたって - 保護対象は何か - その保護対象は誰が(どこが)保護すべきものなのか の部分を意識するといいと思います。 - どのようなリスクがあるのか - そのリスクに対する保護手法を検討した場合、何がその手法を無効化する要素なのか は、今はまだ置いておきましょう。 質問1、質問2は、後にしましょうか。 質問3、質問4は、明確な答えですね。とてもよく理解されてると思います。 異論はありません。 質問4を、もう少しだけ、突っ込んでみますが、 「そういったサービズについてはやはり多段認証やその他のシステムを導入するべきだと思っています。」 これは、おっしゃる通りですね。 では、多段認証やその他のシステム(クライアント証明書など)を導入しているサイトだけを利用するならば、パスワードを使い回してもいいと思いますか?
hojo

2016/10/02 00:25 編集

クライアント証明書を導入とは、信頼ある認証局から発行されたSSL/TLSを利用したhttpsプロトコルの利用をしたwebサービスの場合ということですか? それとも、ユーザ登録完了後にwebサービスから発行された秘密鍵をユーザがブラウザに設定することでサービスにアクセスできるようなセキュリティを導入したwebサービスということでしょうか? 前者の場合は結局質問3、4と同じだと思っています。 後者の場合は、秘密鍵を持っているユーザしかwebサービスにアクセスできないため、秘密鍵の管理をユーザがしっかりしていればパスワードは使い回してもいいと思っています。 もちろんなるべく同じパスワードは使うべきではないですが、kazさんのサイトから漏洩したパスワードと同じものを利用していたとしてもユーザが管理している秘密鍵のファイル自体が漏洩無ければサービスにはアクセスできないのでそういった意味で使い回しても良いと思っています。 しかし、使い回していいというのは「ユーザがそのリスクを把握した上ですればいい」ということであり、多段認証やその他クライアント証明書などのシステムを導入していたとしても僕だったら同じパスワードは利用しません。なぜなら、多段認証やその他クライアント証明書などのシステムが存在していることは、パスワードによる認証に加えてプラスされたセキュリティという認識になりますので、パスワードを使い回してしまったらその2重のセキュリティの1つが突破されてしまうということになります。 突破されたとしても多段認証やクライアント証明書のシステムによって守られたじゃないか。それでいいじゃないかと思う人は使い回せばいいと思いますし、パスワード認証が突破されたことに対して恐怖するユーザは、やはり使い回すべきではないと思っています。
pack

2016/10/02 00:22

後者です。 「使い回してもいいのではないか?(もちろんなるべく同じものを使うべきではないが)」 そうですね。確率的な話になってきますね。 0か1ではない。ただ多段認証などが導入されている場合、パスワードを使い回しをしていなければ、一段目で弾ける訳ですから、ぐっと確率が下がるというのは、解りますよね? 質問3からは、「パスワードを使い回しており、他のサイトで漏れた場合、この方式ではそれに対抗する有効性は無い。」という結論ですね。 質問4からは、「多段認証などは有効性があるが、それらが導入されていない場合、この方式を使ったとしても、パスワードを使い回していい事にはならない」という結論ですね。 ここまでは、どうですか?
hojo

2016/10/02 00:37 編集

投稿編集中にpackさんの返信があったので驚きました! その通りですね!「多段認証などは有効性があるが、それらが導入されていない場合、この方式を使ったとしても、パスワードを使い回していい事にはならない」に関してももちろん納得できる話です。 しかし、我々がいくら「パスワードを使い回してはならない」と訴えかけたところで同じパスワードを使い回すユーザ半数以上なのではないでしょうか?
pack

2016/10/02 01:03

そうですね。それが 質問5. では私は、どうすれば、よろしいでしょうか? になるのですが。 質問3、質問4を踏まえて、多段認証なんかやってられっかという面倒くさがりやのユーザーpackに対して、サイト運営者hojoさんはどんな回答をしますか? いいですよ。 教科書的な答えでも。 hojoさんのサイトの宣伝文句的な言葉でも。
hojo

2016/10/02 01:14

パスワードの使い回しによるパスワードのセキュリティの話から、今は多段認証などによるセキュリティの話へ切り替わっているという認識でよろしいですか? もし「多段認証なんかやってられっかという面倒くさがりやのユーザー」が目の前にいたとしたら、私は「多段認証は設定された方が良いですが、パスワードに単純な単語などは使用せず英数記号8桁以上で他のサイトで利用していないパスワードを使ってくださいね」というと思います。
pack

2016/10/02 02:09 編集

パスワードの話も、含んでいます。 そういったユルいユーザーの認識に対して、どう回答するか、ですので。 おっしゃるように、 「多段認証、面倒くさい」⇒「使った方がいいですよ」 「パスワード覚えられないので、短い方がいい」⇒「長くて、いろんな文字使った方が安全ですよ」 「いくつも管理できないので、使い回したい」⇒「使い回しはダメです」 となりますよね。 質問5の結論としては、これで明確になりましたね。 hojoさんの言葉が、そのまま結論です。 先ほどの 「hojoさんのサイトの宣伝文句的な言葉」というのは、実は質問1の方に戻るんです。 質問3、質問4、質問5を踏まえて、改めて質問1はどう回答しますか? 攻撃手法の話は、まずは置いておいて。 質問1. このクライアント側でのハッシュ化する方式を入れる事で、何が改善されると思いますか? kazさんの言葉を借りれば、何を「保護対象」としていますか?
hojo

2016/10/02 06:54

攻撃手法の話は置いといて改めて質問1をどう思うか、ですか。 うーん、特に変わらないと思ってしまうのは、何か僕が重要な見落としをしてしまっているということなのでしょうか。 ・多段認証は設定したほうがいい ・パスワードはなるべく長く英数記号を使った方がいい ・パスワードの使い回しはしない方がいい ということはごもっともですし納得しています。 しかし、これらが『クライアント側でパスワードのハッシュを生成することでユーザに「パスワード文字列がこのサイトから漏れる心配はない」と保証できる』ことにはならないということに繋が李ませんでした。 もう少しヒントを頂けないでしょうか。
hojo

2016/10/02 06:58

わかったかもしれないです。 安全なパスワードの基準の中に「パスワードを使い回してはならない」というものがあるため「パスワード文字列がサイトから漏れない」と主張したところでこのルールを守ってる人からすると「いや、パスワードって使い回すもんじゃないからw 俺のパスワード漏れたとしても何も問題ないから!」とツッコミを受けるということですかね?
pack

2016/10/02 09:29

『クライアント側でパスワードのハッシュを生成することでユーザに「パスワード文字列がこのサイトから漏れる心配はない」と保証できる』 の中に一つ、「保護対象は何か?」に対する答えを含んでいますね。 解りますか? 質問1の意味として、「課題」⇒「対策」⇒「結果」があると思っています。 今回の対策は、何を保護しようとしているものですか? 保証できる、できない、の話は攻撃手法の話になってくるので、そこは置いておきましょう。
pack

2016/10/02 09:33

この質問に対して、今までの議論関係なく、hojoさんが当初この質問を立てた時に考えた事を、そのまま答えていただければ、いいと思います。
hojo

2016/10/02 11:39

保護対象という言葉をどう受け取ればいいのかわからないのですが思ったことを書いてみます。 まずはサービスの安全性が高まるのではないでしょうか?これを「サービスの保護」や「企業の保護」と表現していいのかわかりませんが先日発覚したDropboxのアカウント情報漏洩(http://gigazine.net/news/20160901-60-million-dropbox-account-stole/)でもこの事件に関してメディアの専門家(?)が「ハッカーもこのハッシュ化されたデータから実際のパスワードを入手することは困難だろう」と述べていたりするようです。 Dropboxはサーバサイドでハッシュを生成しているかもしれませんが、もしクライアントサイドでもハッシュの生成を行っているサービスが存在した場合、「パスワード文字列がこのサイトから漏れる心配はない」とユーザに堂々と言えることになります。なぜならサーバはパスワード文字列を受け取らないからです。そのためクライアントサイドでのハッシュ生成はユーザに安心感を与える事に繋がるのでは?と思ってしまします。 もちろん、XSSなどの脆弱性を孕んでいた場合、ユーザが入力したパスワードをJavascriptで盗聴するというようなことができると思われるので、XSS脆弱性を含んでいないことが前提にはなりますが、「パスワード文字列を直接サーバは受け取らない」という文言にはユーザに安心感を与える説得力のある言葉だと思ってしまいます。 また、何を保護しようとしているのか?について加えさせていただくと「ユーザのパスワード文字列が保護」されていると思います。 もちろん、パスワードは使い回すものではないかもしれません。しかしパスワードを使いまわしている人は多いです。「常識的に考えてパスワード使い回す方が悪い」と割り切って考えた方が良いのかもしれないですが、僕としてはパスワードを使いまわしている人が多い以上、可能であればパスワード文字列を漏らさないように設計し、ユーザを安心させるべきと思ってしまいます。(もちろん他社サイトから漏れたパスワードを使われたら被害を受けるのは自社のサービスになりますが、自社は被害者であるという主張はある程度まかり通るのではないでしょうか?(通らないですかね汗)) ほぼ高確率で、自分の考えがおかしいのは自覚しているのですが、未だにしっかりとした理解ができていないので、ぜひご指摘していただければと思います。
pack

2016/10/02 22:56 編集

hojoさんの案を、全面的に否定している訳ではありません。 「自分の考えがおかしいのは自覚している」。私は、そうは思っていません。 質問1、質問2をまずは、明確にしましょう。 何を保護しようとしているのか?について加えさせていただくと「ユーザのパスワード文字列が保護」されていると思います。 そうですね。そこは明確に出来ましたね。 どんな場合に、どんな有効性が見込めるのか、私も、kazさんも同じように書いています。 見つけられますか? 「その対策に対して、こんな攻撃手法があり有効性には疑問がある」という話になると、また確率的な話になってくるので、それは置いておきましょう。
pack

2016/10/02 14:47

質問2について先に言っておきますが、最初に答えていただいた通り「クラッカーが何らかの手法を使って」盗んだ後の話ですね。 それが、パスワードのままの場合と、ハッシュ化していた場合、何か有効性の違いがあるのか。 この話は、何度も出てきたと思いますが、そこで他社の話に持って行くと、また話が逸れます。それは質問1の方になります。 質問2は、「hojoさんのサイト自身に対して」の話です。そこに集中してください。 そこの区分けを明確にするための質問です。 いろいろ主張したい事があるのは解りますが、もう少し我慢してください。
pack

2016/10/02 22:49 編集

質問1については 「課題:」 「対策:」 「結果(見込み):」 で書くといいと思います。それぞれ、一行ずつくらいで書けるのではないでしょうか。 質問2は、世の中に、hojoさんのサイトのみが存在し、「パスワード使い回し」という問題が存在しない世界で考えてみるといいかもしれませんね。 そこでも、ユーザーは多数おりますので、IDパスワードは必要になります。
hojo

2016/10/02 18:27 編集

質問1. このクライアント側でのハッシュ化する方式を入れる事で、何が改善されると思いますか? 課題: 当Webサービスがパスワード文字列の漏洩が起こる可能性を持ち合わせていると、当Webサービスの利用ユーザを不安にさせることにつながる。なぜならパスワード文字列が他者に漏洩すると、そのパスワード文字列を手に入れた加害者が被害者になりすましてWebサービスを利用できるからである。また、被害者が同じパスワード文字列をその他のWebサービスで使いまわしていた場合、被害者は加害者によって当サイト以外のWebサービスでも同様の被害を受ける可能性がある。 対策: 当Webサービスから当Webサービスを利用するユーザのパスワード文字列を漏洩しないようにする。クライアント側によるパスワード文字列のハッシュの生成をすることでWebサーバはパスワード文字列を直接受け取らない形になる。Webサーバはパスワード文字列を受け取らないため、Webサーバからパスワード文字列が漏洩する可能性を防ぐことができる。 結果: 当WebサービスからWebサービスを利用するユーザのパスワード文字列が漏洩することはないので、当Webサービスを利用するユーザは安心して当Webサービスを利用することができる。
pack

2016/10/02 22:57 編集

まずは、これまでのいただいた回答を、きちんと理解する事に注力してください。
pack

2016/10/02 18:30

「不安にさせる」 「漏洩しないようにする」 「安心して」 そういった抽象的な言葉は、使わない方がいいと思います。 もっと、明確に。 あと、みなさんそれなりに解ってる方達なので、あまり細かい説明もいらないです。 もっと、手短に。
hojo

2016/10/02 18:35 編集

うーん、抽象的な言葉は使わないほうがいいのに手軽に書くんですか? どうすればいいかわからなくなってきました。 一度休憩して、もう一度先ほど記載した文章の中から「不安」「漏洩しないようにする」「安心」という言葉を掘り下げてみます。
pack

2016/10/02 18:51

例えば、対策も 「クライアント側によるパスワード文字列のハッシュの生成をする」 これだけでいいんです。 「Webサーバからパスワード文字列が漏洩する可能性を防ぐことができる。」 これとか、対策ではないですよね。
pack

2016/10/02 18:55

結果: 当WebサービスからWebサービスを利用するユーザのパスワード文字列が漏洩することはない ↓ 当Webサービスを利用するユーザは安心して当Webサービスを利用することができる。 これは、客観的事実ですかね?
pack

2016/10/02 18:58

「不安」「漏洩しないようにする」「安心」という言葉を掘り下げてみます。 掘り下げるというより、排除した方がいいと思います。
kaz.Suenaga

2016/10/03 00:51

他人事のように言ってしまいますが、非常にいい議論してますねー。 hojoさんもpackさんもせっかくなので行けるところまで行ってみましょうね。 hojoさん>1点だけ。 質問1への回答(結果)として > 結果: > 当WebサービスからWebサービスを利用するユーザのパスワード文字列が漏洩することはないので、当Webサービスを利用するユーザは安心して当Webサービスを利用することができる。 とおっしゃっていますが、ここは、 - 元のパスワード文字列は保護できる - サービス利用にあたっての安全性は保護できていない(サービスの安全の侵害要因が、パスワードの漏洩から、クライアントサイドでのハッシュ結果に置き換わっただけ) となるのは理解できますでしょうか。 サーバサイドでは「ハッシュ」を受け取ってそれを基に認証するので、元のパスワード文字列が何かは関係なくなっている、ということです。
pack

2016/10/03 17:08 編集

「掘り下げるというより、排除した方がいいと思います。」 といいましたが、あまり難しく考えなくていいですからね。委縮させてしまいそうで、ごめんなさい。 「掘り下げる」でいいと思います。 「サービスの安全性が高まる」だと、やはりhojoさんの主観になってしまうなと思いますし、それだと「議論」というより、「ツッコまれて」しまうよなと、思ってしまいます。 あと「保証」という言葉も、ものすごく抽象的ですね。 「社会的責任」などの意味合いも含みますし、「安全性の立証」など、また別の行為を含んでくるなど、人によって受け取り方は様々ですので、そういった言葉を無意識に使うと、たいてい議論がこじれます。 議論の余地のない完璧な客観的事実なんてものは無いと思いますし、どこかに主観は入ってしまうんですけどね。 まぁ、まずは意見を出して、あれこれ付け足したりはしなくて、いいです。 議論の余地があるからこそ、こうして議論している訳ですから。
hojo

2016/10/06 02:15

すみません、今出張から帰ってきました。 おそらく本日中に確認できると思いますのでもうしばらくお待ちください。
guest

0

結論:SSL/TLSを適用しましょう。そして、パスワードのハッシュ化はサーバサイドで行う。

SSLなしでパスワードをJavaScriptでハッシュ化した場合、ハッシュ化後のパスワードはそのままネットワーク上を流れますので、それを手に入れてしまえば不正ログインできてしまいます

Google ChromeはHTTPSでない全サイトを「危険」とする方向に向かっていますし、そうでなくてもパスワード入力フォームのあるサイトは、もはやHTTPでの運用は不適当と言って良いでしょう。

投稿2016/09/26 08:41

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hojo

2016/09/26 08:45 編集

「SSLの話ではありません」ということを書いていたつもりなのですが文章がわかりにくかったようですね。すみません。上記の質問はSSLによる暗号化通信を行った上での話になります。
guest

0

この場合、

  • クライアント側では平文パスワードとSaltキーAをハッシュ化
  • サーバー側ではクライアントから送られてきたハッシュとSaltキーBをハッシュ化しDBなどに保存

これが一番安全だと思います。
この場合、ログインできるのは

  • 平文パスワードを知っている人
  • 通信経路を見てクライアント側で生成したハッシュを盗んだ人

です。
通信経路を見られてもこの場合ならハッシュ化パスワードしかわからないですし(もちろんフォームページが改ざんされたら終わりです)、サーバーのDBが漏れたとしてもDBに保存してあるハッシュを利用してログインすることはできません。
(ログファイルにPOSTフォームなどが残る設定になっていて、ログファイルが漏洩してしまったらクライアントサイドのハッシュが漏れてしまいますが)

投稿2016/10/01 03:23

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

なるほどな、と思いました。
おっしゃりたい事は、よく解ります。

私もセキュリティに詳しくはないので、何かの解決策を提示するものではないので、ご了承ください。
他の方の意見を聞いてみたいです。

他の方の回答にあるように

サーバー側では、送られてきたハッシュ値と保存されているハッシュ値の比較だけすれば良いことになります。

は、確かにそうなりますね。

※※これは間違いでした。なりません。サーバー側も必須です。

全ユーザー共通のSaltキーを、Javascriptに記載するという想定ですかね。
あるいは、ユーザー毎にサーバー側で生成して、Javascriptで渡すというようなお考えですかね。

参考リンク内にあった

salt とは一定長以上の文字列で、以下の要件を満たすものです。

ユーザー毎に違うこと
ある程度の長さがあること(20桁以上が目安)

を見ると、ユーザー固有であることが必要ですね。

こういう考えはどうですか?

ユーザーID(仮にメールアドレス)とパスワードを使って、固有のSaltキーを生成。
なんなら、パスワードだけからSaltキーを生成してもいいような。
⇒ そのSaltキーをを基に、ハッシュ化。
⇒ 送信。

現在よく行われているであろうサーバー側での処理で使われる値。

  • WEBアプリ毎に設定される全ユーザー共通のキー(ユーザーからは見えない。ソースには記載。運営は見える)

ユーザー側で処理する場合に使う値

  • パスワード(最後の砦。本人しか知らない。これが漏れたら元も子もない)

「ハッカーに処理が知られる」
⇒「パスワード入力からハッシュ化までの間を狙われる」
⇒「ハッシュ処理を解析される」

この2パターンが考えられると思いますが、確かに入力からハッシュ化までの距離、時間は短ければ短い方が良さそうですね。
繰り返しますが、以上は、質問を拝見しての私の感想です。

あっ、そうすると、「ハッシュ自体を途中で盗まれたら…」になるのか。

投稿2016/09/26 10:04

編集2016/09/26 17:12
pack

総合スコア256

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hojo

2016/09/26 10:15

投稿ありがとうございます。 Saltキーはサービス固有の文字列(安易ですがサービス名とか)を利用するものと思っていました。なるほどメールアドレスを使用するという発想はなかったです。 ただし、Javascriptのコードを見たらメールアドレスをSaltにハッシュを生成していることはバレてしまうので、それがバレた時にどういう問題が起こるのか私にはわかりません。そこが詳しく知りたいとこだったりします。 私も同様、他の方の意見をもっとうかがいたいと思っています。
pack

2016/09/26 10:23

「メールアドレスをSaltキーに使う」ではないです。 例えば 1. 入力フォームのパスワードを取得。 2. それを基に、MD5などで長い文字列を生成。Saltキーとする。 3. そのSaltキーを基に、SHA256などでハッシュ化。 4. サーバーへ送信。 5. 生成したSaltキーは破棄。 ですね。 一点、回答の最後に書きましたが、仮に「ハッシュ自体を盗まれたら」マズいですね。 サーバー側は、それを比較するだけなので。
pack

2016/09/26 10:26

パスワードを「パスワードを使って」ハッシュ化するという、奇妙な感じですが。
pack

2016/09/26 10:31

> Saltキーはサービス固有の文字列(安易ですがサービス名とか)を利用するもの サービス固有のキーを使っている所もあるでしょうし、それプラスメールアドレスをしている所もあるでしょうし、いろいろ組み合わせて、強度を高める方法があるということだと思います。 メールアドレスだけというのはないと思います。 何かしら秘密のキーを使っているはずです。
pack

2016/09/26 10:38

多分、「サーバー側に侵入して、何か悪さをする」より、「Javascriptの処理の部分を乗っ取る」方が、クラッカーにとっては、簡単なのかなと想像します。 セキュリティが、ブラウザ、個人のPCに強く依存しますので。
hojo

2016/09/26 10:41 編集

勘違いしておりました^^; パスワードを元に生成した文字列をSaltキーとしパスワードをハッシュ化するということですね。なるほど。 確かにそうすればパスワードのハッシュが漏洩してしまった場合そのハッシュのSaltを解析するためにWebサービスJavascriptを解析してもSaltはわからないということですね!なるほど!Salt漏洩はこれで防げるということですね!素晴らしいと思います! ただ、おっしゃる通りハッシュが漏洩したらまずいことに変わりはないですね。しかし、同じパスワードを利用しているユーザがいた場合、自分のWebサービスから漏れたパスワードを利用してその他のサービス(Facebookとか)にログインするということはできなくなりそうなので被害の拡大を防げると思いました。
hojo

2016/09/26 10:49

クライアントサイドでハッシュ化したパスワードをサーバサイドで復号化可能な暗号化を行った上でDBに保存すれば、情報漏洩が発覚した時に全てのユーザの「暗号化されたパスワードのハッシュ」を復号化して新しいSaltを利用したサーバサイドの暗号化を再び行えば、漏れた暗号化ハッシュを使ったログインを回避することができるのかもしれない...とか今思ったのですが、本当にそれでできるのか確信はもててません。
pack

2016/09/26 11:05

> 情報漏洩が発覚した時 これは、具体的にどういう事を意味しますか? サーバー側が突破された時の意味ですか? それとも、先ほどの案にあった個人のハッシュが漏れた時ですか?
pack

2016/09/26 11:08

最初にあった > サーバー側では、送られてきたハッシュ値と保存されているハッシュ値の比較だけすれば良いことになります。 も、別に今までのサーバー側の処理を止めなくても、今まで通りサーバー側でもハッシュ化して、2段階構えになり、強化はできそうですね。
pack

2016/09/26 11:23 編集

ユーザー側の秘密のキー(パスワード)が一段階目。 サーバー側のWEBアプリ固有の秘密のキー(全ユーザー共通)が二段階目。 (プラス、ユーザー固有の情報を付加して、複雑にする場合もあり) ですね。 暗号化、復号化の話は、途中経路で盗まれた時の対策なので、DB内で暗号化などは、あまり意味がないような気がします。 どのみち、ログインの際、比較の為に、毎回復号化しなければならないので。
pack

2016/09/29 18:41 編集

そもそも、パスワードというもの自体、人間にとっては何の意味もない文字列ですからね。 それが、ハッシュ化されて複雑になったとしても、意味としては同じであって。
pack

2016/09/29 18:42 編集

「そもそも意味のない文字列」を隠す為に、さらに複雑化してるだけですので。 パスワードというのは、「他のサイトでは違う文字列である事」のみが、意味ある事なのではないでしょうか。
pack

2016/09/29 18:42 編集

そう考えると、振り出しに戻りますが、サービス固有のキーをサーバー側から提供し、ハッシュ化する事で、仮に途中で漏れた場合に効果はある。 ただし、自社に対してではなく、他社でもパスワードを使いまわしていた場合のみ。 という感じです。 もちろん、サーバ側でのハッシュ化は今までと同様に必要。 DBを覗かれた時の為。これは、自社を守るためです。
pack

2016/09/29 18:43 編集

他の方も指摘されてますが、サーバー側かクライアント側か、というような話になってましたが、どちらかという話ではないですね。 サーバー側は必須です。こちらの方が断然、重要です。 それにプラスして、クライアント側でハッシュ化した際に、何が守れるのか。 それは、他社への影響を防げるという所ですね。
pack

2016/09/27 14:50 編集

暗号化は、秘密鍵を持ってこれば、復号化できる。 例えば、元のパスワードを取り出せる。 ハッシュ化は、秘密のSaltキーを持ってきても、復号化できない。不可逆だから。 ハッシュ値の中に、元のパスワードが隠されている訳ではない。 この辺りが整理されて来れば、また改めて質問したい事が出てくるかもしれませんね。
pack

2016/09/29 18:43 編集

パスワードからSaltキーを作る案。ダメみたいですね。 「最低限の要件は、短くないことと、ユーザ毎に違うことです。パスワードを元にしたSaltは後者を満たしません。」 確率的に、他者と被る可能性があるという事でしょう。 http://togetter.com/li/88911
YsMana

2016/09/28 12:16 編集

そもそもSaltは鍵(キー)ではないですし、秘密情報でもありません。 少なくともハッシュに対する攻撃を想定するときには、Saltも漏れていると想定するものです。 パスワードのハッシュ管理で、ソルトは秘密情報ではない(バレてもいい)のはどうしてでしょうか? http://ask.fm/tokumaru/answers/125698957117 >> 「最低限の要件は、短くないことと、ユーザ毎に違うことです。パスワードを元にしたSaltは後者を満たしません。」 > 確率的に、他社と被る可能性があるという事でしょう。 Saltの役割は、「パスワードが同じ」でも「生成されるハッシュ値は違う」ようにすることです。(これによりハッシュ値の事前計算を不可能にする。) Saltをパスワードを元にして生成してしまうと、「パスワードが同じ」なら「生成されるハッシュ値も同じ」になってしまい、Saltの意味が無くなってしまいます。 【追記】 ハッシュと秘密鍵(≠Salt)を組み合わせるという考え方自体はおかしなものではないと思います。HMAC(鍵付きハッシュ)とかありますし。
pack

2016/09/28 12:32

ありがとうございます。 > そもそもSaltは鍵(キー)ではないですし、秘密情報でもありません。 これについては、私も勘違いしてました。 http://www.atmarkit.co.jp/ait/articles/1110/06/news154_3.html の中に 「通常、ソルトはハッシュ値とともに保存するので、オフライン攻撃者にとってソルトは秘密情報ではありません。」 という記述があり、あれ?と思いました。 ただ「オフライン攻撃者にとって」という文言も付いてるんですよね。 今回の質問として、Saltが漏洩するしないがあって、それに対する回答が付いてなかったので、私の方で答えられればと思ったのですが、うまく答えられませんでした。 「ハッシュ値を再現できてしまうのを防ぐ事」が重要なのは解っているのですが、秘密であるなしの想定の前段階として、下記二つの認識としては、合ってますか? ・ハッシュ値が漏れた、ソルトも漏れた、レインボーテーブル作られる、解析されて元の値を割り出される。 ・ハッシュ値が漏れた、ソルトは漏れていない、レインボーテーブル作れない、解析できず元の値を割り出すのは、無理。
YsMana

2016/09/28 12:58 編集

> ただ「オフライン攻撃者にとって」という文言も付いてるんですよね。 オンライン攻撃の場合、そもそもハッシュ値が手元にありません。 ハッシュ値が手元に無いのにSaltだけ知っててもそのSaltでできることはないでしょう。 > ・ハッシュ値が漏れた、ソルトも漏れた、レインボーテーブル作られる、解析されて元の値を割り出される。 Saltが付いている分、レインボーテーブルの解析対象になるパスワード長が増えることになるので、Saltが既知かどうかに関係なく、レインボーテーブルを作ることはできません(正確には非常に困難になる)。 Saltが既知なので、「特定のSalt付きHash関数」に対するレインボーテーブルを作ると言うことも考えられますが、この場合はその特定のSalt専用のレインボーテーブルになるので作る意味がありません。 (レインボーテーブルの利点は総当たりを事前にやって、それを「複数のハッシュ値」の解析に使えることにあるので、1回しか使えないなら普通に総当たりした方が良い。) 【修正】レインボーテーブル周りの説明をちょっと分かりやすく修正。
pack

2016/09/28 12:59

> オフライン攻撃 DB覗かれて、ソルトもハッシュ値も、すぐ側に保存されてる場合等の事を言ってるのですよね。解ります。 > その1つのSalt専用のレインボーテーブルになるので作る意味がありません。 ですが、先ほどのTogetterにあったように 「ちょっとひっかかったのは、IDとsaltのペアがわかっていれば、事前にハッシュテーブルを用意できるかなと思いました。人数分用意する必要はありますが、ターゲットが絞れるなら充分脅威かも、と。」 という所で、私も同じ感覚です。 レインボーテーブル一つ作るのに、どれくらいのコストがかかるのか、解っていませんが。
pack

2016/09/28 13:06

なるほど。 「ブルートフォース攻撃」でという意味ですね。 「レインボーテーブル」の意味が、私の中で、あいまいでした。
pack

2016/09/28 13:13

「ブルートフォース攻撃」というと、それこそ正面から、ログインフォームを使って、というイメージがあるので、それはまた別の所で弾かれてしまうのでは、と思ってしまいます。 Webサーバーなり、ファイアウォールなりで。
YsMana

2016/09/28 13:28

ごめんなさい、コメント修正が遅かったですね。 > 「ブルートフォース攻撃」でという意味ですね。 はい、レインボーテーブルを作るコストは「ブルートフォース攻撃」と同等になります。 レインボーテーブル - Wikipedia https://ja.wikipedia.org/wiki/%E3%83%AC%E3%82%A4%E3%83%B3%E3%83%9C%E3%83%BC%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB にも > このテクニックの発端は「あるハッシュ値に対して総当たり攻撃を行った際の計算結果を、別のハッシュ値を攻撃する際に使用できないか」という点にある。 と書かれているように、レインボーテーブルは複数のハッシュ値を攻撃するときに有効です。 > 「ちょっとひっかかったのは、IDとsaltのペアがわかっていれば、事前にハッシュテーブルを用意できるかなと思いました。人数分用意する必要はありますが、ターゲットが絞れるなら充分脅威かも、と。」 これは、変更前後のパスワードでSaltが重複している前提ということになりますね。 1回目のブルートフォース攻撃時にレインボーテーブルを作っておけば、パスワードが変更された2回目以降の攻撃にレインボーテーブルが有効、ということになります。 他の観点としては、ハッシュ値が漏洩する前にレインボーテーブルを作っておけば、 後にハッシュ値が漏洩した時に短時間で解析が完了するという所でしょうか。 (総当たりのコスト自体はかかるが、それを事前に行えるところを利点とみなす。将来漏洩するかどうかも分からないハッシュ値のために事前に特定Salt専用レインボーテーブルを作るような攻撃者がいるかは微妙な気もしますが。) > 「ブルートフォース攻撃」というと、それこそ正面から、ログインフォームを使って、というイメージがあるので、それはまた別の所で弾かれてしまうのでは、と思ってしまいます。 レインボーテーブルの話が出てくる文脈では、攻撃=手元でハッシュ値を計算するオフライン攻撃のことなので、そういうことはできないですね。
pack

2016/09/29 13:38 編集

ありがとうございます。だんだん整理されてきました。 質問者さんが、戻ってこられるか判りませんが、また改めて不明点を質問してくれるといいですけどね。
pack

2016/09/28 15:08

1回しか使えないなら普通に総当たりした方が良い。 レインボーテーブルを作るコストは「ブルートフォース攻撃」と同等になります。 この部分が、言われてみればそうだなと盲点でした。 「ソルトさえ隠しておけば、大丈夫」みたいな思い込みが、ずっとありましたね。
pack

2016/09/29 13:36 編集

もう一点、質問者さんの気になってた事で、参考になりそうな他の質問が、YsManaさんのクリップの中にありましたので、貼っておきます。 『JavaScriptにはハッシュ関数は用意されていない? コードを確認されると意味がないから?』 https://teratail.com/questions/30933 質問者さんが戻ってきて、また私が的外れな事言ってたら、その時はYsManaさんに、ぜひとも援護願いたいです。
hojo

2016/10/01 03:05

すみません、隙間時間に一つづず返信文を書いており、予想以上の長文でしたので、packさんのコメントについては時間があるときに一気に読み込もうと思って後回しにしておりました。もう少しで時間ができますので、そのときに再度返信させていただきます。
pack

2016/10/01 07:25

私も、生半可な知識だけで、いろいろ言ってしまい、長くなってしまいました。申し訳ありません。 間違った発言も所々あります。今回の質問は、私自身も大変、勉強になりました。 ありがとうございます。 追加で言いたかった事は、raccyさんの回答の方に書きました。
guest

0

元のパスワードを保護し、ハッシュは漏れてもいいという考えなら質問者様の通りで良いと思います。
SHA256はハッシュであり、暗号化ではありません。

ユーザーの安全性に何を含むかによるので、ユーザーの安全性の問題はまた別かと思います。

ただ、SSL/TLSは安全という前提なので、それだけで十分かと思います。
更に安全を求めるならユーザー別にクライアント証明書も利用し、万一ハッシュが漏れても接続クライアントが正しくない場合は利用させないなどの対応も一案かと思います。

投稿2016/09/26 09:30

moonphase

総合スコア6621

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hojo

2016/09/26 09:41

SHA256は「復号化不能な暗号化」と解釈していたのですが、確かに「ハッシュ」と表現した方が適切でした。ご指摘ありがとうございます。 moonphaseさんは、クライアントサイドでSHA256によるハッシュ生成を行う際のSaltキーを隠蔽することは不可能とお考えですか? もしそのようにお考えの場合、ハッシュが漏れてしまった場合に起こりうる危険性はどのようなことが考えられますか? 例えば、Javascriptに記述されているSaltキーとその漏洩したハッシュを利用してそのユーザのパスワードのハッシュとメールアドレスを利用して同じパスワードを利用している異なるサービスにログインできてしまうなどは考えられますか?
moonphase

2016/09/26 11:27

そもそも利用者からSaltを保護する必要がないように思えますがいかがでしょうか。 SaltはユーザーID等を利用すればいいのでは、と思います。 ハッシュが漏れていい場合は、ハッシュが漏れても被害なし。 ハッシュが漏れてダメな場合は、ハッシュが漏れると被害あり(なりすまし)。 というだけの事かと思います。
hojo

2016/09/30 23:40 編集

返信ありがとうございます。moonphaseさんの意見をいただき「Saltに関してはさほど気にしなくて良い」と思えるようになりました。 その他のユーザ様のコメントを見ても「基本的にSaltを保護する必要はない」という意見で一致しているような気がしています。 かといってSaltを使わないのは心配なきがするのでメールアドレスやパスワードから生成した文字列などを利用してSaltを作成しようと思いました。
guest

0

パスワードのハッシュ化はクライアント側ですべきでないと思います。
ハッカーになるべくヒントを与えないような作りにすべきだと思います。

基本的に、パスワードのハッシュ化はサーバーサイドで行います。
Saltを隠蔽するのは当然ですが、加えて、ユーザー固有の一意な情報(ログインIDとかメールアドレスとか)などと併せてパスワードをハッシュ化すればなおよいと思います。

投稿2016/09/26 09:10

CodeLab

総合スコア1939

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hojo

2016/09/30 23:42

ご意見ありがとうございます。質問投稿時に比べ、話が複雑になってきているため、質問の追記などを含めその他の回答をご覧になった上で何か思うところなどございましたらご指摘頂けないでしょうか?宜しくお願い致しますm(_ _)m
guest

0

SHA256ということはハッシュ値を保存すると言うことですよね。
それなら、クライアント側でハッシュ値計算して、それをサーバーへ送ってサーバーで保存すればどうでしょうか?
ハッシュは一方向の不可逆なコードなので、ハッシュ値からパスワードを逆に求めることは出来ません。
なお、MD5などはレインボーテーブルを使った攻撃などの脆弱性があるのでSHA256が推奨されています。

サーバー側では、送られてきたハッシュ値と保存されているハッシュ値の比較だけすれば良いことになります。ただ、サーバー側では平文のパスワードはわかりませんので、パスワードを忘れた時はリセットをできるような仕組みにしておかないといけません。

ただこの方法は、クライアント側でのハッシュ計算がどのように行われているかの解析が困難なようにしておかないとだめです。(解析を完全にブロックするのは難しい。ハッシュ計算の部分を暗号化して実行時に元に戻すとか、まあ、昔のコピープロテクトのようなことでもしないと難しいかもしれません)

パスワードのハッシュ化については下記URLなどが参考になるかと思います。
https://www.websec-room.com/2013/02/27/237

より安全にするには、通信経路はSSLにして、ハッシュ化はサーバー側で行うのが良いと思います。

投稿2016/09/26 08:43

編集2016/09/26 08:51
PineMatsu

総合スコア3579

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hojo

2016/09/26 08:49 編集

SHA256によるハッシュ作成に利用するSaltについての扱いについてはどう思われますか? つまり、クライアントサイドで暗号化を行った場合、Saltを隠蔽する形で暗号化を行う手法はありますか?その術がない場合、Saltを隠蔽するまでする必要はなかったりするなどの意見というか考え方で良いかどうかなど、意見が欲しいです。
PineMatsu

2016/09/26 09:07

追記でも書きましたが、クライアント側での処理の隠蔽は完全には無理だと思います。内部でのハッシュ化の処理が解析されたら終わりです。 処理を動的に幾つものDLLを介するとかなどリバースエンジニアリングを困難にするようなコードを組むとかの手法を用いるくらいしか思いつきません。 コピープロテクトと言うのは、その昔、ソフトがフロッピーで売られていた頃、そのコピーガードとして組み込まれていたプロテクトガードのことです。コピーガードと言うのは、究極はそのチェックルーチンになりますから、そのチェックルーチンを解析できたらその部分をパスすればガードを外すことが出来る事になります。よくやられていたのは、チェックルーチンを暗号化しておき、動作時に復号化してからルーチンを呼び出すようにする手法です。結局、これもイタチごっこです。
PineMatsu

2016/09/26 09:40

追加された質問内容に関して。 クライアント側での暗号化の詳細が第3者に漏れることが絶対にない、解析は絶対に不可能と保証できるのなら問題はないでしょうけど、それは保証できないと思います。リバースエンジニアリングを完全に防ぐ手段がありません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問