コンテンツにスキップ

︎ネットワークセキュリティ@セキュリティ

はじめに

本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。


01. 脅威モデル

  • なりすまし
  • 改竄
  • 否認
  • 情報漏洩
  • DoS (サービス拒否)
  • 特権昇格


01. 【L2L4】ネットワークファイアウォール

ネットワークファイアウォールとは

L2 (データリンク層) から L4 (トランスポート層) までに対するサイバー攻撃 (例:そもそものネットワークへの侵入、ポートスキャンなど) を防御する。


ネットワークファイアウォールの種類

Webアプリファイアウォールの種類 説明
ソフトウェア型 記入中... 記入中...
アプライアンス型 記入中... 記入中...
クラウド型 クラウドプロバイダーが提供するネットワークファイアウォールを配置する。 AWS NF (L2L3 のみ)など

security_protection-type


パケットフィルタリング型ネットワークファイアウォール

▼ パケットフィルタリング型ネットワークファイアウォールとは

パケットのヘッダー情報の送信元 IP アドレスやポート番号などに基づいて、パケットを許可する必要があるか否かを決める。

パケットペイロードは検査しない。

ネットワークファイアウォールと Web サーバーの間には、NAT ルーターや NAPT ルーターが配置されている。

パケットフィルタリング

▼ iptables (Linux/Ubuntu) による標準的ネットワークファイアウォール

Linux/Ubuntu での iptables は、標準的な NAPT ルーターかつパケットフィルタリング型ネットワークファイアウォールである。

特に、パケットフィルタリングのルールは、/etc/sysconfig/iptables ファイルの filter テーブルで設定する。

iptables-save コマンドでこのファイルを作成できる。

filter テーブルで使用できるチェイン配下の通りである。

PREROUTINGPOSTROUTING は使用できない。

filter テーブルで使用できるチェイン名 説明
INPUT 受信を許可/拒否する対象のパケットを定義する。
OUTPUT 送信を許可/拒否する対象のパケットを定義する。
FORWARD フォワーディングを許可/拒否する対象のパケットを定義する。

*例*

$ cat /etc/sysconfig/iptables

...

*filter
:INPUT DROP [5:300]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [32:3205]
# 22番ポートと80番ポート宛てのTCPスリーウェイハンドシェイクを許可する。
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
COMMIT

...

▼ firewalld (CentOS) による標準的ネットワークファイアウォール

CentOS での firewalld は、標準的なパケットフィルタリング型ネットワークファイアウォールである。

デフォルトでは、すべてのインバウンド通信が拒否、すべてのアウトバウンド通信が許可、となっている。

*例*

アクセスが許可されているポート番号を確認する。

$ firewall-cmd --list-all

public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: ssh dhcpv6-client
  ports: 22/tcp 80/tcp 443/tcp # アクセスを許可するポート番号
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

アクセスが許可されている送信元 IP アドレスを確認する。

$ firewall-cmd --get-active-zones

foo-cidr
  sources: 192.168.128.0/23
public
  interfaces: ens192

▼ Windowsネットワークファイアウォール (Windows) による標準的ネットワークファイアウォール

Windows ネットワークファイアウォールは、Windows におけるネットワークファイアウォールである。

パケットフィルタリングの設定

*例*


ゲートウェイ型ネットワークファイアウォール (プロキシサーバー型)

パケットペイロードに基づいて、パケットを許可する必要があるか否かを決める。


サーキットレベル型ネットワークファイアウォール

L4 (トランスポート層) の段階でサイバー攻撃を遮断するネットワークファイアウォールのこと。


02. 【L3L6】IPS:Intrusion Prevention System

IPSとは

L3 (ネットワーク層) から L6 (プレゼンテーション層) までに対するサイバー攻撃 (Dos 攻撃、Syn フラッド攻撃、パケットフラグメンテーション攻撃など) を遮断するセキュリティシステムのこと。

security_protection-type


03. 【L3L6】IDS:Intrusion Detection System

IDSとは

L3 (ネットワーク層) から L6 (プレゼンテーション層) までに対するサイバー攻撃を防御する。

不正アクセスと思われるパケットを検出する。

また、検出内容を管理者に通知する。

あくまで通知するのみで、攻撃を防御することはしない。

