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

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

新規登録して質問してみよう
ただいま回答率
85.50%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

CSRF

クロスサイトリクエストフォージェリ (Cross site request forgeries、CSRF)は、 外部Webページから、HTTPリクエストによって、 Webサイトの機能の一部が実行されてしまうWWWにおける攻撃手法です。

Q&A

解決済

1回答

3258閲覧

csrfの対策とSESSIONの持ち方について

spcl

総合スコア19

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

CSRF

クロスサイトリクエストフォージェリ (Cross site request forgeries、CSRF)は、 外部Webページから、HTTPリクエストによって、 Webサイトの機能の一部が実行されてしまうWWWにおける攻撃手法です。

0グッド

4クリップ

投稿2018/12/22 04:03

編集2018/12/22 06:15

質問失礼します。

ただいま会員システムを自分で作って勉強しております。
会員システムを作る上で気にしないといけないのがセキュリティの問題だと思います。

現在セキュリティの上で気になっているのがcsrfとSESSIONの持ち方です。

csrfを調べた上でこの解釈と対策方法であっているのか教えていただきたいです。

解釈としてはログインする時などユーザーIDとパスワードを入力してログインしますがまずログインページでランダムな文字のトークンを生成する。
それをhiddenで送る。
イメージとしてはユーザーがformのinputで何か入力するページでトークンを生成し、入力した値をチェックするページやinsertするページにトークンチェックのコードを設置すると考えております。
つまりcsrf対策はユーザーが入力した値を受け取る処理があるページ(ログインページや問い合わせフォーム)等で設定しておけばいいと思っているのですがあっていますでしょうか?

下記がトークンの生成コードにまります。

login.php

$_SESSION['token'] = base64_encode(openssl_random_pseudo_bytes(32)); $token = $_SESSION['token'];

次にログイン情報をチェックするページにてhiddenで送られて来たトークンとSESSIONのトークンが一致するか検査。
下記がトークンの検査コードです。
login-check.php

if ($_POST['token'] != $_SESSION['token']){ $_SESSION['E-message'] = "no-token"; header("Location: login.php"); exit(); }

あとは全ページでsession_regenerate_id( true )を記述しています。

また、ログインができればSESSIONにログインしたユーザーid(データベース上で一意なもの)を持ち持ちまわってそのユーザーを特定しているのですがidを持ちまわるのは変でしょうか?
持ちまわるのはSESSIONにidが入っているかいないかでページ上部にログインボタンまたはマイページボタンを表示するために持ちまわっています。

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

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

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

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

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

maisumakun

2018/12/22 04:14

特にフレームワークのない、素のPHPで開発している、ということで間違いないでしょうか。
spcl

2018/12/22 05:06

はい。 全て自分で0から開発しています。
m.ts10806

2018/12/22 06:12

タイトルにスペルミスがあるので修正しておいてください。 >SESSTION
spcl

2018/12/22 06:15

ご指摘ありがとうございます。
MJHSC

2018/12/22 06:34

これは非公開の練習目的でしょうか? 本番、公開するサービスでしょうか? もし、公開の可能性があるようでしたら、CSRF以外にも考慮すべきセキュリティ要素がありますし、セッション管理を行う外部ライブラリを使うことをおすすめします。
spcl

2018/12/22 08:33

最終的には公開目的です。 他にも考慮するセキュリティはあるのは知っていますがまずはcsrfを知りたいと思う質問させていただいた次第です。 外部ライブラリについては初めて知った要素になるので調べます! アドバイスありがとうございます!
guest

回答1

0

ベストアンサー

全般的に間違った理解と思われる箇所が多いので、セキュリティの勉強を基礎からやり直されたほうがよいかと思います。

イメージとしてはユーザーがformのinputで何か入力するページでトークンを生成し、入力した値をチェックするページやinsertするページにトークンチェックのコードを設置すると考えております。

違います。
CSRFとは、サーバー上で重要な更新処理などがある場合に行います。たとえば退会処理は入力なしでボタンを押すだけでも実現できますが、そのような場合でもCSRF対策は必要です。入力は関係ありません。

つまりcsrf対策はユーザーが入力した値を受け取る処理があるページ(ログインページや問い合わせフォーム)等で設定しておけばいいと思っているのですがあっていますでしょうか?

違います。
まず、ログインページでは必須ではありません。まだログインしていないからです。
問い合わせフォームは必須ですが、それは入力があるからではなく、問い合わせによりメールが飛んだりデータベースの更新により、問い合わせがあったことによるサイト運営者側のアクションが発生するからです。

下記がトークンの生成コードにまります。

前述のようにログイン処理ではトークンのチェックは必須ではありませんが、実施してもいいでしょう。

次にログイン情報をチェックするページにてhiddenで送られて来たトークンとSESSIONのトークンが一致するか検査。
下記がトークンの検査コードです。

これだと、$_POST['token'] と $_SESSION['token'] がともにNULLの場合にチェックをすりぬけますね。以下の記事を参考にしてください。

問題:間違ったCSRF対策~初級編~
解答:間違ったCSRF対策~初級編~

あとは全ページでsession_regenerate_id( true )を記述しています。

全ページでsession_regenerate_idを呼ぶ必要はありません。これが必要なのは、セッション変数に重要な情報をセットするページのみです。login-check.phpはidをセッションに保存するために必要ですが、それ以外は必須ではありません。全ページでこれをやると、スマホユーザなどがレスポンスをとりこぼすとログインが継続できなくなリます。

