2013年9月30日月曜日

HTTPSを使ってもCookieの改変は防げないことを実験で試してみた

寺田さんのブログエントリ「他人のCookieを操作する」には、通信路上の攻撃者がいる場合は、SSLを使っても、Cookieの盗聴を防ぐことはできるが、Cookieの改変を防ぐことはできないと指摘されています。いかにも寺田さんらしい簡にして要を得たエントリで、これに付け加えることはあまりないのですが、残念ながらまだ読んでいない人が多そうだと言うことと、より広い読者に向けて具体的に説明した方がよいだろうと考えました。
そこで、通信路上に攻撃者がいる典型例として、公衆無線LANの偽AP(アクセスポイント)があるケースを題材として、「HTTPSを使ってもCookieの改変は防げない」ことを説明します(Secure属性使うと盗聴は防げますが、改変は防げません)。長いエントリなので結論を先に書いておきます。
  • Secure属性がないCookieはHTTPSでも盗聴できる
  • Cookieの改変についてはSecure属性でも防ぐことはできない

偽APを用意する

まるでハッカージャパンの記事みたいな内容なので、この節は文体もハッカージャパンを真似してみましょう。
ここで紹介する実験は、「偽アクセスポイント」の偽物を作ることである。そのまま悪用可能なので、良い子の皆さんは絶対に悪用しないように。約束だぞ。
偽APの構成を下図に示そう。


(1)無線APの準備
 適当に設定すればよいが、SSIDと事前共有鍵を実在の公衆無線LANと同じにすればだまされやすいだろう。ここではだますことが目的でなく実験なので、そこまではやらない(やるなよ)。無線の暗号化は強固なものにしても問題ない。盗聴・改ざんは有線で行うからだ。むしろ、強固な暗号化を選択した方が、だまされやすくなると思うぞ(だが、やるなよ)。

(2)DHCPサーバーの設定
 DHCP(ルーターの機能を利用しても良いし、解析用PCにDHCPサーバーを立てても良い)の設定で、DHCPサーバーが配信するデフォルトゲートウェイを「解析用PC」のIPアドレスにしておく。これにより、被害者からの通信を解析用PCに誘導する。

(3)解析用PCの設定  解析用PCはデフォルトゲートウェイとして動作するので、Ubuntuの設定で、/etc/sysctl.confを以下のように修正する。
#net.ipv4.ip_forward=1
↓ コメントを取る
net.ipv4.ip_forward=1
この後、PCを再起動する。これで、AP→解析用PC→ルータ→インターネットという通信が可能となる。
この段階で既に、哀れな被害者がこのAPに接続したら、その通信は解析用PCを全て通過するので、Wiresharkを起動すれば、暗号化されていない通信は全てキャプチャされる。以下にYahoo!にリクエストした場合の様子を示そう。


ここで示しているのはリクエストだが、もちろんレスポンスについてもキャプチャできる。すなわち、偽APの利用者の通信は、文字通りだだ漏れになるのだ。しかし、SSL通信については暗号化されているため中身を見ることはできない。

Secure属性のないCookieを盗聴する

さて、ここからが本題です。文体も元に戻します。SSLを使っていても、Cookieを盗聴できる場合があるというお話です。タイトルにつけたように、CookieにSecure属性がないと、盗聴が可能になります。
 まず、よくあるのは、サイト全体はHTTP(平文)だが、個人情報を扱うページのみHTTPSというサイトです。この場合、CookieにSecure属性がないと、平文通信でもCookieが送信されてしまいます。以下、実験で確認しましょう。

 まず、被害者が https://www.city.machida.kanagawa.jp/login.php にアクセスしていて、セッションクッキーが付与されているとしましょう。クッキー情報は下図の通りです。

Secure属性がついていないことに注目してください。
この状態で、前述のAPを利用して http://www.city.machida.kanagawa.jp/ (HTTPSではない)にアクセスすると、以下のリクエストが送信されます。ばっちりCookieが見えていますね。


