CVE-2012-1297: CSRF

CVE(Common vulnerabilities and exposures)にCVE-2012-1297として、ContaoのCSRF(Cross Site Request Forgery)の問題が登録されました。これは既にContaoのIssue 4007で議論されていて、最終的にはContao 3、次のメジャーリリースで最終的に解決するというのが、この文書を書いている時点での状況です。

なお、ここに書いてある内容は私なりの調査と解釈によるものであってContao開発チームの公式なものでないことを改めて強調しておきたいと思います。

問題の発端

最初に問題を指摘したと思われるのはPacketstrom-Securityの記事で、

  1. 特定の条件、具体的にはContaoのバックエンドに管理者または通常のユーザーでログインして、
  2. 悪意を持って用意したページをアクセスすると、
  3. バックエンドのユーザー、ニュースの記事、ニュースレターを削除できる。

と、いうインパクトのある内容です。悪意を持ったページの例としては、同記事には以下のようなコードの例が掲載されています。

<html>
<body onload="javascript:document.forms[0].submit()">
<H2>CSRF Exploit to delete News</H2>
<form method="POST" name="form0" action="http://<contao_ip>:80/contao/main.php?do=news&act=delete&id=1">
</form>
</body>
</html>

目的を達成する、POSTのリクエストを含んだHTMLのフォームを書いておいて、それをbodyタグのonload属性に書いたJavaScriptで提出するといった内容です。

但し、formタグのaction属性に含まれるURLは、攻撃しようとしているContaoのサイトのURLで、<contao_ip> と記述されていますが、名前ベースの仮想ホストを使用している場合は、そのサイトの名前のURLでアクセスしないと不可能でしょう。

仮に攻撃に成功したとしても、取り消しを使用して復元できます。(取り消しのテーブルの内容の消去は、フォームの項目を含んだPOSTが必要なため、今回の攻撃方法では実行できません。)

さらに、最初にインストールツールで作成する管理権ユーザーのIDは1となるため、このユーザーを狙った攻撃はしやすく思え、さらに管理者ユーザーが一人だけだと危うく見えます。しかし、ログインしている状態の管理者ユーザーを自分で削除することはできません。従って、この場合には攻撃は成功しません。

議論

この問題はCSRF(Cross Site Request Forgery)で、Cross Site Script(XSS)ではありません。実際にセキュリティの問題を突くには複数の前提条件が必要なことと、フォームで送信する内容そのものは正常に送られる可能性があるものでサービスを提供する側での対応には難しい面もあります。

可能性としてContaoのバックエンド以外に、このようなリンクを用意してバックエンドの処理を直接提供したいという場合もあるかもしれません。この場合、一旦Contaoのバックエンドの認証を行った後で、実際の処理を行うことになります。

コードの調査

コードを確認すると、問題なのは攻撃のコードにあるようにPOSTで提出するフォームの項目が1つもない場合です。フォームの項目が1つでも存在するPOSTの場合は、

  • Contao 2.9まではRefererの検査
  • Contao 2.10移行はリクエストトークンの検査

が行われて、このような攻撃は成功しません。言い替えると、本当にバックエンドで行った処理に限って実行します。

フォームの項目が1つもないPOSTはAjaxな処理に使用されていそうです。それが失敗しても良いことと引き換えに、フォームの項目が1つもない場合に同様な検査を加えると問題を回避できることになります。

pkgsrcでの対応

リクエストトークンによる検査は、呼び出す側の変更も確実に必要となるため副作用がどこまで波及するか予測が難しいため、pkgsrcではContao 2.9の頃のReferによる検査を加えて防止するコードを追加してみました。

それでも何らかの副作業が起きる恐れを考慮して、以下を system/config/local.config.php に追加するとオリジナルのままの動作とするようにしてあります。

$GLOBALS['TL_CONFIG']['disableCompatRefererCheck'] = true;

Contao側の公式な対応

現時点ではContao 2.11に具体的な対応が行われる予定はなく、Contao 3で対応が行われます。その内容は、

  1. 外部のサイトからのPOSTのような、リクエストトークンを持たない場合は確認のポップアップを表示します。
  2. ポップアップで処理を受け入れた場合は実際に処理を勧め、必要な場合は認証を伴います。

といったものとなるようです。これで、セッションがタイムアウトしたところから処理を続ける場合も救えるようになるようです。その一方で、一部のテンプレートの変更も併せて行っています。

ユーザー側の対処

今回の問題は、

  • バックエンドにログインしたままで怪しいところをアクセス
  • 予め標的を絞って用意されたページを準備

といった前提条件が必要なため、実際の危険性は然程大きいとは言えません。

また、ユーザー側もブラウザーにCSRFを防止するためのアドオンなどを活用すると良いでしょう。Firefoxの場合はRequestPolicy辺りがたいへん有効です。

まとめ

今回のセキュリティの問題をまとめると以下のようになります。

  • CVE-2012-1297は致命的に恐いものではない。
  • フロントエンド、公開しているウェブサイト側には何の問題もない。
  • バックエンドで通常のユーザーでログインしていると、その権限で可能な意図せぬ処理をしてしまう可能性がある。
  • バックエンドで管理者ユーザーでログインしている場合は、ユーザーを含めた削除といった意図せぬ処理をしてしまう可能性がある。
  • 但し、ログインしている管理者ユーザー自身の削除はできない。
  • いずれもログインしたままで、他の怪しいウェブサイトにアクセスして発生する可能性がある。
  • FirefoxのRequestPolicyアドオンのようなプラグインを使用して、安全性を高められる。