また、ログインができればSESSIONにログインしたユーザーid(データベース上で一意なもの)を持ち持ちまわってそのユーザーを特定しているのですがidを持ちまわるのは変でしょうか?

変ではありません。通常のやり方です。

持ちまわるのはSESSIONにidが入っているかいないかでページ上部にログインボタンまたはマイページボタンを表示するために持ちまわっています。

この目的だけであれば、idではなく、ログイン中かどうかのフラグ(falseかtrue)でよいのですが、マイページがあるのであればログインユーザの情報(idや、もし登録してあればメールアドレス等)を表示する必要があるような気もしますがいかがですか?


コメントの後半に対して回答します。

スマホユーザなどがレスポンスをとりこぼすとログインが継続できなくなる。
そんなことがあるんですね。
何故そうなるのか理由を探してみます。

考えてもわからなければ、新しい質問いただけたら回答します。

フラグはどのようなものでしょうか?

フラグとは、false/trueあるいは 0/1 のような値(真偽値や二値といいます)をとる変数のことです。

SESSION['flag']のような形でfalseかtrueをセットするということでしょうか?

それでもいいですし、フラグの意味がわかりやすいように、$_SESSION['is_loggedin'] のような形にすることも多いです。

当方は今SESSIONにidを入れて持ち回り、マイページにようこそ○○さん(ユーザーの名前)や登録情報変更 の際inputのvalueに現在登録されている情報を表示するためにidを持ち回っています。
SQLのWHEREでidで検索するためです。

ということは、単に「SESSIONにidが入っているかいないかでページ上部にログインボタンまたはマイページボタンを表示するために持ちまわっています」というわけではないのですね。回答側は質問文のみが頼りですので、正確に書くようにしましょう。

マイページでユーザーに自身のデータベース上のidや登録しているメールアドレスを表示する理由は何でしょうか?

ユーザー自身が確認するためです。あるいは、「マイページにようこそ○○さん(ユーザーの名前)や登録情報変更 の際inputのvalueに現在登録されている情報を表示するためにidを持ち回っています」と書かれたこともほぼ同じですよね。そのことを指しています。

投稿2018/12/22 13:27

編集2018/12/23 07:15
ockeghem

総合スコア11701

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

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

spcl

2018/12/23 02:36

ockeghem様 連休中にもかかわらずご丁寧な回答ありがとうございます。 どの回答も今までネットで見て勉強したページより分かりやすく鳥肌が立っています。 >違います。 >CSRFとは、サーバー上で重要な更新処理などがある場合に行います。たとえば退会処理は入力なしでボタンを押すだけでも実現できますが、そのような場合でもCSRF対策は必要です。入力は関係ありません。 >違います。 >まず、ログインページでは必須ではありません。まだログインしていないからです。 >問い合わせフォームは必須ですが、それは入力があるからではなく、問い合わせによりメールが飛んだりデ>ータベースの更新により、問い合わせがあったことによるサイト運営者側のアクションが発生するからです。 csrfへの理解はまだ浅いですがcsrfが行われるタイミングを知れたのは大変ありがたいです。 >これだと、$_POST['token'] と $_SESSION['token'] がともにNULLの場合にチェックをすりぬけますね。以下の記事を参考にしてください。 $_POST['token'] 、 $_SESSION['token']が共にNULLのことは全く頭になかったです。 ありがとうございます。 >全ページでsession_regenerate_idを呼ぶ必要はありません。これが必要なのは、セッション変数に重要な情報をセットするページのみです。login-check.phpはidをセッションに保存するために必要ですが、それ以外は必須ではありません。全ページでこれをやると、スマホユーザなどがレスポンスをとりこぼすとログインが継続できなくなリます。 スマホユーザなどがレスポンスをとりこぼすとログインが継続できなくなる。 そんなことがあるんですね。 何故そうなるのか理由を探してみます。 >この目的だけであれば、idではなく、ログイン中かどうかのフラグ(falseかtrue)でよいのですが、マイページがあるのであればログインユーザの情報(idや、もし登録してあればメールアドレス等)を表示する必要があるような気もしますがいかがですか? なるほどです。 フラグはどのようなものでしょうか? SESSION['flag']のような形でfalseかtrueをセットするということでしょうか? 当方は今SESSIONにidを入れて持ち回り、マイページにようこそ○○さん(ユーザーの名前)や登録情報変更の際inputのvalueに現在登録されている情報を表示するためにidを持ち回っています。 SQLのWHEREでidで検索するためです。 >idや、もし登録してあればメールアドレス等)を表示する必要があるような気もしますがいかがですか? マイページでユーザーに自身のデータベース上のidや登録しているメールアドレスを表示する理由は何でしょうか? 長文になりましたが再度ご回答いただけると幸いです。 よろしくお願い申し上げます。
spcl

2018/12/26 05:14

返信遅くなり申し訳ございません。 度々のご回答まことにありがとうございます。 >考えてもわからなければ、新しい質問いただけたら回答します。 ありがとうございます。 できる限り頼らず自分で調べてみます! >単に「SESSIONにidが入っているかいないかでページ上部にログインボタンまたはマイページボタンを表示するために持ちまわっています」というわけではないのですね。回答側は質問文のみが頼りですので、正確に書くようにしましょう。 かしこまりました。 最初からidを持ち回る意味もきちんと書いていればよかったですね。 次回より気をつけます。 この度は本当に詳しくご教授いただきありがとうございました。 できるだけ自分で調べ抜きますがどうしても解決できない場合はまたお力添えいただけますと幸いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問