次に、「うちのサイトは、HTTPSのみで80番ポート閉じているから大丈夫」と言う意見をよく目にしますが、これは誤解です。少し手順は増えますが、Cookieを盗聴することは可能です。
それは、罠をしかけて、 http://www.city.machida.kanagawa.jp:443/ (httpsではなくhttp)にアクセスさせることです。罠の例を以下に示します。利用者(被害者)の通信は全て解析用PCを通過するので、わざわざ罠サイトを作る必要はなく、適当にHTTPレスポンスを改変して以下を突っ込めばよいことになります。
<img src="http://www.city.machida.kanagawa.jp:443/" width="1" height="1">
これによるリクエストは下記となります(デスティネーション443ポートをHTTPとしてデコードするように指定しています)。Cookieを含むHTTPリクエストが平文でキャプチャされています。


【結論】Secure属性のないCookieは盗聴の危険性がある

ということで、秘密情報を含むCookie(セッションIDのCookieを含む)にはSecure属性をつけましょう。

クッキーを強制する

次に、この環境を用いて、Cookieの強制(追加あるいは変更)をしてみましょう。ここまで出てきたツールではCookieの変更はできないので、Burp Suiteを使うことにします。Burp Suiteを透過Proxyとして使用するために以下の2点を設定します。
  • iptablesにより80番ポート宛のパケットをローカルの8080ポートにリダイレクトする
$ sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
  • Burp Suiteをinvisibleモードに設定する

これで、偽APを通る80番ポート向けTCPパケットは、全てBurp Suiteを通ることになります。
次に、Burp Suiteの機能で、全てのレスポンスにSet-Cookieヘッダを付与する設定を追加します。


以上で、「偽APを通過した80番ポート宛のHTTPリクエストすると、もれなくPHPSESID=ABCD12345というクッキーが設定される」という罠ができあがりです。
さっそく試してみましょう。罠を使うなどして、偽AP利用者に http://www.city.machida.kanagawa.jp/ を閲覧させます。Burp suiteの画面は下記となります。


確かに、Set-Cookie: PHPSESSID=ABCD12345 というレスポンスヘッダが付与されています。

80番ポートを閉じているサイトの場合のクッキー強制方法

次に、攻撃対象サイトが80番ポートを閉じている場合について検討します。この条件では上記の方法は使えません。その理由は、HTTPレスポンスが帰ってこないので、そのレスポンスにSet-Cookieヘッダを付与することもできないからです(リクエストは飛ぶので、リクエストのCookieヘッダを見ることは可能です)。
しかし、やりたいことはSet-Cookieヘッダを含むHTTPレスポンスを返すだけなのですから、PROXYではなく、Webサーバーを立てて、それにリクエストをリダイレクトすることにしましょう。ということで、今度はApacheの出番です。
$ sudo iptables -t nat -L --line-numbers         ← 現在の状態を確認
Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination
1    REDIRECT   tcp  --  anywhere             anywhere             tcp dpt:http redir ports 8080
... 省略
$ sudo iptables -t nat -D PREROUTING 1           ← 1番のルールを削除
$ sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dst 133.242.129.62 --dport 80 -j REDIRECT --to-port 80          ← 133.242.129.62:80来たパケットをローカルに
これにより、偽APから IPアドレス133.242.129.62 (偽町田市サイトのIPアドレス)宛のTCPパケットを解析用PC上のapacheにリダイレクトします。
さらに、クッキー設定用のPHPスクリプト(image.php)を解析用PC上に配置します。Base64エンコードされた文字列は、1ピクセル×1ピクセルのGIF画像です。
<?php
  header('Content-Type: image/gif');
  setcookie('PHPSESSID', 'image.php');
  echo base64_decode('R0lGODlhAQABAIgAAP///wAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==');
後は、利用者に罠を仕掛けて、http://www.city.machida.kanagawa.jp/image.php を閲覧させるだけです。このリクエストは、解析用サーバー上のapacheにリダイレクトされて、1x1のGIF画像を表示するとともに、PHPSESSID=image.phpというCookieが、利用者のPCにセットされます。

Cookieの強制はサイト側で防御できない

