NICによるWebアプリのセキュリティ #### この章では、実際にデプロイしたNGINX Ingress Controllerを使い、Webアプリケーションに対するWAF・DoS対策の実施方法を確認します。 設定例は `NGINX Inc GitHubの examples/custom-resources/ `__ に管理されております Syslog Serverのデプロイ ==== NGINX App Protect WAF、NGINX App Protect DoS 双方のセキュリティモジュールのログをSyslogサーバに転送し、結果を確認します。 まずはじめにSyslogサーバをデプロイします。 | ``syslog.yaml`` は、NAP WAF、NAP DoSで利用します。 | ``syslog2.yaml`` は、NAP DoSで利用します Syslogイメージのデプロイ .. code-block:: cmdin cd ~/kubernetes-ingress/examples/custom-resources/app-protect-dos kubectl apply -f syslog.yaml kubectl apply -f syslog2.yaml デプロイされた内容の確認 .. code-block:: cmdin kubectl get deployment .. code-block:: bash :linenos: :caption: 実行結果サンプル NAME READY UP-TO-DATE AVAILABLE AGE syslog 1/1 1 1 9m syslog-2 1/1 1 1 9m .. code-block:: cmdin kubectl get svc| grep syslog-svc .. code-block:: bash :linenos: :caption: 実行結果サンプル syslog-svc ClusterIP 10.96.250.209 514/TCP 9m syslog-svc-2 ClusterIP 10.103.224.109 514/UDP 9m Ingress Controller で WAF機能(NGINX App Protect WAF) のデプロイ ==== https://github.com/nginxinc/kubernetes-ingress/tree/v3.1.1/examples/custom-resources/app-protect-waf サンプルアプリケーションをデプロイ ---- アプリケーションをデプロイします。 .. code-block:: cmdin cd ~/kubernetes-ingress/examples/custom-resources/app-protect-waf kubectl apply -f webapp.yaml kubectl apply -f ap-apple-uds.yaml kubectl apply -f ap-dataguard-alarm-policy.yaml kubectl apply -f ap-logconf.yaml kubectl apply -f waf.yaml kubectl apply -f virtual-server.yaml Syslogサーバのログの出力状況を確認します。新たに同ホストへ接続するターミナルを1つ用意し、ログを表示してください SyslogサーバのPod名を確認します .. code-block:: cmdin kubectl get pod .. code-block:: bash :linenos: :caption: 実行結果サンプル NAME READY STATUS RESTARTS AGE syslog-2-96dfdf5c6-7t8d4 1/1 Running 0 1h syslog-cccc648c6-2n9v4 1/1 Running 0 1h webapp-64d444885-bgrj7 1/1 Running 0 6m syslog、それぞれのPOD名を参考に、追加するターミナルでログを表示してください。 .. code-block:: cmdin # 追加するターミナル1 で 'syslog' の情報を表示する kubectl exec -it -- tail -f /var/log/messages リソースを確認 ---- ポイントとなるファイルの内容を確認します。 NAP WAFのPolicyでは様々なセキュリティ機能を用いて外部からの攻撃をブロックします。 外部からの様々な攻撃を通信の特徴や、リクエストに含まれる文字列などから検知・ブロックするためのルールとしてSignatureがあります。 NAP WAFではお客様アプリケーションに合わせた制御や、特定の通信を制御するため、ユーザ定義シグネチャ(User-Defined Signature)の定義が可能です | こちらで設定する ``ユーザ定義シグネチャ`` の詳細は、以下の内容を参照してください。 | `NGINX App Protect WAF Configuration Guide/User-Defined Signatures `__ | NGINX Ingress Controller での NAP WAF の詳細は、以下のページを参照してください。 | `NGINX Ingress Controller Configuration/App Protect User Defined Signatures `__ | ``ap-apple-uds.yaml`` は、ユーザ独自のシグネチャの定義となります。 | 条件は ``rule`` に指定された内容となります。また、tagとして ``Fruits`` を指定します。 .. code-block:: yaml :linenos: :caption: ap-apple-uds.yaml :emphasize-lines: 13,18 apiVersion: appprotect.f5.com/v1beta1 kind: APUserSig metadata: name: apple spec: signatures: - accuracy: medium attackType: name: Brute Force Attack description: Medium accuracy user defined signature with tag (Fruits) name: Apple_medium_acc risk: medium rule: content:"apple"; nocase; signatureType: request systems: - name: Microsoft Windows - name: Unix/Linux tag: Fruits ``ap-dataguard-alarm-policy.yaml`` は、App ProtectのPolicy設定となります。tagとして ``Fruits`` を持つシグネチャを参照・有効にしています .. code-block:: yaml :linenos: :caption: ap-dataguard-alarm-policy.yaml :emphasize-lines: 4,8,14 apiVersion: appprotect.f5.com/v1beta1 kind: APPolicy metadata: name: dataguard-alarm spec: policy: signature-requirements: - tag: Fruits signature-sets: - name: apple_sigs block: true signatureSet: filter: tagValue: Fruits tagFilter: eq applicationLanguage: utf-8 blocking-settings: violations: - alarm: true block: false name: VIOL_DATA_GUARD data-guard: creditCardNumbers: true enabled: true enforcementMode: ignore-urls-in-list enforcementUrls: [] lastCcnDigitsToExpose: 4 lastSsnDigitsToExpose: 4 maskData: true usSocialSecurityNumbers: true enforcementMode: blocking name: dataguard-alarm template: name: POLICY_TEMPLATE_NGINX_BASE ``ap-logconf.yaml`` は、Logの定義に関する設定となります。 .. code-block:: yaml :linenos: :caption: ap-logconf.yaml :emphasize-lines: 4 apiVersion: appprotect.f5.com/v1beta1 kind: APLogConf metadata: name: logconf spec: content: format: default max_message_size: 64k max_request_size: any filter: request_type: all ``waf.yaml`` は、VirtualServerが参照するPolicy設定となります。利用するApp ProtectのPolicyとして ``dataguard-alarm`` を指定し、Log 設定として ``logconf`` を指定します。 .. code-block:: yaml :linenos: :caption: waf.yaml :emphasize-lines: 4,8,11 apiVersion: k8s.nginx.org/v1 kind: Policy metadata: name: waf-policy spec: waf: enable: true apPolicy: "default/dataguard-alarm" securityLog: enable: true apLogConf: "default/logconf" logDest: "syslog:server=syslog-svc.default:514" ``virtual-server.yaml`` で、作成した ``waf-poicy`` を割り当てます .. code-block:: yaml :linenos: :caption: virtual-server.yaml :emphasize-lines: 7,8 apiVersion: k8s.nginx.org/v1 kind: VirtualServer metadata: name: webapp spec: host: webapp.example.com policies: - name: waf-policy upstreams: - name: webapp service: webapp-svc port: 80 routes: - path: / action: pass: webapp 以下の通り、各リソースを適切に作成されていることを確認します。 .. code-block:: cmdin kubectl get APUserSig .. code-block:: bash :linenos: :caption: 実行結果サンプル NAME AGE apple 38m .. code-block:: cmdin kubectl get aplogconf .. code-block:: bash :linenos: :caption: 実行結果サンプル NAME AGE logconf 39m .. code-block:: cmdin kubectl get appolicy .. code-block:: bash :linenos: :caption: 実行結果サンプル NAME AGE dataguard-alarm 39m .. code-block:: cmdin kubectl get policy .. code-block:: bash :linenos: :caption: 実行結果サンプル NAME STATE AGE waf-policy Valid 41m 動作確認 ---- curlコマンドでリクエストを送信します。 .. code-block:: cmdin curl -v --resolve webapp.example.com:80:127.0.0.1 "http://webapp.example.com/" .. code-block:: bash :linenos: :caption: 実行結果サンプル :emphasize-lines: 12,22 * Added webapp.example.com:80:127.0.0.1 to DNS cache * Hostname webapp.example.com was found in DNS cache * Trying 127.0.0.1:80... * TCP_NODELAY set * Connected to webapp.example.com (127.0.0.1) port 80 (#0) > GET / HTTP/1.1 > Host: webapp.example.com > User-Agent: curl/7.68.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < Content-Type: text/plain < Content-Length: 157 < Connection: keep-alive < Expires: Thu, 20 Jan 2022 03:07:27 GMT < Cache-Control: no-cache < Server address: 192.168.127.42:8080 Server name: webapp-64d444885-jg6hf Date: 20/Jan/2022:03:07:28 +0000 URI: / Request ID: e0b6f00106a11885f85300ffcaf5b912 * Connection #0 to host webapp.example.com left intact ログメッセージを見ると、通信をブロックせず転送(PASSED)していることが確認できます。NGINX App ProtectはBot Signatureの機能をもっておりますので、curlコマンドであることを“人によるブラウザの通信ではなくBot Clientである”という形で検知をしておりますが、即座に驚異であると判断される設定となっておりませんので適切な通信としてWebアプリケーションへ転送が行われております。 .. code-block:: json :linenos: :caption: 該当するSyslogのサンプル :emphasize-lines: 23,24,27,28,29,31,32,35 Jan 20 03:07:28 nginx-ingress-5ddc7f4f-zjlt2 ASM: attack_type="Non-browser Client", blocking_exception_reason="N/A", date_time="2022-01-20 03:07:28", dest_port="80", ip_client="10.1.1.9", is_truncated="false", method="GET", policy_name="dataguard-alarm", protocol="HTTP", request_status="alerted", response_code="200", severity="Critical", sig_cves="N/A", sig_ids="N/A", sig_names="N/A", sig_set_names="N/A", src_port="49443", sub_violations="N/A", support_id="16242938385820378173", threat_campaign_names="N/A", unit_hostname="nginx-ingress-5ddc7f4f-zjlt2", uri="/", violation_rating="0", vs_name="32-webapp.example.com:8-/", x_forwarded_for_header_value="N/A", outcome="PASSED", outcome_reason="SECURITY_WAF_VIOLATION_TRANSPARENT_MODE", violations="Bot Client Detected", violation_details="N/A", bot_signature_name="curl", bot_category="HTTP Library", bot_anomalies="N/A", enforced_bot_anomalies="N/A", client_class="Untrusted Bot", client_application="N/A", client_application_version="N/A", request="GET / HTTP/1.1\r\nHost: webapp.example.com\r\nUser-Agent: curl/7.68.0\r\nAccept: */*\r\n\r\n", transport_protocol="HTTP/1.1" 次にNAP WAFで攻撃として検知するリクエストを、curlコマンドで送信します。クロスサイトスクリプティング(XSS)を想定した接続をします。 .. code-block:: cmdin curl -v --resolve webapp.example.com:80:127.0.0.1 "http://webapp.example.com/