Ribbon NetworkのXSS脆弱性関連情報と対策

概要
====
[情報処理推進機構] \(IPA) を通じ、[Ribbon Network]運営に[クロスサイトスクリプティング] \(XSS) 脆弱性の修正を求めてきましたが、以下の通り修正を行わないことが決定されました。これによりIPAにおける取り扱いが終了したため、脆弱性関連情報と対策方法を公開いたします。

> ■ 運営者の判断(運営組織としての判断)：
>   \--------------------------------------------------------------
>   問題に対する対応を行った場合、ウェブサイトの提供するサービス上
>   で問題が発生するため、対応を行わない方針とした。
>   \--------------------------------------------------------------

[情報処理推進機構]: https://ja.wikipedia.org/wiki/%E6%83%85%E5%A0%B1%E5%87%A6%E7%90%86%E6%8E%A8%E9%80%B2%E6%A9%9F%E6%A7%8B "独立行政法人情報処理推進機構は、日本におけるIT国家戦略を技術面、人材面から支えるために設立された、経済産業省所管の中期目標管理法人たる独立行政法人。"
[Ribbon Network]: https://ja.wikipedia.org/wiki/Ribbon_Network "Ribbon Network（リボンネットワーク）は、日本の無料Webページスペース。"
[クロスサイトスクリプティング]: https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AD%E3%82%B9%E3%82%B5%E3%82%A4%E3%83%88%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0 "クロスサイトスクリプティングとは、Webアプリケーションの脆弱性もしくはそれを利用した攻撃。脆弱性をツリー型に分類するCWEではXSSを不適切な入力確認(CWE-20)によるインジェクション(CWE-74)のひとつとして分類している(CWE-79)。"

攻撃の例
========
ブラウザに保存されたパスワードが、Webサイト管理人以外の第三者から盗まれる等の被害が起こり得ます。

影響するサイト
==============
何らかの方法で認証やアクセス制限を行っているサイト、フォームを設置しているサイトなどが、本脆弱性の影響を受けると考えられます。

ユーザー (サイト管理人) 側での対策
==================================
安全な対策方法
--------------
以下のような `.htaccess` ファイルを設置して `http://⦅サーバ名⦆.ribbon.to/~⦅ユーザID⦆/○○○○` `http://⦅サーバのIPアドレス⦆/~⦅ユーザID⦆/○○○○` 形式などの危険なURLによるアクセスを遮断することが、安全な対策方法です。

```apacheconf:/.htaccess
SetEnvIf Host ^[0-9a-z]+\.[bryg]\.ribbon\.to$ subdomain
Order Deny,Allow
Deny from all
Allow from env=subdomain
```

不確実な対策方法
----------------
`http://⦅サーバ名⦆.ribbon.to/~⦅ユーザID⦆/○○○○` 形式の危険なURLから `http://⦅ユーザID⦆.⦅サーバ名の頭文字⦆.ribbon.to/○○○○` 形式のURLにリダイレクトさせたい場合、Ribbon Networkでは `.htaccess` 等によるリダイレクト設定が禁止されているため、ページごとに個別の対策が必要です。

### PHPの場合の例
すべてのPHPファイルへのアクセスをリダイレクトします。

```apacheconf:/.htaccess
php_value auto_prepend_file /home/freeuser/⦅ユーザID⦆/htdocs/.htredirect.php
```

```php:/.htredirect.php
<?php
if (preg_match('/^[0-9a-z]+\\.[bryg]\\.ribbon\\.to$/', $_SERVER['HTTP_HOST']) !== 1) {
    switch ($_SERVER['HTTP_HOST']) {
        case 'blue.ribbon.to':
        case '153.150.14.82':
            $thirdLevelDomainName = 'b';
            break;
        case 'red.ribbon.to':
        case '153.150.14.83':
            $thirdLevelDomainName = 'r';
            break;
        case 'yellow.ribbon.to':
        case '153.150.14.84':
            $thirdLevelDomainName = 'y';
            break;
        case 'green.ribbon.to':
        case '153.150.14.85':
            $thirdLevelDomainName = 'g';
            break;
    }
    preg_match('#^/~([0-9a-z]+)/(.*)$#', $_SERVER['PHP_SELF'], $matches);
    header("location: //$matches[1].$thirdLevelDomainName.ribbon.to/$matches[2]", true, 301);
    exit;
}

```

