1. Home
  2. Linux
  3. Apache
  4. Apache2.4セキュリティ「mod_headersモジュールでX-Frame-Optionsレスポンスヘッダの設定を行いクリックジャッキング攻撃対策を行う」

Apache2.4セキュリティ「mod_headersモジュールでX-Frame-Optionsレスポンスヘッダの設定を行いクリックジャッキング攻撃対策を行う」

  • 公開日
  • カテゴリ:Apache
  • タグ:Linux,CentOS,Apache,Security,httpd,2.4,7.2,Clickjacking,X-Frame-Options,mod_headers
Apache2.4セキュリティ「mod_headersモジュールでX-Frame-Optionsレスポンスヘッダの設定を行いクリックジャッキング攻撃対策を行う」

「セキュリティ対策とは、常に小さな事の積み重ねである」
どなたの名言でもありませんが、激しく同意している今日この頃。

べつにしてもしなくてもどっちでもまあいい。程度のレベルなら、ひとまずやっておくのが WEB サーバーのセキュリティ対策だと思っています。

という事で今回は、クリックジャッキング対策として、X-Frame-Options レスポンスヘッダの設定を行います。

Contents

  1. クリックジャッキング攻撃
  2. X-Frame-Options HTTP レスポンスヘッダ
  3. Apache mod_headers モジュールの有効化
  4. X-Frame-Options レスポンスヘッダを設定する
    1. 現在の設定確認
    2. X-Frame-Options HTTP レスポンスヘッダ設定
  5. 動作確認

クリックジャッキング攻撃

クリックジャッキング攻撃とは、悪意のあるユーザが iframe に別のサイトへのリンクなどを仕込み、気づかれない(見えない)ようにして攻撃対象のサイトへそれを表示させ、訪問者にその部分をクリックさせる事で、意図しないサイトへ強制的に誘導してしまう攻撃手法の事。

X-Frame-Options HTTP レスポンスヘッダ

X-Frame-Options HTTP レスポンスヘッダとは、外部サイトからの、HTML の iframe タグの読み込み許可範囲を設定できるもの。設定出来る値は以下の3つです。

DENY 問答無用で全ての iframe タグが無効となる SAMEORIGIN 同一オリジンのものであれば iframe が有効となる。オリジン=同一ドメインであっても、http と https であれば無効となる ALLOW-FROM uri 指定したドメインのみ有効となる(1件のみ)例) ALLOW-FROM example.com## 現状確認と準備

今回は WEB サーバを2台用意して確認してみます。現状では何も制限をおこなっていないので、どこの外部サイトからであっても iframe で読み込みが可能なはずです。

1号機 CentOS 7.2Apache 2.4192.168.33.20http://apache-practice.com/2号機 CentOS 7.2Apache 2.4192.168.33.21http://apache-practice-master.com/まずは1号機のページを用意します。 HTML で簡単なページを作ります。

# 1号機のルートディレクトリに移動
cd /var/www/html

# index.html を作成
vim index.html

# index.html に記述したのソースコード
html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>title</title>
</head>
<body>
  <h1>Hello World!</h1>
  <p>こちらは検証1号機です</p>
</body>
</html>

ブラウザから確認するとこんな感じになります。

続いて2号機。こちらも HTML で簡単なページを作ります。

# 2号機のルートディレクトリに移動
cd /var/www/html

# index.html を作成
vim index.html

# index.html に記述したのソースコード
html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>title</title>
</head>
<body>
  <h1>hoge hoge hoge</h1>
  <p>こちらは検証2号機です</p>
</body>
</html>

ブラウザから確認するとこんな感じになります。

ではここから、2号機で1号機のページを iframe で読み込んでみます。2号機のページに iframe を追記します。

<html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>title</title>
</head>
<body>
  <h1>hoge hoge hoge</h1>
  <p>こちらは検証2号機です</p>

  <iframe src="http://192.168.33.20/" width=800 height=600></iframe>

</body>
</html>

ブラウザから確認するとこんな感じになります。

2号機のページから iframe で1号機のページが表示されました。

Apache mod_headers モジュールの有効化

X-Frame-Options レスポンスヘッダの設定の為には、Apache の mod_headers モジュールを有効にする必要があります。

Apache2.4 の場合は既に導入・有効化されているので、有効確認を行います。

ファイル設置箇所/etc/httpd/conf.modules.d ファイル名 00-base.conf00-base.conf を開き、mod_headers モジュールの存在と有効化を確認します。

# vim コマンドで 00-base.conf を開く
vim /etc/httpd/conf.modules.d/00-base.conf

# 以下の記述があれば OK 。コメントアウトされている場合は外す。
LoadModule headers_module modules/mod_headers.so

LoadModule headers_module modules/mod_headers.so の記述があれば導入はされています。もしコメントアウトされていた場合は外してください。

