HTTPについて

体系的に学ぶ 安全なWebアプリケーションの作り方   
脆弱性が生まれる原理と対策の実践 第2版  
著 /  徳丸 浩

上記の本を読み進めながら学習をしているので、その忘備録的な内容。

HTTPとは、Hyper Text Transfer Protocolの略。www(World Wide Web)上でWebサーバとクライアントが、 HTML(Hyper Text Markup Language)で書かれた文章などの情報をやりとりする時に使われる通信手順を意味する。

HTTPではデータが暗号化されていないため、通信経路のどこかで内容を知られる可能性がある。 第三者に知られたくない情報をやり取りする際には、別途暗号化を行うか、暗号化されたHTTPSという通信手段を使う必要がある。

基本的なHTTP

ブラウザからリンクを叩くと、リンク先へページが遷移する。
この時に、ブラウザはサーバーへHTTPリクエストを送信し、サーバはブラウザへHTTPレスポンスを返す。

リクエストライン

リクエストメッセージの1行目は、リクエストラインと呼ばれ、webサーバに対する命令。
リクエストラインは、メソッド,URL(URI),プロトコルバージョンを空白で区切って表す。

GET /sample/sample-01.html HTTP/1.1
  • GET - メソッド
  • /sample/sample-01.html - URL(URI)
  • HTTP/1.1 - プロトコルバージョン

HTTPのメソッドはGETのほか、POSTHEADなどがある。GETPOSTはhtmlのform要素に指定するmethod属性と同じ。
リクエストメッセージの2行目以降は、ヘッダと呼ばれ、名前と値を:で区切ってある。

ヘッダの例

GET /sample/sample-01.html HTTP/1.1
User-Agent: xxxxxx
Accept: text/html,application/xhtml,xxxxx
Accept-Language: ja,en-US,xxxx
Referer: http://sample.com/sample/
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Pragma: no-cache
Cache-Control: no-cache
Host: sample.com

この中で必須のヘッダはHostのみ。

レスポンスメッセージ

レスポンスメッセージはステータスライン,ヘッダ,ボディから構成される。

項目 内容
ステータスライン HTTP/1.1 200 OK
ヘッダ Server: XXXXX
Date: XXXXXXXXX
Content-Type: text/html charset=UTF-8
Content-Length: X
Connection: keep-alive
X-UA=Compatible: XXXX
空行
ボディ <body>hogehoge</body>

ステータスライン

リクエストメッセージの処理結果を返す。

HTTP/1.1 200 OK
  • HTTP - プロトコルバージョン
  • 200 - ステータスコード
  • OK - テキストフレーズ
ステータスコードの説明
ステータスコード 概要
1xx 処理が継続している
2xx 正常終了
3xx リダイレクト
4xx クライントエラー
5xx サーバエラー

レスポンスヘッダ

レスポンスメッセージの2行目以降は、ヘッダ。ヘッダは空行が現れるまで続く。

主なMINEタイプ

MINEタイプ 意味
text/plain テキスト
text/html HTML文章
application/xml XML文章
text/css CSS
image/gif GIF画像
image/jpeg JPG,JPEG画像
image/png PNG画像
application/pdf PDF文章

POST

お問合せページでよくある、入力画面 -> 確認画面 -> 登録の流れのHTTPを確認する

POSTメソッド

POSTをすると、リクエストラインの冒頭がPOSTになる。GETと異なり、空行に続いてブラウザから入力された値が送信される。この部分をメッセージボディと呼ぶ。

POST /XXX/XXXX.php HTTP/1.1
Referer: http://XXXX/XXX.php
Content-Type: application/x-www-form-urlencoded
Content-Length: XX
Host sample.com

name=XXXXXXXXXXXXXXX&mail=XXXXXXXXX.sample.com 
// ↑ メッセージボディ

メッセージボディ

POSTメソッドによるリクエストメッセージには、ボディという部分がある。レスポンスメッセージ同様、ヘッダとボディは空行で区切る。リクエストのボディには、POSTで送信される値が入る。