### Perlの場合の例
ブラウザからアクセスされるスクリプトファイル先頭の `#!/usr/local/bin/perl` 直後に、以下のコードを挿入し、アクセスをリダイレクトします。

```perl:index.cgi
#!/usr/local/bin/perl

# スクリプトの先頭に以下のコードを挿入
if ($ENV{'HTTP_HOST'} !~ /^[0-9a-z]+\.[bryg]\.ribbon\.to$/) {
	my %thirdLevelDomainNames = (
		'blue.ribbon.to'   => 'b',
		'153.150.14.82'    => 'b',
		'red.ribbon.to'    => 'r',
		'153.150.14.83'    => 'r',
		'yellow.ribbon.to' => 'y',
		'153.150.14.84'    => 'y',
		'green.ribbon.to'  => 'g',
		'153.150.14.85'    => 'g',
	);
	$ENV{'REQUEST_URI'} =~ m#^/(?:~|%7E)([^/]+)/(.*)$#i;
	print "status: 301\n";
	print "location: //$1.$thirdLevelDomainNames{$ENV{'HTTP_HOST'}}.ribbon.to/$2\n\n";
	exit;
}

                        ####################
                        ## 以下はそのまま ##
                        ####################

```

### ディレクトリにアクセス制限をかけている場合の例
`http://⦅ユーザID⦆.⦅サーバ名の頭文字⦆.ribbon.to/○○○○` 形式のURLでしかファイルを取得できないようにします。

```apacheconf:/○○○○/.htaccess
SetEnvIf Host ^[0-9a-z]+\.[bryg]\.ribbon\.to$ subdomain
Order Deny,Allow
Satisfy all
Deny from all
Allow from env=subdomain
# これより上の行を挿入

AuthType Basic
AuthName ○○○○
AuthUserFile /home/freeuser/○○○○/htdocs/.ht○○○○
Require ○○○○
```

### 静的なページにフォームが存在する場合の例
新しいディレクトリに既存のページを移動し、`<meta>` タグでリダイレクトします。

新しいディレクトリには以下の `.htaccess` ファイルを作成しておきます。

```apacheconf:/new/.htaccess
SetEnvIf Host ^[0-9a-z]+\.[bryg]\.ribbon\.to$ subdomain
Order Deny,Allow
Deny from all
Allow from env=subdomain
```

`/○○○○.html` → `/new/○○○○.html` のようにファイルを移動し、もともとファイルがあった場所には以下のようなファイルを作成しておきます。

```html:/○○○○.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<meta http-equiv="refresh" content="0; URL=//⦅ユーザID⦆.⦅サーバ名の頭文字⦆.ribbon.to/new/○○○○.html" />
		<title>301 Moved Permanently</title>
	</head>
	<body></body>
</html>
```

後処理
======
パスワードのリセット
--------------------
- すでにパスワードが攻撃者に取得された可能性がある
- ブラウザへ保存されたままになっているパスワードが今後攻撃者に取得される可能性がある
- 万が一他のサービスなどでパスワードを使いまわしていた場合、利用者がパスワードを使いまわしていた可能性
	+ 利用者への注意喚起
	+ 他サービスのパスワードの変更
	+ 他サービスにおける被害の確認
	+ Webブラウザのパスワードマネージャから、`⦅サーバ名⦆.ribbon.to` に結び付けられているパスワードを削除

セッションのリセット
--------------------
- ブラウザに保存されているセッションCookieが攻撃者に取得される可能性がある

被害の確認
----------
- 管理人や特定の利用者の権限で改竄などが行われた可能性がある
- 管理人や特定の利用者しか閲覧できないページ等の内容を攻撃者が取得している可能性がある

Webブラウザ側での対策
=====================
閲覧者側で可能な対策として、拡張機能を利用して危険なURLから安全なURLへ書き換える方法があります。

たとえばFirefoxのアドオン[Redirector]の場合、以下の設定を追加します。

- **Example URL:** `http://green.ribbon.to/~exampleusername/path`
- **Include pattern:** `^(https?://)(?:(b)lue|(r)ed|(y)ellow|(g)reen)\.ribbon\.to/(?:~|%7E)([%0-9a-z]+)/(.*)$`
- **Redirect to:** `$1$6.$2$3$4$5.ribbon.to/$7`
- **Pattern Type:** 🔘 Regular Expression
- **Apply to:**
	+ ☑ Main window (address bar)
	+ ☑ IFrames

