Internet Explorer も、気がついてみたらFirefoxまでも、複数タブ・ウィンドウ間で同一セッションになってしまった。確か、Firefox 3.6のときは、ウィンドウが別だったらセッションも別になっていたと思ったのになぁ...
で、同一セッションになって困るのは、セッション変数の扱い。
同じフォームを二つのタブやウィンドウで開くと、後から開いた方の値でセッション変数は上書きされてしまう。
これを防ぐには、フォームがはじめて表示されたときにフォームに対して一意の値を生成し、そいつを毎回POSTする。
そして、セッション配列へフォームの値を保存するときは、POSTされた一意の値をセッション配列のkey、保存したいフォームの値をvalueとすればよい。
で、いらなくなったときに、セッション配列の要素をunset()してやればいい。
この考え方は、ワンタイムチケットと同じ。
こっちも参照してね。
ワンタイムチケットでなくても、例えばログインフォームで一意の値を生成し、そいつをフォーム間で引き回せば、同じことができる。
ただし、ログインフォームで生成した一意の値が仮に悪意の第3者に漏れた場合、何をされるかわからないので、できれば、一定間隔で再生成する仕組みを考えた方がいい。
なんでも屋さんの自称SEさんが、知らなかったことをメモ代わりに書いてます。
たまに関係のないことも書きますが、良かったら参考にどうぞ。
2020/11
なんでも屋さんだったSEさんは、転職しました。今は社内SEさんとして、自社システム開発してます。でも、一人なんだよね・・・
2021/8 もう少し自分で考えてよって人が増えました...いい歳なんだからさー、指示待ちやめてよねー
2023/11 転職してから早3年、仲間が4名になりました!
2024/10 この一年で貯金がかなり減りました・・・
2012-02-25
2012-02-05
クロスサイトスクリプティング対策とかいろいろチェック
基本は出力時のエスケープ
外部から取得した値は、出力時に必ずエスケープする。
<?=htmlspecialchars(外部から取得した値, ENT_QUOTES)?>
外部から取得できる値
- ポストされた値
- URIのパラメタ値
- アップロードされたファイルの内容
- データベースから取得した値
しかし、URIを指定できる場所へエスケープして出力しても、「javascript:」で始まる文字列はエスケープされないため意味がない。
<?php // この変数 $var へ代入する値が、$_POST や $_GET $var = 'javascript:window.alert("XSS成功")'; ?> <a href="<?=htmlspecialchars($var, ENT_QUOTES)?>">リンク</a>
このような場所へは、外部からの取得値を出力してはならない。
また、エスケープが意味をなさない次の場所へは、外部からの取得値を出力してはならない。
<style>ここ</style> <script>ここ</script>
不正なマルチバイト文字対策
外部入力値に不正な文字コード(EUC-JPなのに1バイトだったなど)が含まれていたり、アップロードしたファイルが壊れていて、正しく文字エンコードを判別できないような場合、意図しない動きになる。特に、日本語のようなマルチバイト文字を使う場合は、必ずチェックする。mb_check_encoding(外部入力値, 'UTF-8');
mb_check_encoding()は、第一引数で指定したバイトストリームが、第二引数で指定する期待した文字エンコーディングとして有効な場合はtrue、無効な場合はfalseを返すので、無効な文字エンコーディングと判断されたときは、(処理にもよるが)強制終了すればいい。
$var = isset($_GET['param1']) ? $_GET['param1'] : ''; if (!mb_check_encoding($var, 'EUC-JP') { die('Invalid Access!'); };
NULLバイト攻撃の対策
まず「NULLバイト」の説明。エスケープシーケンスで表すと「\0」。
PHPには、このNULLバイト (バイナリ値) が渡された場合でも正しく処理できる関数 (バイナリセーフな関数) と、NULLバイトが渡されると、NULLバイトを文字列の終端と判断してしまう関数 (バイナリセーフでない関数) が存在する。
文字エンコードは正しく
header()でcontent-type を送信するか、php.ini の default_charset を指定する。表示するページのエンコードも、上で送信する文字エンコードに合わせる。
php.iniで次のよに設定されていれば何も意識しなくてよい。
default_mimetype = "text/html"
default_charset = "UTF-8"
このように設定されていれば、header()で次のように送信しなくても自動で送信される。
header('Content-Type: text/html; charset=UTF-8');
仮に、php.iniで default_charset が空の場合、Content-Typeヘッダ で charsetオプションパラメタ は送信されない。
・php.ini
default_mimetype = "text/html"
default_charset =
・送信されるヘッダ
Content-Type: text/html
送信されるヘッダにcharsetがないからといって、charasetだけ送信すると、今度はmimetypeが送信されない。Content-Typeヘッダを送信するときは、mimetypeもcharsetも
header('Content-Type: charset="UTF-8"'); // これはNG
header('Content-Type: text/html; charset="UTF-8"'); // mimetypeとcharsetはセットで送信
結論
php.iniで正しく設定するか、毎回 header()でContent-Typeを送信する。
session_get_cookie_params()
第4引数の意味:
× HTTPSのときだけ、サーバーからブラウザへセッションクッキーが送信される。
○ サーバーからブラウザへは常にセッションクッキーを送信するが、HTTPSのときだけ、ブラウザからサーバーへセッションクッキーが送信される。
× HTTPSのときだけ、サーバーからブラウザへセッションクッキーが送信される。
○ サーバーからブラウザへは常にセッションクッキーを送信するが、HTTPSのときだけ、ブラウザからサーバーへセッションクッキーが送信される。
登録:
投稿 (Atom)
.htaccessで403を404で返す
久しぶりにリライトルールを書いたよ。 ドキュメントルートに.htaccessを置く場合の記述↓ # 403.html は実体がなくてよい。この設定をすることで、あっても使われなくなる。 ErrorDocument 403 /403.html # 独自の404ページをドキュメ...
-
本題に入る前に、まずは、sh/bash系のシェルで標準出力と標準エラー出力をリダイレクトする方法から。 現在使用中のシェルを確認するには、 # echo $SHELL とすれば確認できる。 その他、利用できるシェルを確認するには # cat /etc/shell...
-
Internet Explorer も、気がついてみたらFirefoxまでも、複数タブ・ウィンドウ間で同一セッションになってしまった。確か、Firefox 3.6のときは、ウィンドウが別だったらセッションも別になっていたと思ったのになぁ... で、同一セッションになって困るの...
-
mb_send_mail()を使ってメールを送信する場合は、第5引数に Return-Path を指定する。 さもなければ、Return-Path は apache@hoge.dom (コマンドラインから実行したときは、実行アカウント名@hoge.dom)になる。 第5引...