WAF(ModSecurity) を用いたセキュリティについて勉強をした(XSS, SQL インジェクション)

# TL;DR

- 仕事でホームページのセキュリティ対策を進めることになり、
主な脆弱性として XSS や SQL インジェクション(SQLi と略します) は
WAF(WEB アプリケーション Firewall) で防げるとされているが、具体的に WAF がどんな対策を行っているかを知りたく、
簡単なフォームを用意し、悪意ある入力を行い、どのような結果になるかテストを行ったので情報整理のためにまとめようと思います。
- テスト結果について
    - XSS → WAF による対策を確認
    - SQLi → WAF による対策を確認
        - 今回は簡易的にテストを行いたく、 DB を使っていない。
    - CORS → 今後テスト予定(未検証)



## 脆弱性のおさらい(自分の前提知識)
- 脆弱性について(※ いずれも入力フォームを用いたもの)
    - XSS(クロスサイトスクリプティング) とは？
        - JS を用いた攻撃
        - ブラウザへの攻撃
        - Cookie への攻撃
    - SQLiとは？
        - SQL 文を用いた攻撃
        - DB への攻撃
- WAF とは？
    - 脆弱性を対策するもの
    → 試してみる

## テストの流れ

- 環境セットアップ
- WAF なしテスト
    - フォームに悪意ある入力を行う
    - 攻撃されたことをブラウザで確認
- WAF ありテスト
    - フォームに悪意ある入力を行う
    - 攻撃されたときの挙動をブラウザで確認
        - ログを見てどのような対策されるのか念の為確認

## 試した環境
- m1 Macbook Air
- Docker(環境依存したくないので...)
    - php:7.4-apache
        - php で入力フォームを作成(apache で web サーバーを立てる)
            - フォームは Name と Email を入力し、 Submit をクリックすると Name と Email の値が表示されるだけのもの
        - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165196/db6a2226-c5d0-128f-ceb9-2d3bc67b2ebe.png)
    - DB
        - なし(SQLi を試すなら必要だったかも)
    - WAF(Apache で必要な WAF(ModSecurity))
        - libapache2-mod-security2

## 実践
### ① XSS のテスト

Name: の入力フォームに下記スクリプトと Email を仮で入力し Submit をクリック
`<script>alert('XSS');</script>`

#### 対策前
- 不正なスクリプトの実行が確認された
![スクリーンショット 2024-11-24 20.18.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165196/2cc8ff30-7615-4931-72c3-81cc1a051d01.png)
#### WAF 対策後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165196/3ca04ebd-92aa-a42e-ba1a-1b54a8210ecd.png)

#### WAFのlog

- 実行されたスクリプト、403 のステータスコード、XSS に該当していることを確認

```
root@4f2c3d556abe:/var/www/html# tail -f /var/log/apache2/modsec_audit.log
...
--297c1155-C--
name=%3Cscript%3Ealert%28%27XSS%27%29%3B%3C%2Fscript%3E&email=bbb%40aaa
...
--297c1155-F--
HTTP/1.1 403 Forbidden
...
Message: Warning. detected XSS using libinjection. [file "/usr/share/modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "55"] [id "941100"] [msg "XSS Attack Detected via libinjection"] [data "Matched Data: XSS data found within ARGS:name: <script>alert('XSS');</script>"] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-xss"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/242"]
Message: Warning. Pattern match "(?i)<script[^>]*>[\\s\\S]*?" at ARGS

```

### ② SQLi のテスト

Name: の入力フォームに下記と Email を仮で入力し Submit をクリック

`' OR '1'='1`

#### 対策前

- 今回は DB 周りの設定はしていないので何もおこらない
    - 対策されていない場合は SQL の結果は true になるためログインがある機能の場合はログインができてしまう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165196/8bb56bf5-c09c-c580-7500-b0d5623c10a5.png)

#### WAF 対策後

※ キャプチャは XSS と同様
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165196/3ca04ebd-92aa-a42e-ba1a-1b54a8210ecd.png)

#### WAFのlog

- 攻撃者、攻撃内容、403 ステータスコード、SQLi に該当していることが分かる

```

Referer: http://localhost:8080/
Accept-Encoding: gzip, deflate, br, zstd
...
--297c1155-C--
name=%27+OR+%271%27%3D%271&email=bbb%40aaa
--297c1155-F--
HTTP/1.1 403 Forbidden
...
--297c1155-H--
Message: Warning. detected SQLi using libinjection with fingerprint 's&sos' [file "/usr/share/modsecurity-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf"] [line "65"] [id "942100"] [msg "SQL Injection Attack Detected via libinjection"] [data "Matched Data: s&sos found within ARGS:name: ' OR '1'='1"] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-sqli"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/248/66"] [tag "PCI/6.5.2"]
Message: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:anomaly_score.

```

## まとめ
- WAF はパターンにマッチしたもののみ対策(リクエストをブロック)できる
    - 403を返す(ページはあるが、アクセス権限は無い。情報を与えているため 404 が望ましい。)
    - 攻撃者の情報がわかる
    - 攻撃内容がわかる
    - WAF のみですべての攻撃に対する完全な防御は難しい
- 下記のような対策が推奨されている
    - ORM(Active Record) を採用する
    - 手動でサニタイズをする(htmlspecialchars()(php))
    - WAF を導入する