以上のように、元サイト側で80番ポートを閉じている・いないに関わらず、HTTPSでCookieを利用しているサイトは、中間者攻撃により偽のCookieをセットされてしまうことが分かりました。これは、以下の理由によるものです。
  • Cookieはポートやプロトコル(http/https)をまたがって共有されている
  • Cookieのsecure属性は平文でCookieを送信しないという設定であり、Cookieをセットする(受信する)場合には効果がない
  • 既にsecure属性つきCookieがあっても、HTTPのsecure属性なしCookieで上書きされる(IE10、Google Chrome、Firefoxで確認)

Cookie Monster Bugの影響のないドメイン名でもセッション固定対策はしっかり行おう

ここまで説明したように、HTTPSを利用しているサイト(通信路上の盗聴・改ざんを許容していない)では、外部からCookieを強制されること自体は防御できないので、「Cookieを改変されても構わないようにサイトを設計する」必要があります。これには、以下が重要です。
  • セッション固定脆弱性対策を行う。具体的には、ログイン成功後にセッションIDを振り直す
    session_regenerate_id(true);
  • Cookieには、外部から変更されると困る値は入れない
  • Cookieに攻撃文字列を入れるタイプのXSSの影響を受けるので、攻撃経路がCookieだからという理由で許容してはいけない

緩和策としてHTTP Strict Transport Securityが有効

先ほど、Cookieの強制はWebサイト側で防御することはできないと書きましたが、緩和策としてであれば、HTTP Strict Transport Security (HSTS) が有効です。HSTSとは、特定サイトへの通信をHTTPSに強制する機能です。HSTSを利用するには、HTTPレスポンスヘッダとして下記をブラウザに送信します。includeSubdomainsはサブドメインまで含めてHSTSを強制するというオプションです。
Strict-Transport-Security: max-age=有効期間(秒); includeSubdomains
これを受け取った後は、max-ageで指定した期間、指定サイトにHTTPで接続することはできなくなり、強制的にHTTPSで接続されます。このため、HTTP(平文)でCookieの盗聴や強制も防御されます。PHPでの利用例を下記に示します。
header('Strict-Transport-Security: max-age=2592000; includeSubdomains');  // HSTS30日間有効
HSTSが完全な防御ではなく緩和策である理由は下記の通りです。
  • 対応ブラウザが本稿執筆時点でGoogle Chrome、Firefox、Operaであり、IEとSafariは未サポート
  • 利用者が初めて訪問するサイトや、HSTSの期限切れの状態では効果がない
このため、前述の対策を施した上で、HSTSヘッダを緩和策として実施するとよいでしょう。
一方、従来よく用いられてきたサーバー側でのHTTPSへの強制リダイレクトは効果がありません。この場合は、最初のリクエストはHTTPで送信されますが、Cookieの盗聴・強制には1リクエストあれすば十分だからです。

※追記(2013/9/30 10:15) このエントリ公開時にincludeSubdomainsの指定が抜けておりましたが、これがないと、サブドメイン上のページ(DNSも偽装すれば、存在しないサブドメインでも攻撃できる)でCookieの改変が可能になることを、はせがわようすけさんから指摘いただきました。ありがとうございます。もしも、既にHTTPで稼働しているサブドメインがある場合は、includeSubdomainsは指定できないので、HSTSによる緩和策は有効ではありません。

まとめ

通信路上に攻撃者がいる場合でも、SSLの正しい利用により通信路上でのHTTPメッセージの盗聴・改ざんを防ぐことができますが、Cookieに関して言えば、Secure属性の付与により盗聴は防げるものの、改ざん(強制・改変)については防御できないことを示しました。これにより、セッション固定攻撃の他、Cookieを攻撃経路とするXSS等の攻撃が現実の脅威となります。
結論としては、Cookieを改変できるかどうか(通信路上の攻撃者、Cookie Monster Bug)とは無関係に、Cookieを攻撃経路とする脆弱性は常に対処することを推奨します。また、盗聴防止として、CookieのSecure属性は必ず設定しましょう。


2013年9月20日金曜日

PHP5.5.4にてstrict sessionsのバグ(bug65475)が修正されたがテストがないことに気づいた

以前のエントリで、PHP5.5.2にて大垣さん提案のstrict sessionsがマージされたと報告しましたが、PHP5.5.4にて、このバグ(bug65475)が修正されました。バグの例として紹介したアクセスカウンタも、カウントアップすることを確認しました。