IDS


04. 【L3L7】暗号化プロトコル

L3 (ネットワーク層) から L7 (アプリケーション層) までに対するサイバー攻撃を防御する。


04. 【L3L4】IPアドレス、プロトコル、ポート番号制限

Amazon EC2 Security Groupとは

L3 (ネットワーク層) から L4 (トランスポート層) までに対するサイバー攻撃を防御する。

IP アドレスの制限は L3 防御、プロトコルとポート番号制限は L4 防御である。


05. 【L7】Webアプリファイアウォール:Web Application Firewall

Webアプリファイアウォールとは

L7 (アプリケーション層) に対するサイバー攻撃 (例:SQL インジェクション、XSS、CSRF、パストラバーサル) を防御する。

L7 を防御できていない場合、より低いレイヤー (例:L3) を突破できれば (例:送信元 IP アドレスの乗っ取り) 、L7 のサイバー攻撃を実施できてしまうことになる。

security_protection-type


Webアプリファイアウォールの種類

Webアプリファイアウォールの種類 説明
ソフトウェア型 Webアプリファイアウォールの能力を持つソフトウェアを自社サーバーにセットアップし、これを配置する。 SuiteGuard、SmartCloudなど
アプライアンス型 Webアプリファイアウォールのソフトウェアがすでにセットアップされたハードウェアを購入し、これを配置する。 FortiWeb、Imperva SecureSphere、SiteGuardなど
クラウド型 クラウドプロバイダーが提供するWebアプリファイアウォールを配置する。 AWS WAF、Google Cloud Armor、Cloudbric、Scutum、CrowdStrikeなど


06. 【L7】チェックサム

チェックサムとは

L7 (アプリケーション層) に対するサイバー攻撃を防御する。

sha256 によって作成された文字列をファイル情報として添付し、これを送受信の両方のアプリケーション側で照合することにより、通知途中でファイルが改竄されていないことを保証する。

L7 のアプリケーションデータを暗号化/復号するわけではない。


07. 【L7】ワンタイムトークン

ワンタイムトークンとは

L7 (アプリケーション層) に対するサイバー攻撃 (例:CSRF) を防御する。

認証時に、セッション ID のみでなく、ワンタイムトークンも併用する。

認証フォームがリクエストされたとき、サーバー側でワンタイムトークンを発行する。これを Set-Cookie ヘッダーの csrftoken パラメーター (フレームワークによっては、これに相当するパラメーター) や自前ヘッダーに割り当てて、レスポンスを返信する。

csrf-token


ワンタイムトークンの仕組み

200 OK
---
Set-Cookie: csrftoken=<トークン>
# 自前ヘッダー
X-CSRF-TOKEN: <トークン>
(1)

ブラウザではレスポンスヘッダーからワンタイムトークンを取り出し、認証フォームの input タグの hidden 属性に割り当てる。

他に、metaタグにトークンを割り当てることもある。

<form method="POST" action="http://example.com/bar-form.php">
  <input type="hidden" name="csrftoken" value="<csrfトークン>" />
  <input type="text" name="email" />
  <input type="text" name="password" />
  <input type="submit value="ログイン">
</form>
<head>
  <meta name="csrftoken" content="<ヘッダーから取り出したトークン>" />
</head>
(2)

認証のための POST リクエスト時に、リクエストボディや自前ヘッダーにアクセストークンを割り当て、リクエストを送信する。

どちらを使用するかは、バックエンド側の仕様によって異なる。

POST https://example.com/bar-form.php
---
# 自前ヘッダー
x-csrf-token: <トークン>
---
# ボディ
{_token=<トークン>}
(3)

サーバー側では、POST リクエストによって送信されたトークンとワンタイムトークンを比較し、認証する。

以降、POSTリクエストの場合はそのワンタイムトークンを使い回し、GETリクエストの場合は使用しない。

トークンが変更されていれば、誤った入力フォームからのリクエストとして判定し、401ステータスを返却する。


08. 【L7】パラメーターの制限

パラメーターの制限とは

L7 (アプリケーション層) に対するサイバー攻撃 (例:SQL インジェクション) を防御する。

アプリケーションで、任意のパラメーターを入力できないようにする。


特殊な文字列の無効化

