[web]運用中のサイトでセキュリティ脆弱性対策をやっていった一連の流れ

はじめましてからの話。

前提

セキュリティ周りに知見のない人間が、ひょんなことからWEBサイト脆弱性対策に着手。

大手のサービスじゃないから一応伏せるけど、ZENがベースになってる。

対象のサイトはWordpressで組んであって、投稿しまくりだし広告出したり色々やってる。

という状態。

脆弱性チェック

とりあえず出てる警告を検索して、CSPやらCORSやらの言葉を知る。

警告はレベル分けがされていて、一番やばいやつから潰すのが妥当な話。だけども無知なので、調べて出てきたのをひたすら試していった。理想は高リスク順、実際は潰せる順。

要するにでいうと以下の感じを守っていくための取り組み。

  • 余計なもんは入れるな、消せ
  • どういう動き方するか、外部JSとか使うとか、ちゃんと宣言しろ
  • インラインで書くな、書くならnonceつけろ
  • 送信フォーム使うならワンタイムのトークンを仕込め

これが色々分けられてる。

サーバーの問題

脆弱性つぶしでしんどいのは、サーバー自体の設定を変えろという内容。

ヘッダー情報によってはサーバー側で設定しないと変えられないものがある。

例えば「X-Powered-By」で、環境をオープンにするな、消せよって警告がある。これはphpのheader()で削除できるけど、phpだけじゃなくて画像とかも該当する。サーバーの設定変更ができなければ詰む。

サーバーの設定ができない状況というのは一般的なレンタルWEBサーバーで、お名前.comとかロリポップとかconoHaとかさくらサーバーとかそういうやつ。案件ではお名前を使っていて、「X-Powered-By」が入っていなかった。ロリポップを見てみたら入ってた。お名前にも操作できない部分があるので万全ではない。

セキュリティのためにサーバーを変更しなきゃいけない状況が出てくる。そういうサーバーを探すとか、自分で構築する必要が出てくる。「これでいいでしょ」でリリースされてずっと使われてるものに喧嘩を売れるはずがないので、つらい。

潰せないものが出てきたら、どうしようもないから諦める・セキュリティを優先して引っ越すの2択ですね。

運用中のWEBサイトに手を入れる

ズブの素人である点、脆弱性対策はWEBサイトそれぞれになる点、めちゃくちゃ時間がかかることは目に見えてる。じゃあどうするか。

閲覧に影響しない部分であればやっちゃえばいい、影響する部分があれば人がいない時間帯にやっていく。小規模なところだとまでこれで何とかなる。

規模がデカくなるとそういうわけにもいかず、WEBサイトを複製してやっていく必要がある。まあ規模関係なしに普通にそうすべきではあるんだけど。コピーしたサイトで対策を構築して、本番環境に反映する。

極力同じ環境を複製する必要があるわけで、これが厄介。運用歴が長ければ総ファイル数は結構なもので、移植がめっちゃ大変。WordpressだとDBを使ってるんで、それも移さないといけない。間違ってなにかあるとまずいから絶対に同じのDBを使い回せない。

jsのCDNは問題ないんだけど、例えばアナリティクスとかの計測タグはサービス元に登録しないと正常な動作にならなくて、元サイトと同条件を作るのはほんとに大変。たまらないですね。

そんな感じで、WEBサイトを閉鎖しないでどうにかやっていく形をとる。

警告を無視する状況がある

ページのタイムスタンプは必要ないものは見せるなという警告がある。これはサーバーの設定で変更できる。でもサーバーに手を入れられない環境。この警告はリスク的に見て低いもので、言ってしまえば投稿記事を更新したときに出すじゃんって話で、重要度は超低い。だから無視していいって判断もできる。まあ、ちゃんと割り振れたとしてその割り振りが正しいよってセキュリティチェックが認識してくれるか怪しいんで、出すか消すかの2択になる。あんまり意味ないっすね。

phpとかjsとかがメッセージを吐くのをやめろって内容も、理屈は分からなくないけど外部サーバーのやつだから触れませんだとか、必要なものしか書いてないからいじりようがないだとか、ある。お上と現場の判断が違うんですね。

そういうあれ。

チェッカーの選び方

無料だったり有料だったり独自路線だったり色々なチェッカーがあって、例えば特定のヘッダー情報が入っていれば可(内容は問わない)だったり、チェック元が納得する書式出ないと可を出さないだったりがある。バチクソめんどくさい上に正しさの担保はどこにあるのかが謎いので、素人からするとしんどい。

作業自体はWEBがいじれたらできるんだけど、セキュリティの知識がないと結局なんにもならない。

チェックの流れ

WordPress的なあれだけど。

CDNのチェック

integrityとかをちゃんと書く。

header.phpとかfunctions.phpにまとめてあればいいんだけど、page.phpとかに個別に書いてると見落としやすいので注意。

プラグインのチェック

プラグインを無効化して、プラグインの影響でなにか起きてないか確認。

プラグインが外部のなんちゃらを読み込んでる場合がある上、何がどうなってるかわからない場合がある。入れてるものだから極力使用を続行したいけど、無理っぽいやつは外す。機能によってはjQueryプラグインとか、自作で賄ったりして対応できる。

フォームのチェック(CSRF)

トークンを発行してやっていく。CF7の場合、自作したコードを突っ込めば済んだ。なので、場合によって無理だったりしたら、フォーム自体の見直しも視野に入る。

不要なタグの削除

現在使っていない計測タグが警告の元になる場合がある。

自前で管理してたらいいんだけど、外部委託しまくってるとどれが生きてるのか確認するのがめんどい。貼付するときにどこからのどういう何かログを残しておくのがいい。そうでないとしんどい。

表示速度施策は脆弱性対策の後

脆弱性対策をする前とした後では結構状況が変わるんで、PageSpeedInsightsの評価も変わってくる。並行して進めても大していいことは起きないので、後回しにした方がいい。二度手間になるはず。

脆弱性つぶしは泥臭い

「ここを見直せ」はあっても「こうしろ」はあんまりない。

とりあえず、ヘッダー情報をいじるのがメインになる。

phpだとこんな感じ。

header("Strict-Transport-Security: max-age=31536000");
header("X-Content-Type-Options: nosniff");
header("X-Frame-Options: SAMEORIGIN");
header("X-Permitted-Cross-Domain-Policies: none");
header("Referrer-Policy: strict-origin-when-cross-origin");
header("Cache-Control: s-maxage=0, private, no-store, no-cache, must-revalidate, max-age=31536000");
header("Access-Control-Allow-Origin: https://example.jp https://example.com https://example.co.jp");
header("Access-Control-Allow-Methods: GET, POST, HEAD, OPTIONS, PUT, DELETE, PATCH");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Headers: X-Requested-With, Origin, X-Csrftoken, Content-Type, Accept");
header("Accept-Encoding: gzip");

.htaccessだとこんな感じ。

Header always set Cache-Control "private, no-store, no-cache, must-revalidate, max-age=31536000"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Forwarded-Host "www.mydomain.com"
Header always set X-Content-Type-Options "nosniff"
php_value display_errors Off

ディレクトリ単位で指定したい場合やファイル別に指定したい場合や.htaccessで指定できるもの・できないもの、サーバーの設定じゃないと無理なものなどある。

記述してスキャンしてをひたすら繰り返す。

脆弱性を全部潰した後は、運用中にまた警告が出ないように祈る日々を送ることになります。

頑張りましょう。

コメント

タイトルとURLをコピーしました