---------------------------------------------------------------------

- **Example URL:** `http://153.150.14.82/~exampleusername/path`
- **Include pattern:** `^(https?://)153.150.14.82/(?:~|%7E)([%0-9a-z]+)/(.*)$`
- **Redirect to:** `$1$2.b.ribbon.to/$3`
- **Pattern Type:** 🔘 Regular Expression
- **Apply to:**
	+ ☑ Main window (address bar)
	+ ☑ IFrames

---------------------------------------------------------------------
 
- **Example URL:** `http://153.150.14.83/~exampleusername/path`
- **Include pattern:** `^(https?://)153.150.14.83/(?:~|%7E)([%0-9a-z]+)/(.*)$`
- **Redirect to:** `$1$2.r.ribbon.to/$3`
- **Pattern Type:** 🔘 Regular Expression
- **Apply to:**
	+ ☑ Main window (address bar)
	+ ☑ IFrames

---------------------------------------------------------------------

- **Example URL:** `http://153.150.14.84/~exampleusername/path`
- **Include pattern:** `^(https?://)153.150.14.84/(?:~|%7E)([%0-9a-z]+)/(.*)$`
- **Redirect to:** `$1$2.y.ribbon.to/$3`
- **Pattern Type:** 🔘 Regular Expression
- **Apply to:**
	+ ☑ Main window (address bar)
	+ ☑ IFrames

---------------------------------------------------------------------
 
- **Example URL:** `http://153.150.14.85/~exampleusername/path`
- **Include pattern:** `^(https?://)153.150.14.85/(?:~|%7E)([%0-9a-z]+)/(.*)$`
- **Redirect to:** `$1$2.g.ribbon.to/$3`
- **Pattern Type:** 🔘 Regular Expression
- **Apply to:**
	+ ☑ Main window (address bar)
	+ ☑ IFrames

[Redirector]: https://addons.mozilla.org/firefox/addon/redirector/ "Automatically redirects to user-defined urls on certain pages"

原因
====
Ribbon Networkでは管理人の異なる複数のWebサイトが同一生成元に存在し、かつ動的ページが設置可能です。このため、掲示板などと同一生成元、かつ任意のJavaScriptが実行できるページを第三者が作成可能になっています。

※生成元 (オリジン) は、基本的にスキーム、ホスト、ポートの組み合わせです。[^origin]

[^origin]: [生成元 | HTML Standard — Loading Web pages（日本語訳）](https://triple-underscore.github.io/browsers-ja.html#origin "生成元は Web のセキュリティモデルにおける基礎的な通貨である。 Web プラットフォームにおける，ある生成元を共有する動作者たちは、互いを信用し，同じ権限を有するものと見做される。 互いの生成元が相違する動作者たちは、潜在的に敵対的にあると見なされ，様々な程度で互いに隔離される。")

IPAへの届け出から運営者に連絡が行われるまでの日数
=================================================
| 日付け         | IPAの対応                                                                  | 当方の対応                 |
|----------------|----------------------------------------------------------------------------|----------------------------|
| **2016-04-06** |                                                                            | **届出**                   |
| 2016-04-06     | 自動応答                                                                   |                            |
| 2016-07-21     | 攻撃シナリオがCookieの窃取と想定しているかの確認                           |                            |
| 2016-07-21     |                                                                            | 返信                       |
| 2016-09-13     | ログイン機能を有するプログラムは規約違反であるため脆弱性ではないという判断 |                            |
| 2016-09-13     |                                                                            | 利用規約の読み間違いを指摘 |
| 2016-10-28     | 受理                                                                       |                            |
| **2016-11-14** | **運営者へ通知**                                                           |                            |
| 2017-04-14     | 複数回修正を促したが、運営者が修正しないと決定したため、取扱い終了の意向   |                            |
| 2017-04-14     |                                                                            | 取扱い終了を受諾           |
| 2017-04-19     | 取扱い終了                                                                 |                            |

IPAへ届け出を行ってから実際に運営者へ連絡が行くまでに、今回は222日かかりました。別件でXSSの危険性についてIPA側に解説していたので、これでもスムーズだった感じです。

脚注
====