DB の SQL クエリのパラメーターとなる入力では、『シングルクオーテーション』や『バックスラッシュ』などは SQL で特別な意味を持つ。

そのため、これらのパラメーターが割り当てられているリクエストを拒否する。

例えば、Web アプリファイアウォールを使用する。


プレースホルダー

プリペアードステートメントの SQL 中にパラメーターを設定し、値をパラメーターに渡したうえで、SQL として発行する。

処理速度が速い。

また、パラメーターに誤って SQL が渡されても、型をチェックすることにより、実行できなくなるようにできる。

そのため、SQL インジェクションの対策になる。


09. 【L7】CORS:Cross-Origin Resource Sharing (オリジン間リソース共有)

CORSとは

L7 (アプリケーション層) に対するサイバー攻撃 (例:SQL インジェクション、XSS、CSRF、パストラバーサル) を防御する。

異なるドメインのクライアントからのリクエストを拒否する仕組みである。

ブラウザではデフォルトで CORS が有効になっており、正しいリクエストが CORS を突破できるように対処する必要がある。

異なるドメインクライアントからのリクエストを許可したい場合は、リクエストとレスポンスの両方で対応が必要である。

cors


CORSの突破

リクエストの Origin ヘッダーとレスポンスの Access-Control-Allow-Origin ヘッダーの値を同じにする必要がある。

リクエストの Origin ヘッダーは、デフォルトで『プロトコル + ドメイン + ポート番号』に設定されるため、特に対処する必要はない。

レスポンスの Access-Control-Allow-Origin ヘッダーは、リクエストの Origin ヘッダーと同じ値あるいはワイルドカード (*) とする必要がある。

*実装例*

(1)

リクエストの Origin ヘッダーに送信元オリジンを設定する。

加えて、Cookieヘッダーを持つリクエストを送信したい場合は、JavaScriptの実装でwithCredentialsオプションにtrueを割り当てる。

JavaScriptのパッケージによってオプション名が異なるため注意する。

GET https://example.com/bar
---
# 送信元オリジン
Origin: https://example.com
import axios from "axios";

const instance = axios.create({
  // Originヘッダーはデフォルトで『プロトコル + ドメイン + ポート番号』に設定されるため、特に対処する必要はない。
  baseURL: "https://foo.co.jp",
  // Cookieヘッダーを設定する
  withCredentials: "true",
});

return new Promise((resolve, reject) => {
  instance
    .get("/bar")
    .then((data) => {
      resolve(data);
    })
    .catch((err) => {
      reject(err);
    });
});
(2)

必須の設定として、レスポンスの Access-Control-Allow-Origin ヘッダーに、許可された送信元オリジンやワイルドカード (*) を割り当てて返信する。

Cookieヘッダーを持つリクエストを許可する場合、同じくレスポンスのAccess-Control-Allow-Credentialsヘッダーにtrueを割り当てる。

その他、許可するHTTPメソッドやHTTPヘッダーも定義できるが、必須ではない。

例えば、許可されていないHTTPメソッドを使用して、異なるオリジンにリクエストを送信すると、405ステータスでエラーレスポンスが返信される。

200 OK
---
# 許可された送信元オリジン
Access-Control-Allow-Origin: https://example.com
# リクエストがCookieヘッダーを持つことを許可する場合
Access-Control-Allow-Credentials: "true"
# 許可するHTTPメソッド
Access-Control-Allow-Methods: GET,POST,HEAD,OPTIONS
# その他、許可するHTTPヘッダー
Access-Control-Allow-Headers: Content-Type

補足として、Cookie ヘッダーを持つリクエストを許可しない場合に限り、すべてのオリジンやヘッダーを許可できる。

200 OK
---
# 全てのオリジンを許可
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: *


L7 (アプリケーション層) に対するサイバー攻撃 (例:SQL インジェクション、XSS、CSRF、パストラバーサル) を防御する。

属性を有効化することにより、リクエストヘッダーの作成を制限できる。


Domain属性

▼ Domain属性とは

リクエストが Cookie ヘッダーを持つことを許可した場合、サブドメイン名のオリジンにも Cookie ヘッダーの送信を許可するか否かを制御できる。