POSTによって送信される値に関するヘッダがContent-TypeContent-Length

  • Content-Length

ボディのバイト数。

  • Contetn-TYpe

送信する値のMINEタイプで、HTMLのform属性で指定することができる。指定がない場合は、application/x-www-form-urlencodedになる。これは名前=値の組を&でつないだデータ形式で、パーセントエンコーディングされる。

パーセントエンコーディング

URL上で特別な意味を持つ、記号や日本語などをURL上に記述するとき用いられる。対象の文字をバイト単位で%xxという形式で用いられる。xxはバイトの16進数表記。 スペースは%20となるが、application/x-www-form-urlencodedの場合はスペースを特別扱いして+に符号化する。

Referer

Refererはリンク元のURLを示すヘッダ。 form要素によるフォーム送信、a要素のリンク、img要素の画像参照でもRefererヘッダがつく。
Refererを確認することで、アプリケーションが意図した遷移を経ていることを確認できる。しかし、ツールや、ブラウザのプラグインなどによって改変・削除されることがあるため必ず正しいとは限らない。URLがセッションIDを含んでいる場合、Referer経由で外部に漏洩しなりすましに利用される場合がある。

GETとPOSTの使い分け

  • GETメソッドは参照のみに用いる(リソースの取得のみ)
  • GETメソッドは副作用がないことが期待される
  • 秘密情報の送信にはPOSTメソッドを使う

※副作用 - リソースの取得以外の作用(追加・更新・削除が起きるなど)

GETメソッドはURLにクエリ文字列の形でパラメータを渡すが、URLの長さには上限がある。 多量が多い場合には、POSTメソッドを使うほうが安全。

秘密情報をPOSTで送信すべき理由は、GETだと下記の可能性があるため。

  • URL上に指定されたパラメータがReferer経由で漏洩する
  • URL上に指定されたパラメータがアクセスログに残る
  • URL上のパラメータがブラウザのアドレスバーに表示され他人にのぞかれる
  • パラメータつきのURLを利用者がソーシャルネットワークなどで共有してしまう

以下が1つでもあてはまる場合はPOSTを使う

  • データ更新など副作用をともなうリクエスト
  • 秘密情報を送信
  • 送信するデータの総量が多い

hiddenパラメータ

利用者の入力した値はhiddenパラメータとして、HTML上に記述されている。
HTTPはFTP、talnetとは異なり、クライアントの現在の状態を覚えておく設計になっていない。
=> HTTPのステートレス性という。
※ 現在の状態を覚えているプロトコルは、ステートフルという

HTTPというレイヤーでは、ブラウザ上では変更できない値も、書き換え可能。

hiddenパラメータのメリット

  • hiddenは利用者自身からは書き換え可能だが、情報漏洩や第三者からの書き換えに対しては堅牢

クッキーやセッション変数は、セッションIDの固定化攻撃に弱いのが欠点。
このため、利用者自身によっても書き換えられて困る認証や許可に関する情報はセッション変数に保存すべき。 それ以外は、まずhiddenパラメータに保存することを検討する。特に、ログイン前は認証・許可に関する情報はないはずなので、 原則としてセッション変数の使用を避ける。

ステートレスなHTTP認証

HTTP認証と総称されるが、実装方式によってBasic認証、NTLM認証、Digest認証などがる。
HTTPステートレスなプロトコルなのでHTTP認証もステートレス。

Basic認証は、認証が必要なページにリクエストがあると、いったん401 Unauthorized(認証が必要なのにされてない)というステータスを返す。 ユーザ名とパスワードを入力すると、再度HTTPリクエストメッセージが送信される。その際、以下のAuthorizationヘッダが付与される。

Authorization: Basic dXN1cjE6cGFzczE=

Basicの後ろの文字列はIDとパスワードを:で区切ってつなげてBase64でエンコードしたもの。
dXN1cjE6cGFzczE=をデコードするとuser1:pass1という文字列になる。

一度Basic認証に成功すると、Basic認証がかけられているディレクトリにリクエストがあったときに、自動的にAuthorizationへっだを付与する。