︎ネットワークセキュリティ@セキュリティ¶
はじめに¶
本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。
01. 【L2
~L4
】ネットワークファイアウォール¶
ネットワークファイアウォールとは¶
L2
(データリンク層) からL4
(トランスポート層) までに対するサイバー攻撃 (例:そもそものネットワークへの侵入、ポートスキャンなど) を防御する。
ネットワークファイアウォールの種類¶
Webアプリファイアウォールの種類 | 説明 | 例 |
---|---|---|
ソフトウェア型 | 記入中... | 記入中... |
アプライアンス型 | 記入中... | 記入中... |
クラウド型 | クラウドプロバイダーが提供するネットワークファイアウォールを配置する。 | AWS NF (L2 〜L3 のみ)など |
パケットフィルタリング型ネットワークファイアウォール¶
▼ パケットフィルタリング型ネットワークファイアウォールとは¶
パケットのヘッダー情報の送信元IPアドレスやポート番号などに基づいて、パケットを許可する必要があるか否かを決める。
パケットのペイロードは検査しない。
ネットワークファイアウォールとwebサーバーの間には、NATルーターやNAPTルーターが配置されている。
- https://www.rworks.jp/system/system-column/sys-entry/21277/
- https://www.fenet.jp/infla/column/network/%E3%83%95%E3%82%A1%E3%82%A4%E3%82%A2%E3%82%A6%E3%82%A9%E3%83%BC%E3%83%AB%E3%81%AE%E7%A8%AE%E9%A1%9E5%E3%81%A4%EF%BD%9C%E6%B3%A8%E6%84%8F%E7%82%B9%E3%82%84%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88%E3%81%AB/
▼ iptables (Linux/Ubuntu) による標準的ネットワークファイアウォール¶
Linux/Ubuntuでのiptablesは、標準的なNAPTルーターかつパケットフィルタリング型ネットワークファイアウォールである。
特に、パケットフィルタリングのルールは、/etc/sysconfig/iptables
ファイルのfilter
テーブルで設定する。
iptables-save
コマンドでこのファイルを作成できる。
filter
テーブルで使用できるチェイン配下の通りである。
PREROUTING
とPOSTROUTING
は使用できない。
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. 【L3
~L6
】IPS:Intrusion Prevention System¶
IPSとは¶
L3
(ネットワーク層) からL6
(プレゼンテーション層) までに対するサイバー攻撃 (Dos攻撃、Synフラッド攻撃、パケットフラグメンテーション攻撃など) を遮断するセキュリティシステムのこと。
03. 【L3
~L6
】IDS:Intrusion Detection System¶
IDSとは¶
L3
(ネットワーク層) からL6
(プレゼンテーション層) までに対するサイバー攻撃を防御する。
不正アクセスと思われるパケットを検出する。
また、検出内容を管理者に通知する。
あくまで通知するのみで、攻撃を防御することはしない。
04. 【L3
~L7
】暗号化プロトコル¶
L3
(ネットワーク層) からL7
(アプリケーション層) までに対するサイバー攻撃を防御する。
05. 【L7
】Webアプリファイアウォール:Web Application Firewall¶
Webアプリファイアウォールとは¶
L7
(アプリケーション層) に対するサイバー攻撃 (SQLインジェクション、XSS、OSコマンドインジェクションなど) を防御する。
L7
を防御できていない場合、より低いレイヤー (例:L3
) を突破できれば (例:送信元IPアドレスの乗っ取り) 、L7
のサイバー攻撃 (SQLインジェクション、XSS、OSコマンドインジェクションなど) を実施できてしまうことになる。
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
パラメーター (フレームワークによっては、これに相当するパラメーター) や自前ヘッダーに割り当てて、レスポンスを返信する。
ワンタイムトークンの仕組み¶
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
(アプリケーション層) に対するサイバー攻撃 (例:CSRF、XSS) を防御する。
異なるドメインで表示されるページからのリクエストを許可する仕組みのこと。
デフォルトでは、異なるドメインで表示されるページからのリクエストは拒否されるようになっている。
異なるドメインで表示されるページからのリクエストを許可したい場合は、ページからのリクエストとサーバーからのレスポンスの両方で対応が必要である。
CORSの仕組み¶
*実装例*
(1)
-
リクエストの
Origin
ヘッダーに送信元オリジンを設定する。加えて、
Cookie
ヘッダーを持つリクエストを送信したい場合は、JavaScriptの実装でwithCredentials
オプションにtrue
を割り当てる。JavaScriptのパッケージによってオプション名が異なるため注意する。
GET https://example.com/bar
---
# 送信元オリジン
Origin: https://example.com
import axios from "axios";
const client = axios.create({
baseURL: "https://foo.co.jp",
withCredentials: "true", // オプションの有効化
});
return new Promise((resolve, reject) => {
client
.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: *
10. 【L7
】Set-Cookie
ヘッダー¶
Set-Cookie
ヘッダーとは¶
L7
(アプリケーション層) に対するサイバー攻撃 (例:XSS) を防御する。
属性を有効化することにより、リクエストヘッダーの作成を制限できる。
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文字) |
暗号アルゴリズムのバージョンを表す。他に、2 、2a 、2b 、2x がある。 |
$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、AWS API Gatewayを使用する。