しかし、bug65475のテストを見て、重大な抜けがあることに気づきました。
$ cat bug65475.phpt
--TEST--
Bug #65475: Session ID is not initialized when session.usr_strict_mode=1
--INI--
session.save_handler=files
session.name=PHPSESSID
--SKIPIF--
<?php include('skipif.inc'); ?>
--FILE--
<?php
ob_start();

echo "Testing file module".PHP_EOL;
session_start();
$_SESSION['foo'] = 1234;
$_SESSION['cnt'] = 1;
$session_id = session_id();
session_write_close();

session_start();
var_dump($session_id === session_id());
$_SESSION['cnt']++;
session_write_close();

session_start();
var_dump($session_id === session_id());
var_dump($_SESSION['cnt']); // Should be int(2)
session_write_close();

--EXPECTF--
Testing file module
bool(true)
bool(true)
int(2)
このテストは、session.use_strict_mode=1 の指定がないと意味がないはずですが、見あたりません。use_strict_modeのデフォルトは 0 ですから、これだと strict sessions モードでない状態でのテストになります。
試みに、上記指定を追加して、同バグのあるPHP5.5.2およびPHP5.5.3で上記をテストしてみました。
ockeghem@php552:~/php-5.5.2/ext/session/tests$ pear run-tests bug65475.phpt
Running 1 tests
PASS Bug #65475: Session ID is not initialized when session.usr_strict_mode=1[bug65475.phpt]
TOTAL TIME: 00:00
1 PASSED TESTS
0 SKIPPED TESTS
なんと、テストをPASSしてしまいました。バグがある状態でFAILしてくれないと、テストの意味がありません。ということで、上記テストは、use_strict_mode=1の指定がないだけでなく、テストとして不完全なようです。

それでは、他のテストはどうなんだろうと思って同じディレクトリをgrepしてみましたが、use_strict_mode=1に設定したテストはないようです。
PHP5.5.1からPHP5.5.2(strict sessionsが実装された)で、ext/session/tests内のテスト(*.phpt)は197で増えていません。PHP5.5.4でphptの数は200に増えましたが、上記の他にbug65359に関するもののようです。

まとめ

  • PHP5.5.4にてstrict sessionのバグ(65475)が修正され、ようやくstrict sessionsが使えるようになった
  • 上記バグに関するテストbug65475.phptにはバグがあり、PHP5.5.3以前でもFAILしない
  • PHP5.5.4までの時点で、strict sessionsに関するテストが1つも存在しない
ということで、strict sessionsはとりあえず使えるようになりましたが、テストが一つもない状態は今後の品質上不安ですので、テストを強化することを希望します。

2013年9月11日水曜日

PHPカンファレンス2013でトークします

