これは、筆者の「2025振り返り用ひとりアドカレ」記事の一つです。
はじめに
本記事は、フロントエンドに携わっている筆者がwebセキュリティを学習した際にメモ書きしていたものを体系的にまとめ直した内容です。
かなり長くなったので7記事のシリーズとして投稿していきます。
これまでの開発において、エスケープ処理やサニタイズ、アクセス制御などセキュリティを意識して行ってきましたが、そもそも「どういった経緯で、どうなる(なってしまう)から、どのような対策が必要となるか」を深く理解できていない自覚がありました。
そこで【フロントエンド開発のためのセキュリティ入門 知らなかったでは済まされない脆弱性対策の必須知識】をベースに生成AIも使いながらインプットしていきました。
もちろん今でもまだまだだと思っていますし、本記事は備忘録の側面が強いかもしれませんが、初心者をはじめ、筆者のようにセキュリティ対策の重要性は理解しているがどこか表層的な部分に留まっているかもというような方々に少しでも役立つように書いていきたいと思います。
シリーズ目次
- 第1回:Web通信の基礎知識(本記事)
- 第2回:オリジンとCORS
- 第3回:サイドチャネル攻撃とSite Isolation
- 第4回:XSS(クロスサイトスクリプティング)
- 第5回:CSP(Content Security Policy)
- 第6回:CSRF、クリックジャッキング、その他の攻撃
- 第7回:認証・認可とセキュアな実装
前提として
- セキュリティの動向は時代背景や技術進歩、攻撃手法の変化から年々変わるものという意識を持つ
機能要件・非機能要件
web開発では機能要件・非機能要件という呼称でタスクを分別します。
機能要件はシンプルに「顧客からの要望」です。
他方、非機能要件は「わざわざ言語化しなくても対応してくれてるよね?」といったグレーゾーンな性質があり、考慮漏れするリスクがあります。
そのため、ここではIPA(情報処理推進機構)が出している非機能要求グレードなどを交えながら説明していきます。
機能要件
顧客からのヒアリングなどを通じて得る顧客要望(システムで必ず満たすべき)を指す
非機能要件
セキュリティ対策をはじめ、サイトのサーバ負荷対策、レスポンス速度、SEO対策など開発するシステムを利用する上で主目的にならないような事項を指す
- IPA(情報処理推進機構)が出している「非機能要求グレード」
「非機能要求グレード」は、「非機能要求」についてのユーザと開発者との認識の行き違いや、互いの意図とは異なる理解を防止することを目的とし、非機能要求項目を網羅的にリストアップして分類するとともに、それぞれの要求レベルを段階的に示したものです。重要な項目から順に要求レベルを設定しながら、両者で非機能要求の確認を行うことができるツール群です。
非機能要求の6つのカテゴリ
1. 可用性(Availability)
- 概要: システムがどれだけの時間、停止せずに稼働できるか
- 例: 稼働時間の割合(稼働率99.99%など)、障害時の復旧時間、メンテナンス時間帯の明示
2. 性能・拡張性(Performance and Scalability)
- 概要: システムの応答速度や処理能力、将来的な拡張のしやすさ
- 例: 画面表示の応答時間、同時アクセス数、スループット、拡張に要する工数や影響範囲
3. 運用・保守性(Operability and Maintainability)
- 概要: システムの運用のしやすさ、障害対応や変更対応のしやすさ
- 例: 障害発生時のログ出力内容、設定変更の容易さ、運用手順書の有無
4. 移行性(Portability)
- 概要: 他の環境やバージョンへシステムを移行する際の容易さ
- 例: データ移行の手段、OS変更時の対応範囲、バージョンアップ時の互換性
5. セキュリティ(Security)
- 概要: システムやデータを不正アクセスや破壊から守る能力
- 例: 認証方式、アクセス権管理、通信の暗号化、ログの改ざん防止
6. システム環境・エコロジー(System Environment and Ecology)
- 概要: システムが稼働するための環境条件や、環境負荷の配慮
- 例: 対応ブラウザ・OS、電力消費、設置スペース、利用端末制限
TCP/IP
IP(Internet Protocol)は聞いたことがある方も多いかと思います。これもよくある表現ですが、端的に言うと「インターネット上での住所」です。
TCPは Transmission Control Protocol といい、インターネットで使われる通信ルール(プロトコル)の一つで、データを確実に相手に届けることを目的とした「信頼性の高い通信」を実現する仕組みです。
相手と接続(コネクション)を確立してからデータを送り、届いたかどうかの確認(ACK)や、届かなかった場合の再送処理を行うため、Webサイト閲覧やメール送受信など、データの欠落が許されない場面で広く利用されています。
つまり、概念レベルで簡潔に抽象化すると「IPは場所」で「TCPはそこへの通信手段」というイメージですね。
TCP/IPの4つのレイヤーとその役割・代表的なプロトコル
アプリケーション層:レイヤー4(最上位)
- 主な役割: アプリケーションに応じた通信をする
- 代表的なプロトコル: HTTP, FTP, DNS, SMTP, POP3, IMAP
トランスポート層:レイヤー3
- 主な役割: インターネット層から受け取ったデータをどのアプリケーション層に渡すかを決めたり、データの誤りを検知したりする
-
代表的なプロトコル:
- TCP: 送信したデータを確実に相手に届けたい場合
- UDP: リアルタイム通信など速度を重視したい場合
インターネット層:レイヤー2
- 主な役割: どのコンピュータにデータを届ける(伝達経路の選択:ルーティングする)か決定する
- 代表的なプロトコル: IP, ICMP, ARP, IGMP
ネットワークインターフェース(データリンク)層:レイヤー1(最下位)
- 主な役割: 通信機器は文字や数字のデータをそのまま送ることができず、物理的に送信可能な電気信号に変換してデータをやりとりする。データリンク層は電気信号を相手に届けたり、電気信号の伝送制御や誤りの検知を行う
-
代表的なプロトコル:
- Ethernet: 有線LAN
- IEEE 802.11: 無線LAN
- Wi-Fi: 無線LAN(※Wi-FiはIEEE 802.11規格の商標名なので実質的には同じもの)
- PPP: Point-to-Point Protocol
実際の通信フロー例
以下のような階層構造により、各レイヤーは独立して機能し、保守性と拡張性を高めています。
データ送信時:
アプリケーション層 → トランスポート層 → インターネット層 → ネットワークインターフェース層
データ受信時(※送信時と逆順):
ネットワークインターフェース層 → インターネット層 → トランスポート層 → アプリケーション層
HTTPメッセージ
HTTP(Hyper Text Transfer Protocol)は、簡潔に言うと「クライアントとサーバがデータを適切にやり取りするための決まり事」を指します。
少し踏むこむと、HTTP自体は「どのような形式でリクエストとレスポンスをやり取りするか」を定めたアプリケーション層の通信ルールです。
また現在主流のHTTPS通信では、このHTTP通信の前段で TLSによる証明書の検証や暗号化通信の確立(ハンドシェイク) が行われ、その上でHTTP通信が実行されます。
HTTPメッセージの形式
リクエストとレスポンスの2種類あるが形式は以下同じ
開始行
----------
メッセージヘッダ
----------
空白行
----------
メッセージボディ
HTTPリクエスト
HTTPによるブラウザとサーバの通信は、ブラウザからサーバへ要求を送ることからはじまる。
この要求を送ることをリクエスト(処理要求)という。
# リクエストライン
POST / HTTP/1.1
# ヘッダ:2行目から空白行まで
Host: localhost:8080
Connection: keep-alive
...
..
.
Cache-Control: max-age=0
# 空白行(ここまでヘッダ)
# ボディ:以降の行
id=1&user=hoge
- リクエストライン
GETやPOSTといったHTTPメソッドをはじめ、リソースのパス名、HTTPバージョンが含まれている - ヘッダ
ブラウザの情報や接続に関する情報などデータのやりとりに必要な付加情報が含まれている - ボディ
リクエスト本文。取得したい情報のキーワードや登録したい情報が記載されている(※リクエスト内容によってはボディが空の場合もある)
-
OPTIONSメソッド
HTTPメソッドの一つで、サーバがサポートしているHTTPメソッドを確認する -
Access-Control-Max-Ageヘッダ
常時プリフライトリクエストを行うと、ネットワーク環境が低速な場合や大量のリクエストを送る場合などにおいてパフォーマンス面で支障をきたす可能性がある。そこで、プリフライトリクエストの内容をキャッシュさせておく際にAccess-Control-Max-Ageヘッダを使用する。
# キャッシュ時間:1時間
Access-Control-Max-Age: 3600
代表的なリクエストヘッダ
開発者ツールのNetworkパネルから確認可能
Host
- 概要: リクエスト先のホスト名とポート番号を指定
- 例:
Host: www.example.com
User-Agent
- 概要: クライアントのブラウザやアプリケーションの情報を送信
- 例:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Accept
- 概要: クライアントが受け入れ可能なコンテンツタイプを指定
- 例:
Accept: text/html,application/json
Accept-Language
- 概要: クライアントが希望する言語を指定
- 例:
Accept-Language: ja,en-US;q=0.9
Accept-Encoding
- 概要: クライアントが対応している圧縮方式を指定
- 例:
Accept-Encoding: gzip, deflate, br
Authorization
- 概要: 認証情報(トークンやパスワード)を送信
- 例:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Cookie
- 概要: 以前にサーバから送信されたクッキーを送信
- 例:
Cookie: session_id=abc123; user_pref=dark_mode
Referer
- 概要: リクエストの元となったページのURLを指定
- 例:
Referer: https://www.google.com/search?q=example
If-Modified-Since
- 概要: 指定日時以降に更新されたリソースのみを要求
- 例:
If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT
HTTPレスポンス
リクエスト(ブラウザからサーバへの処理要求)に応じて、サーバが送信する情報をレスポンスという。
# ステータスライン
HTTP/1.1 200 OK
# ヘッダ:2行目から空白行まで
content-encoding: gzip
content-type: text/html;
...
..
.
content-length: 648
# 空白行(ここまでヘッダ)
# ボディ:以降の行
<!doctype html>
<html>
...
..
.
- ステータスライン
リクエストに応じたサーバの処理結果。200:正常終了, 400系:クライアントエラー, 500系:サーバエラー - ヘッダ
サーバに関する情報や送信したリソースの形式などの付加情報が含まれている - ボディ
レスポンス本文。リクエストされた情報やサーバの処理結果などが記載されている(※リクエスト内容によってはボディが空の場合もある)
代表的なレスポンスヘッダ
開発者ツールのNetworkパネルから確認可能
Status
- 概要: HTTPステータスコードとメッセージを示す
- 例:
200 OK,404 Not Found,500 Internal Server Error
Server
- 概要: サーバーソフトウェアの情報を送信
- 例:
Server: Apache/2.4.41 (Ubuntu)
Set-Cookie
- 概要: クライアントにクッキーを設定(保存)するよう指示
- 例:
Set-Cookie: SESSION_ID=abc123; Path=/; HttpOnly-
保存形式:
SESSION_ID: abc123(キー: 値)
-
保存形式:
Location
- 概要: リダイレクト先のURLを指定(主に3xxステータスで使用)
- 例:
Location: https://www.example.com/new-page
Cache-Control
- 概要: キャッシュの動作を制御
- 例:
Cache-Control: no-cache, must-revalidate
Expires
- 概要: リソースの有効期限を指定
- 例:
Expires: Wed, 21 Oct 2015 07:28:00 GMT
Last-Modified
- 概要: リソースが最後に更新された日時を示す
- 例:
Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT
ETag
- 概要: リソースの固有識別子(バージョン管理用)
- 例:
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
WWW-Authenticate
- 概要: 認証が必要な場合の認証方式を指定
- 例:
WWW-Authenticate: Basic realm="Restricted Area"
HTTPメソッド
- 冪等性(べきとうせい)
これは「何度処理をしても必ず同じ結果になる性質」を指します。以降に何度も出てくるので先に説明しておきます。
※HTTPにおいては「同じリクエストを何度送っても、サーバの“最終状態”が変わらない」といったイメージです。
-
GET
- 役割: サーバからリソースを取得する
- 特徴: 安全で冪等性がある
- 使用例: Webページの表示、データの取得
-
POST
- 役割: サーバにデータを送信して新しいリソースを作成する
- 特徴: 安全ではなく、冪等性もない
- 使用例: フォームの送信、ユーザー登録、データの作成
-
PUT
- 役割: サーバ上のリソースを更新または新規作成する
- 特徴: 冪等性がある
- 使用例: ファイルのアップロード、データの完全更新
-
DELETE
- 役割: サーバ上のリソースを削除する
- 特徴: 冪等性がある
- 使用例: ファイルの削除、ユーザーアカウントの削除
-
HEAD
- 役割: GETと同じだが、レスポンスボディを返さずヘッダのみを取得
- 特徴: 安全で冪等性がある
- 使用例: リソースの存在確認、メタデータの取得
-
CONNECT
- 役割: プロキシサーバを通じてSSL/TLSトンネルを確立する
- 特徴: 主にHTTPS通信でプロキシを経由する際に使用(※通信先の制限などをしないと攻撃者に悪用されるリスクがある)
- 使用例: プロキシサーバ経由でのHTTPS接続、VPN接続
-
OPTIONS
- 役割: サーバがサポートしているHTTPメソッドを確認する
- 特徴: 安全で冪等性がある
- 使用例: CORS(Cross-Origin Resource Sharing)での事前確認
-
PATCH
- 役割: リソースの部分的な更新を行う
- 特徴: 冪等性は実装によって異なる
- 使用例: ユーザー情報の一部更新、設定の変更
-
TRACE(現在ではほとんど使用されていない)
- 役割: クライアントのリクエストがサーバに到達するまでの経路を確認
- 特徴: 安全で冪等性がある
- 使用例: デバッグ、ネットワーク診断(セキュリティ上の理由で無効化されることが多い)
代表的なエンティティヘッダ
リクエストとレスポンスのどちらにも使えるHTTPヘッダのことをエンティティヘッダという。
Content-Type
- 概要: 送信データ(リソース)のメディアタイプを指定
- 例:
Content-Type: application/json; charset=utf-8
Content-Length
- 概要: 送信データ(リソース)のバイト数を指定
- 例:
Content-Length: 1024
Content-Encoding
- 概要: データの圧縮方式を指定
- 例:
Content-Encoding: gzip
Content-Language
- 概要: データの言語を指定
- 例:
Content-Language: ja
Content-Location
- 概要: データの元となる場所のURLを指定
- 例:
Content-Location: /documents/report.pdf
Content-Disposition
- 概要: データの処理方法を指定(インライン表示またはダウンロード)
- 例:
Content-Disposition: attachment; filename="report.pdf"
Content-Range
- 概要: 部分的なデータ送信時の範囲を指定
- 例:
Content-Range: bytes 200-1023/2048
Allow
- 概要: リソースで使用可能なHTTPメソッドを指定
- 例:
Allow: GET, POST, PUT, DELETE
HTTPSの仕組み
HTTPSとは、暗号化されておらず、改ざんなどのリスクがあるHTTP(通信)の危険性を回避するための技術であり通信規格を指します。
TLS(Transport Layer Security)
HTTPSは、TLSという通信プロトコルを用いてHTTPデータを暗号化して通信している
- HTTPデータをやり取りする前に、TLSハンドシェイクという一連の手順によって暗号通信を確立する
TLSでの通信では、通信データの暗号化、通信相手の検証、通信データの改ざんチェックなどを実現する
TLSによる 通信相手の検証
電子証明書を用いて通信相手が本物かどうかを検証する。電子証明書は、認証局(CA)と呼ばれる社会的に信頼されている機関が発行していて、サーバから送信された電子証明書が正しいかどうかをブラウザが検証する。
あらかじめ、ブラウザやOSには電子証明書が組み込まれていて、それらと照合する仕組みなので、もしCAから発行されていない電子証明書が使用されている場合にブラウザは警告画面(例:この接続ではプライバシーが保護されません)を表示する。
つまり、サーバ側は必ず信用できるCAから発行される電子証明書を用いなければならない。
TLSによる 通信データの改ざんチェック
改ざんがなかったことを証明するために認証タグという検証用データをTLSは用いる。認証タグはデータの暗号化と同時に作成され、通信相手に送信される。
受信側は復号と同時に認証タグを使って暗号文の改ざんチェックを実施し、もし形跡があった場合は通信は行われずにエラー処理される。ちなみに、改ざんチェックに関しては、TLSハンドシェイク中にも実施されている。
HTTPS通信でないと処理できない内容(Secure Context)
-
Service Workers
オフラインでもwebアプリケーションを表示可能とする機能 -
Payment Request API
web上の決済を手軽に実現するための機能。ブラウザに記憶させた決済情報を使って決済が行える
上記のような機能はWebサービスや開発の拡充に有用だが、Payment Request API など悪用されるとリスクの高いものもある。そのため、これら機能に関しては「安全なコンテキスト(Secure Context)」上でのみ利用可能となっている。具体的には以下の条件を満たすと Secure Context とみなされる。
- https:// または wss:// といった暗号通信で配信されている
- http://localhost, http://127.0.0.1, file:// といったローカルホスト通信
※Secure Contextを要件としているブラウザの機能は先の2つ以外にもたくさんある
Mixed Contentの危険性
Mixed Content とは(HTTPS化されたWebアプリケーション内で)https通信またはhttp通信で読み込んでいるファイルが一つのwebページ内で混在している際に発生する警告を指す。
Passive mixed content(画像や音声、動画ファイルなど)はそこまでリスクはないものの、Active mixed content(JavaScriptやCSSファイルなど)というプログラムに影響を与えるものが Mixed Content の場合はリスクが高まる。
※Chrome, Firefox, Safari など主要ブラウザは、別サイトから配信されている Active mixed content のサブリソースへのアクセスをブロックしている。
- 例:
Mixed Content: The page at 'https://exmaple-hoge/app/' was loaded over HTTPS, but requested an insecure stylesheet ...中略.
This request has been blocked; the content must be served over HTTPS.
用語集
CDN(Content Delivery Network)
Webページのリソースを高速かつ効率よく配信するためのサーバを提供する仕組みです。
世界中にサーバを用意することで、遠い国で開発されているWebアプリケーションでも、近くのCDNサーバからコンテンツ(※主にJavaScriptやCSSといった各種ライブラリまたは画像ファイルなど)を取得することができ、Webページの表示を高速化できます。
オリジンサーバに都度問い合わせるのではなく、近場にデータをキャッシュしておいて、それを参照する「エッジコンピューティング」の仕組みに似ています。
さいごに
ここまで読んでいただき、ありがとうございました。
筆者の知識・経験不足から間違った点や、誤解を招きかねない表現がありましたらご教示・ご指摘いただけますとありがたい限りです。