サブドメイン名のレスポンスの Set-Cookie ヘッダーにて、Domain 属性にドメインが割り当てなかった場合は、ページを表示するサーバーのドメインにのみ Cookie ヘッダーを持つリクエストを許可でき、サブドメイン名への送信を拒否できる。

一方で、ドメインが割り当てた場合は、そのページからサブドメイン名に対しても、Cookie ヘッダーを持つリクエストを許可できる。

ドメインではなく、オリジンであることに注意する。

▼ Domain属性の仕組み

*実装例*

Domain 属性に example.com が割り当てられていたとする。

最初にドットがついているドメイン (.example.com) でも、同じ値として認識される。

この場合、example.com に加えて、サブドメイン名 (foo.example.com) に対しても、Cookie ヘッダーを持つリクエストを送信できる。

200 OK
---
Set-Cookie: domain=example.com
POST http://foo.example.com/bar-form.php
---
# 送信元オリジン
Origin: https://example.com
Cookie: sessionid=<セッションID>; csrftoken=<トークン>


HttpOnly属性

▼ HttpOnly属性とは

これを有効化した場合、Set-Cookie ヘッダーに HttpOnly 属性が割り当てられるようになる。

JavaScript から Cookie ヘッダーにアクセスできなくできる。

200 OK
---
Set-Cookie: HttpOnly


sameSite属性

▼ sameSite属性とは

属性値 説明
None 異なるドメインから受信したすべてのリクエストが Cookie ヘッダーを持つことを許可する。
Lax 異なるドメインから受信した一部のリクエストが Cookie ヘッダーを持つことを許可する。
Strict 異なるドメインから受信したすべてのリクエストが Cookie ヘッダーを持つことを拒否する。

異なるドメインからのリクエストが Cookie ヘッダーを持つことを許可/拒否する。

ここでリクエストを制御しているのは、オリジンではなく、ドメインであることに注意する。

200 OK
---
Set-Cookie: SameSite=None


Secure属性

▼ Secure属性とは

これを有効化した場合、Set-Cookie ヘッダーに Secure 属性が割り当てられるようになる。HTTPS プロトコルを使用した場合のみ、リクエストに Cookie ヘッダーを割り当てられるようになる。

200 OK
---
Set-Cookie: Secure


11. 【L7】認証/認可情報の複雑化

認証/認可情報の複雑化とは

L7 (アプリケーション層) に対するサイバー攻撃 (例:SQL インジェクション) を防御する。

認証/認可で必要になる情報を簡単に特定できないようにする。


BCryptによるハッシュ化

▼ BCryptによるハッシュ化

BCrypt を使用して、Blowfish 方式に基づく暗号化を実行する。

Blowfish 方式では、同じパスワードの文字列であっても異なるハッシュ値が作成されるため、レインボー攻撃を防げる。

Blowfish 方式で作成されたハッシュ値は、異なるルールで作成された複数のハッシュ値の組み合わせである。

▼ 構造

# <アルゴリズムバージョン> + <ストレッチング回数> + <ランダム文字列> + <パスワードハッシュ値>
$2y$10$1QVmWNzk.TsaZQLQ/zeI9OAZL02AWP.VdFPPyAc9hSc2Cp4yOXKtG
文字列 説明
$2y$ (4文字) 暗号アルゴリズムのバージョンを表す。他に、22a2b2x がある。
$10$ (4文字) ストレッチング (ハッシュ化の反復) の回数を表す。10 とした場合は、2^10回反復でハッシュ化を実行する。
1QVmWNzk.TsaZQLQ/zeI9O (22文字) ソルト (ランダムな文字列) を表す。
AZL02AWP.VdFPPyAc9hSc2Cp4yOXKtG (31文字) パスワードそのもののハッシュ値を表す。


12. 【L7】アプリケーションのリクエスト数制限

リクエスト数制限とは

L7 に対するサイバー攻撃 (例:Dos 攻撃、DDos 攻撃など) を防御する。


POSTリクエストのリクエスト制限

*実装例*

php.ini ファイルにて、一度に受信できる POST リクエストの上限値を設定できる。

max_input_vars = 1000


同一送信元のリクエスト制限

同じ送信元からの 1 分間当たりのリクエスト数を制限する。

例えば、AWS WAF、Amazon API Gateway を使用する。