コメントアウトされていて、外した場合は Apache を再起動します。

# Apache の再起動
apachectl restart

X-Frame-Options レスポンスヘッダを設定する

ここからいよいよ、X-Frame-Options レスポンスヘッダを設定していきます。

現在の設定確認

まずは、設定前のレスポンスヘッダを確認します。2号機の WEB サーバから、1号機に向けて以下の curl コマンドを叩きます。

# 2号機の WEB サーバから、curl コマンドで1号機にアクセスする
curl -v -X GET http://192.168.33.20/

# 実行結果
[demo@localhost ~]# curl -v -X GET http://192.168.33.20/

* About to connect() to 192.168.33.20 port 80 (#0)
*   Trying 192.168.33.20...
* Connected to 192.168.33.20 (192.168.33.20) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 192.168.33.20
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Tue, 22 Aug 2017 01:48:16 GMT
< Server: Apache
< Last-Modified: Tue, 22 Aug 2017 01:14:55 GMT
< ETag: "v5-8295d52fq1k32"
< Accept-Ranges: bytes
< Content-Length: 177
< Content-Type: text/html; charset=UTF-8
<

<html lang="ja">
<head
<meta charset="UTF-8">
<title>title</title>
</head>
<body>
<h1>Hello World!</h1>
<p>こちらは検証1号機です</p>
</body>
</html>
* Connection #0 to host 192.168.33.20 left intact

「X-Frame-Options 」の記載が無いので、X-Frame-Options HTTP レスポンスヘッダは未設定である事が確認出来ます。

X-Frame-Options HTTP レスポンスヘッダ設定

X-Frame-Options の設定ですが、conf ファイルに記述する事で設定できます。ここでは、httpd.conf に記述します。

ファイル設置箇所/etc/httpd/conf ファイル名 httpd.confhttpd.conf を開いて、以下を記述します。場所は大方どこでも大丈夫ですが、httpd.conf にオリジナル設定を記述する場合には、後で見返してわかりやすいように、下の方にまとめておくと良いと思います。

# vim コマンドで httpd.conf を開く
vim /etc/httpd/conf/httpd.conf

# httpd.conf に以下を追記する
# X-Frame-Options Setting
Header append X-FRAME-OPTIONS "DENY"

「DENY 」と記述しているところは、上記X-Frame-Options HTTP レスポンスヘッダ の項で説明した3つのどれかを指定してください。今回はデモなので、一撃一刀両断の DENY 氏をアサインしました。

Apache を再起動します。

# Apache の再起動
systemctl restart httpd.service

ちなみにこの前に記述した Apache の再起動コマンドと違っていますが、ただの気まぐれです。再起動コマンドはいくつか存在しているので、自分の好きなコマンドで叩いてください。

動作確認

設定が出来たので、改めてレスポンスヘッダを確認してみます。先ほどと同じように、2号機の WEB サーバから、1号機に向けて以下の curl コマンドを叩きます。

# 2号機の WEB サーバから、curl コマンドで1号機にアクセスする
curl -v -X GET http://192.168.33.20/

# 実行結果
[demo@localhost ~]# curl -v -X GET http://192.168.33.20/

* About to connect() to 192.168.33.20 port 80 (#0)
*   Trying 192.168.33.20...
* Connected to 192.168.33.20 (192.168.33.20) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 192.168.33.20
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Tue, 22 Aug 2017 01:49:38 GMT
< Server: Apache
< Last-Modified: Tue, 22 Aug 2017 01:14:55 GMT
< ETag: "b1-5574d52bc1b18"
< Accept-Ranges: bytes
< Content-Length: 177
< X-FRAME-OPTIONS: DENY
< Content-Type: text/html; charset=UTF-8
< 

<html lang="ja">
<head
<meta charset="UTF-8">
<title>title</title>
</head>
<body>
<h1>Hello World!</h1>
<p>こちらは検証1号機です</p>
</body>
</html>
* Connection #0 to host 192.168.33.20 left intact

「X-FRAME-OPTIONS: DENY 」の表示が確認出来ました。これで設定は完了です。

ブラウザから2号機にアクセスして確認してみましょう。

X-Frame-Options HTTP レスポンスヘッダを DENY にしたことにより、外部ドメインである2号機から1号機のコンテンツは読み込まれなくなりました。

また、Google Chrome のデベロッパーツールからみると、それぞれ、X-FRAME-OPTIONS が効いている事がわかります。

1号機(読み込まれる側)以上で X-FRAME-OPTIONS HTTP レスポンスヘッダの設定は完了です。

Author

rito

  • Backend Engineer
  • Tokyo, Japan
  • PHP 5 技術者認定上級試験 認定者
  • 統計検定 3 級