基本的なWebセキュリティ その3 第04回 20年03月 / 最終更新:2020.03.12

前々回は「パスワードの保存方法」、前回は「SQLインジェクション」と「XSS」という、極めてポピュラーかつ有名な脆弱性について簡単にお話をしていきました。
あともう少しだけ「ありがちな脆弱性」についてお話をしていきましょう。

少し仕組みが厄介なのですが、対応が重要なものにCSRF(Cross-Site Request Forgeries)があります。クロスサイトリクエストフォージェリ、と呼称します。
「ぼくはまちちゃん」で、もしかすると覚えてらっしゃる方がいるかもしれません。或いは「犯罪予告をした、とされての誤認逮捕(パソコン遠隔操作事件)」といってピンと来る方がいらっしゃるかもしれません。
CSRFは、端的には「正規のユーザが、自分の意図に反して一定のリクエストを強要されてしまう」脆弱性です。
これは「ログインが必要なサービス」だけではなく、「特にログインがないサービス」でも発生する、のは、上述の「犯罪予告をした、とされての誤認逮捕」ですでに行われている事柄になります。

こちらの対応は、上述の2つと比べると「比較的出来ていない事も多い」ように思われます。
しかし場合によっては、実際に「誤認逮捕」のような実害も出ているものなので、しっかりと対応をする必要があります。

これに対する対応として一つ確実なのが「処理実行ページの直前に、もう一度パスワードを入力してもらう」という方法があります。パスワードの変更画面が、よくこの作り(新パスワードの他に、現在使っているパスワードを確認のために入力してもらう)になっているかと思います。

もう一つよく使われているのが「POSTで情報を投げる時に、CSRF対策用のtokenを一緒に入れる」方法です。
最近のWeb Application Firewallだと「この機能があって、デフォルトでチェックを入れてくれる」事も多いのですが。
もし自作をする場合は「tokenの作り方」をしっかりと確認しておきましょう。弱いtokenを作ってしまうと、そこが脆弱性になってしまいます。
tokenの強弱の判断基準としてわかりやすいのが「暗号論的に安全か?(cryptographically secure)」です。
tokenを作る時に「暗号論的に安全な関数とアルゴリズムのみで構成されていること」を、確認したり依頼に盛り込んだりしておくと、よいでしょう。
PHP7(またはPHP5.2以上+ユーザーランドの実装)を使っているようであれば、random_bytes()関数とbin2hex()関数を組み合わせるのが、わかりやすくて確実だと思います。
ネットや書籍では定期的にuniqid()関数を使った実装がありますが、uniqid()は「使うのを避けた方が安全」です。また、hash関数を通す実装も「空間が狭くなりがち」なので、同様に避けたほうが無難でしょう。
そういった「少し細かいレイヤーでのチェック」も、折々、やっておくと安全性が増すように思われます。

最後にもう1点、筆者が比較的「定期的に見かける」脆弱性のお話をしていきたいと思います。
それは、ディレクトリトラバーサルまたはパストラバーサルと呼ばれる脆弱性です。どちらの呼称も存在しますが、本稿では一端「ディレクトリトラバーサル」のほうの呼称を使っていきます。
端的には「アプリケーションが意図していないファイルをのぞき見することが出来てしまう脆弱性」になります。
一般的に、Webサーバは「DocumentRoot」と呼ばれる、行ってしまうと「世界に向けて公開するディレクトリ」をサーバの中に持ちますので、DocumentRoot配下にあるファイルは「そもそも、見る事が出来ます」。
逆に言うと「DocumentRoot配下にないファイルは、外からは閲覧出来ない」前提で作っている事が多いです。例えば典型的には「DB接続の情報を含むコンフィグレーションファイル」などが、それにあたります。
しかし、このディレクトリトラバーサルの脆弱性があると「DocumentRoot配下にないファイル」でも閲覧が出来るようになってしまいます。
ファイルのパーミッション(権限)にもよりますが、「OSの挙動に関わる」ようなファイルすら閲覧可能になるので、大変な注意が必要です。

また、これを「ディレクトリトラバーサル」と呼称してよいか? は幾分に疑問があるのですが。
例えば「アンケートの結果」や「mail formで得られた(個人情報を含む)内容」や「管理画面からダウンロードさせたい(デリケートな情報を含む)CSV」などを、「DocumentRoot配下に置いてある / DocumentRoot配下を作業領域としてファイルを作成する」アプリケーションを、時々、拝見します。
勿論普通の所にリンクは張っていないだろうと思われるのですが、なにかの拍子にURLが漏れた時など、ノーガードでそういった「本来、公開されてはならないデータ」が簡単に、かつ誰にでもダウンロード出来てしまう状態が起きるので。
「DocumentRoot配下には、公開してよい情報以外は一切置かない」というルールを、状況に応じて、明記する必要があるのかもしれません。

3回に渡って、少しセキュリティについて細々としたお話をしていきました。
次回は「開発環境と本番環境」について、理想と現実の2つの側面から色々と考察をしていきたいと思います。