サーバーは聞かれたことに答えすぎる
Webサーバーとは、サイトのファイルをブラウザに送り返すプログラムです。設定がゆるいと、見せたくないファイルや、攻撃の手がかりまで答えてしまいます。
この回では、サーバーが返す答えの読み方と、安全な設定の考え方を学びます。
ラボのルール
注意
ラボのパン屋のサイトは、あなた専用のコピーです。調べてよいのは、自分のコピーだけです。許可なく他人のサイトに同じことをするのは、不正アクセス禁止法に反します。目的は、自分のサイトを守ることです。
このレッスンのゴール
メモ
Webサーバーの設定を点検して、安全な設定にすることができる。
キーワード
| ことば | いみ | れい |
|---|---|---|
| HTTPヘッダー | Webの返事の先頭に付く、決まりごとの一覧 | Server: nginx |
| ステータスコード | 返事が成功か失敗かを表す3桁の数 | 200、403、404 |
| ディレクトリ一覧 | フォルダの中のファイル名を、そのまま表示すること | |
| バージョン情報 | ソフトの名前と番号。分かると、古い弱点を探される | |
| 設定ファイル | サーバーの動き方を書いたファイル | |
| 最小限の公開 | 見せる必要があるものだけを見せる考え方 |
学生が入力するセルは、このプレビューでは空白です。
ブラウザとサーバーは何を送り合うのか
ブラウザはサーバーに「このページをください」とお願いします。サーバーは、ステータスコードとヘッダーを付けて返します。
ヘッダーには、サーバーの名前や、ブラウザへの指示が入っています。curl -I は、ヘッダーだけを見るコマンドです。
自分のサイトのヘッダーを見る
curl -I http://webここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
出力のどこを読めばよいのか
先頭は HTTP/1.1 200 OK です。200 は、成功したという意味です。
次に Server: nginx/1.27.5 という行があります。サーバーの名前だけでなく、番号まで外に教えています。
守りに役立つ4つのヘッダー
| ヘッダー | 何を守るか |
|---|---|
| X-Content-Type-Options | ブラウザがファイルの種類を勝手に決めること |
| X-Frame-Options | 他のサイトの枠の中に、自分のページを出されること |
| Content-Security-Policy | 読みこんでよいスクリプトなどの出どころ |
| Referrer-Policy | 次のサイトに渡る、元のページの情報 |
学生が入力するセルは、このプレビューでは空白です。
ファイルの一覧が見えると、なぜ危ないのか
フォルダにトップページがないとき、サーバーの設定しだいで、中のファイル名が全部並んで表示されます。これがディレクトリ一覧です。
見せるつもりのなかったファイルも、名前が分かれば開かれてしまいます。
files フォルダの表示を見る
curl -s http://web/files/ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
一覧にあるファイルを開く
curl -s http://web/files/prices.csvここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
サーバーの番号を直接聞く
docker exec web nginx -vここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
3つの出力から分かること
1つ目の Run では、Index of /files/ という見出しと、ファイル名の一覧が出ます。2つ目では、パン3種類の値段が読めます。
3つ目は、nginx version: nginx/1.27.5 です。誰でも見られる情報が、サーバーの内側の情報と同じ番号なのが分かります。
設定の言葉と働き
| 設定の言葉 | 働き |
|---|---|
| server_tokens | 返事にバージョン情報を載せるかどうか |
| autoindex | ファイルの一覧を表示するかどうか |
| add_header | 返事にヘッダーを1つ足す |
| location | 道(URL)ごとに、別の決まりを書く |
| deny all | その道へのアクセスをすべて断る |
学生が入力するセルは、このプレビューでは空白です。
設定の書き方の形
# 例: 設定は「言葉 値;」の形で、行の終わりに ; を付けます。
# これは書き方の見本で、ラボの答えではありません。
add_header X-Example "hello" always;
ヘッダーの1行を分けてみる
# ヘッダーは「名前: 値」の形です。最初の : で2つに分けます。
line = "Server: nginx/1.27.5"
pos = line.find(":")
name = line[:pos].strip().lower()
value = line[pos + 1:].strip()
print(name)
print(value)
よくある間違い
注意
設定ファイルを直しただけで、直ったと思う人がよくいます。動いているサーバーは、読みこみ直すまで古い設定のままです。直したあとは、もう一度 curl で確かめます。
最小限の公開という考え方
安全な設定の基本は、見せる必要があるものだけを見せることです。バージョン、一覧、使わないファイル、管理用のページは、まず隠します。
直した設定は、読みこみ直してから、同じコマンドで答えが変わったか確かめます。確かめるまでが、作業です。