PHPカンファレンス2013にてトークしますのでご案内します。
  • 日時:2013年9月14日(土曜日) 10時00分~(徳丸の出番は12:00~12:45)
  • 場所:大田区産業プラザ(PiO)
  • 費用:無料(申し込みはこちら
  • 講演タイトル:安全なPHPアプリケーションの作り方2013
PHPカンファレンスでは2009年以降毎年トークさせていただいております。今年は、上記タイトルにて以下のテーマを取り上げます。
  • パスワードの守り方
  • セッションフィクセイション結局どうする
  • PHPのライフサイクルにどうつきあう?
  • HTML5セキュリティ入門
上の2つはPHPの最新版PHP5.5に関する話題です。また、PHPのリリースサイクルが短いということから、ライフサイクルについても(少し)お話しします。

HTML5のセキュリティについては少しずつ情報が出てきましたが、難しい、抽象的、結局なにが問題か分からない、という感想が多いのではないでしょうか。
そのため、架空の脆弱なレジストラ(ドメイン名屋さん)「おネーム.COM」に登場いただき、「HTML5で起こる実際の悪いこと」を見ていただこうと思います。
現在デモを準備中ですが、以下を予定しています。
  1. XHR Level2によるCSRFにてパスワード変更
  2. JSONハイジャックによる個人情報漏えい
  3. 広告モジュールのDOM Based XSS(単独では影響なし)
  4. ドメイン名販売ページでの潜在的なDOM Based XSS(単独では影響なし)
  5. 3と4の合わせ技で大変なことに…
関連技術としては下記があります。
  • XMLHttpRequest Level2 
  • localStorage
  • postMessage
  • クロスサイト・リクエストフォージェリ(CSRF)
  • DOM Based XSS

それでは、PiOでお会いしましょう。

2013年9月2日月曜日

ロリポップのサイト改ざん事件に学ぶシンボリックリンク攻撃の脅威と対策

既に報道されているように、ロリポップ!レンタルサーバーに対する改ざん攻撃により、被害を受けたユーザー数は8428件にのぼるということです。ここまで影響が大きくなった原因は、報道によると、(1)「WordPressのプラグインやテーマの脆弱性を利用」し、不正なファイルがアップロードされた、(2)パーミッション設定の不備を悪用されて被害が拡大した、ということのようです。
29日夜の時点では、攻撃者の改ざん手法について「WordPressのプラグインやテーマの脆弱性を利用」し、不正なファイルがアップロードされて「wp-config.phpの」の設定情報が抜き出されたと説明していたが、30日午後7時過ぎの説明で、この脆弱性が侵入経路となって同社のパーミッション設定の不備を悪用されたことが原因だったことを明らかにした。
「ロリポップ」のWordPressサイト改ざん被害、原因はパーミッション設定不備より引用
これ以上の詳細は本校執筆時点で公表されていないので憶測は控えますが、ロリポップからのリリースに以下の内容があることが気になるところです。
サーバーの設定を変更しFollowSymLinksを無効にしました。
当社サービス「ロリポップ!レンタルサーバー」ユーザーサイトへの第三者による大規模攻撃についてより引用
これは、httpd.confにて元々FollowSymLinksが有効になっていたか、レンタルサーバーの利用者が.htaccessによりFollowSymLinksを有効にできる状態であったという意味でしょう。この状況では、レンタルサーバーの悪意の利用者(サーバーへの侵入者を含む)が、同じサーバーを共有する別の利用者の秘密情報をシンボリックリンク攻撃により盗み読みすることができます。以下、シンボリックリンク攻撃の原理と脅威、対策について説明します。

デモ環境の説明

以下は、ロリポップに似せた設定の架空のレンタルサーバーのホームディレクトリ設定です。ユーザはsuzukiとtanakaで、それぞれsuzuki.example.jpとtanaka.example.jpがホスト名です。以下は、suzuki.example.jpの表示です。


ホームディレクトリの設定は下記となります。
$ ls -l
drwx-----x  3 suzuki      LolipopUser 4096 Aug 31 17:26 suzuki/
drwx-----x  3 tanaka      LolipopUser 4096 Aug 31 17:39 tanaka/
$
各利用者のホームディレクトリのパーミッションが701となっていて、同じグループ(LolipopUser)に属していますが、これはレンタルサーバー特有の設定です。これは、レンタルサーバーの利用者同士は同じグループに属するため、他のユーザのファイルにアクセスできず、apache等のサービスは、LolipopUserグループに属さないユーザの権限で動くため、各ユーザのファイルにアクセスできるという設定になっています。

レンタルサーバーの利用者間では、ファイルは閲覧できない

ここで、tanakaさんが、suzukiさんのファイルを閲覧できないことを示します。
$ su - tanaka
Password:  ←パスワードを入力
tanaka$ pwd
/home/tanaka
tanaka$ ls -l
total 8
-rw-r--r-- 1 tanaka LolipopUser  465 Sep  1 23:45 log.txt
drwxr-xr-x 2 tanaka LolipopUser 4096 Sep  1 23:39 www
tanaka$ ls -l ../suzuki/
ls: cannot open directory ../suzuki/: Permission denied  ← 別ユーザのディレクトリは参照できない
tanaka$ cat ../suzuki/www/index.html
cat: ../suzuki/www/index.html: Permission denied  ← 別ユーザのコンテンツも同様
tanaka$

閲覧権限がないファイルにシンボリックリンクを設定できる

ところが、tanakaさんは、suzukiさんのファイルに対してシンボリックリンクを設定することは可能です。
tanaka$ cd www
tanaka$ ln -s ../../suzuki/www/index.html suzuki.html
tanaka$ cat suzuki.html
cat: suzuki.html: Permission denied  ← シンボリックリンクは作れるが参照はできない
tanaka$
上記のように、シンボリックリンクは、権限のないファイルに対して設定することができます(存在しないファイルにも可)。上記のように、このシンボリックリンクを指定してもファイルを閲覧することはできませんが、apacheによる表示は可能です。apacheは、シンボリックリンク自体とリンク先の両方にアクセス権があるからです。


ただ、これだと、元々公開している情報を別のホストで表示しているだけなので、攻撃としての価値はあまりありません。問題は、この方法で以下が可能になる場合があることです。
  • CGIプログラムやPHPスクリプトのソースが閲覧できる
  • 非公開ディレクトリのファイルが閲覧できる場合がある

閲覧できない情報をシンボリックリンク攻撃により表示する

以下、これを試してみましょう。suzukiさんのホームページ上にメールフォームがあり、そのファイル名が inquiry.php であることが分かっているとします。以下のように、これに対して inquiry.txt というシンボリックリンクを設定します。
tanaka$ ln -s ../../suzuki/www/inquiry.php inquiry.txt
これを閲覧すると、下記となります。


拡張子を.txt に変更したことで、PHPスクリプトのソースが見えてしまっています。
実は、拡張子が.php のままだと、レンタルサーバー環境の場合、PHPスクリプトは実行できないと考えられます。レンタルサーバーの場合は、CGIプログラムやPHPスクリプトは、suEXECにより、各ユーザの権限で動作します。上記のシンボリックリンクの場合、tanakaの権限により、suzukiのスクリプトを実行しようとしますが、今まで見たように、tanakaの権限ではスクリプトファイルの読み込みができないからです。しかし、apacheの実行ユーザだと読み込み権限があるため、ソースの閲覧は可能です。
さて、上図のソースから、ログファイルが ../log.txt だと分かります。このファイルにもシンボリックリンクを設定して、閲覧できるか調べてみましょう。
tanaka$ ln -s ../../suzuki/log.txt log.txt
閲覧画面は下記となります。


上記のように、通常は閲覧できないディレクトリ上の、攻撃者に読み込み権限のないデータファイルも、シンボリックリンクを設定することで、外部から閲覧できることが分かりました。この際のlog.txtのパーミッションは下記となっています。
tanaka$ su - suzuki
Password:
suzuki$ ls -l log.txt
-rw-r--r-- 1 suzuki LolipopUser 465 Sep  1 23:45 log.txt
suzuki$
すべてのユーザーに対して読み込み権限が与えられています。これは、PHPスクリプトのfopenで作成したファイルに与えられるパーミッションですが、仮にアプリケーションの実行に最低限の権限(600)が設定されていたら、apacheから読み込むことができず、このファイルに対するシンボリックリンク攻撃は成立しません。

シンボリックリンク攻撃が成立する条件

冒頭に書いたように、シンボリックリンク攻撃が成立する条件は下記の両方が成立する場合です。
  • FollowSymLinksが有効になっているか、攻撃者が.htaccessによりFollowSymLinksを有効にできる
  • 攻撃者が、公開ディレクトリにシンボリックリンクを設定できる
通常のWebサーバーでFollowSymLinksが問題にならないのは、後者の条件が成立しないからです。一方、レンタルサーバーの場合は、以下のいずれかにより、攻撃者が公開ディレクトリにシンボリックリンクを設定可能です。
  • 攻撃者がレンタルサーバーのユーザとなる(お試し等でも可)
  • 攻撃者がレンタルサーバーのユーザtanakaを攻撃して、tanakaの書き込み権限を得る
通常のWebサーバーでも、攻撃者が書き込み権限を得ることはあり得ますが、他のユーザの権限を得る動機があまりないところが、レンタルサーバー環境との違いです。

シンボリックリンクを作成する時点で、相手側のディレクトリ一覧は参照できない場合が多いのですが、以下の手順でファイル名が推定可能です。
  • 外部公開のURLからファイル名を推定する
  • スクリプトのソースファイルからファイル名を得る
  • WordPress等の標準的なファイル構成からファイル名を得る

シンボリックリンク攻撃の脅威

一般的には、シンボリックリンク攻撃が成立すると、攻撃者の有する権限よりも高い権限を獲得することができます。上記の例では、攻撃者が持っているtanakaの権限に加えて、apacheの権限により、権限を持たないファイルも閲覧可能になります。
おおざっぱに言って、シンボリックリンク攻撃の影響は、ディレクトリトラバーサル攻撃の影響と似ています。

対策

一般に、シンボリックリンク攻撃が問題になる場合は、ファイルのオープン時にシンボリックリンクかどうかを確認して、シンボリックリンクの場合はエラーにします(参考)。apacheの場合は、FollowSymLinksを無効にすることで、これが実現できます。
しかし、これだけではだめです。攻撃者が.htaccessの設定で、FollowSymLinksを設定する可能性があるからです。このため、AllowOverride ディレクティブにて、Noneを指定するか、Options=にて、許可したいオプション(FollowSymLinks以外)を明示的に列挙する方法があります。
利用者側でシンボリックリンクを安全に設定したい場合は、SymLinksIfOwnerMatchを利用できます。これは、「シンボリック先のファイルまたはディレクトリが、 シンボリックリンクの所有ユーザ ID と同じ場合にのみシンボリックリンクを たどれるようにします。」というものです(参照)。
レンタルサーバーの利用者が上記を確認する方法についてはここでは説明しませんので、レンタルサーバー事業者に個別に確認いただくのがよいと考えます。レンタルサーバー事業者は、今回の事件を受けて、自社の設定状況と安全性を説明いただく(あるいは急いで設定を修正する)とよいでしょう。

まとめ

シンボリックリンク攻撃の脅威と対策について説明しました。これは、シンボリックリンクを悪用して、上位権限のプロセスにファイルをアクセスさせる手法です。前述のように、レンタルサーバー環境で、apacheのFollowSymLinksが有効な場合、シンボリックリンク攻撃が成立してしまいますが、これはレンタルサーバー利用者の中に悪意のユーザが存在する可能性があるからです。
似たような状況として、Androidアプリケーションがあります。Androidアプリケーションは、アプリケーション毎にLinuxのアカウントが割り当てられるので、悪意のアプリケーション(マルウェア)が端末に導入された場合、root権限で動作するプロセスに対してシンボリック攻撃を仕掛け、マルウェアがroot権限を奪取するような攻撃に使われます。

追記(2013/09/03 10:00)

さとうふみやすさんから、apacheの-FollowSymLinksでは、レースコンディションによりシンボリックリンク攻撃の防御が回避されてしまうという指摘をいただきました(参照: Apache HTTPD: `Options -FollowSymLinks` は不完全)。さとうさん、ありがとうございます。
これは、TOCTOU 競合状態という問題で、参考文献として紹介したJPCERT/CCのドキュメントでも言及されています。また、TOCTOU競合を避ける方法についても、同じJPCERT/CCの解説に、「POS35-C. シンボリックリンクの有無のチェック時の競合状態を避ける」として紹介されています。ただ、これはapache(などのhttpd)を開発する側でとれる対策で、apacheの利用者としては、apache側で対策してくれるのを待つしかありません。
さとうさんは、『この攻撃の根本的な対策方法は「シンボリックリンクを作らせない」 しかない』としていますが、これもなかなか難しいと思います。現在のレンタルサーバーの多くは、シンボリックリンク攻撃のTOCTOU競合については受容している(あきらめている)のだと理解しています。
利用者側でとれる対策としては、CGIやPHPのスクリプトや、これらからアクセスするファイルのパーミッションを600や400として、apacheから読み取らせないようにすることです。ただし、.htaccessや.htpasswdはapacheから読めないとまずいので、この方法では保護できません。
ということで、この問題が受容できない利用者は、さとうさんの言及されている「ユーザーごとに別権限の Web サーバーを立ち上げる」サービスを提供しているレンタルサーバーやVPSなどに移行するしかないと考えます。
(追記終わり)

参考文献

フォロワー

ブログ アーカイブ