Contaoと入力の検証に関する不十分な検証

(コメント: 0)

HASHコンサルティング株式会社の徳丸さんのブログでCMS四天王のバリデーション状況を調査したところ意外な結果になったという記事が出ています。Concrete5でもCMS四天王から外れたconcrete5 のユーザーID長さと使える文字という記事が出ていましたので、少し刺激を受けてContaoの場合も見てみましょう。

Contaoでのユーザー

まず、CMS四天王やConcrete5と異なり、Contaoではユーザーはコンテンツの管理を行うバックエンドのユーザーと、公開しているウェブサイト(フロントエンド)上のユーザーであるメンバーで扱いが異なります。

  • ユーザーは権限のあるバックエンドのユーザーによってだけ新規の登録ができます。
  • メンバーは権限のあるバックエンドのユーザーが登録するか、フロントエンドに設置した「登録」のフロントエンドモジュールを介して登録ができます。

ユーザーのDCAでの定義

いずれにしても、バックエンドのデータ格納配列(DCA)に基づいて入力は検証されます。ユーザ名のような入力項目は、フォームの入力形式やデータベースの定義はDCAに記述されています。ユーザーの場合の定義部分をsystem/modules/core/dca/tl_user.phpから抜き出します:

'username' => array
{
    'label'         => &$GLOBALS['TL_LANG']['tl_user']['username'],
    'exclude'       => true,
    'search'        => true,
    'sorting'       => true,
    'flag'          => 1,
    'inputType'     => 'text',
    'eval'          => array('mandatory'=>true, 'rgxp'=>'extnd', 'nospace'=>true, 'unique'=>true, 'maxlength'=>64),
    'sql'           => "varchar(64) COLLATE utf8_bin NULL"
),

ここで入力フォームに関係する部分はinputtypeevalの部分です。

  • inputtype: textでテキスト入力
  • eval:
    • mandatory: trueを指定して必須の項目
    • rgxp: 正規表現のextndで入力値を検証
    • nospace: trueを指定して空白文字の入力を禁止
    • unique: trueを指定して値の重複を禁止
    • maxlength: 入力できる最大長を64に制限

extndによる検証は、次の文字を禁止しています。

#&()/<=>;

Contaoでのユーザー名の状況

以上を踏まえて徳丸さんの記事の項目を考えてみましょう。

シングルクォート

シングルクォートは上記のextndで禁止している文字ではありません。従って、シングルクォートを含んだユーザーを作成でき、バックエンドからログインもできました。

タグ

タグは上記のextndで禁止している文字です。このため、タグの文字を含んだユーザーを登録しようとした時点で入力エラーとなり、登録できません。

バックスラッシュ

バックスラッシュは上記のextndで禁止している文字ではありません。従って、シングルクォートを含んだユーザーを作成でき、バックエンドの(管理者ユーザーからの)ユーザー切り替えで、登録したユーザになれました。

バックスラッシュを含んだユーザー

しかし、バックエンドのログイン画面からログインはできませんでした。完全にコードを追いかけきれてはいませんが、ユーザー名をデータベースから探せていないようです。

最長な文字列

登録時はきっちりとフォームで制限されていますし、データベースのレコード長の64文字を越えるユーザー名は登録されようがありません。

一方、ログイン時は特に長さの最大長を気にした処理はしていないようで、徳丸さんの記事の四天王のCMSと同様なようです。

不正な文字エンコーディング

不正な文字エンコーディングの文字列を旨いこと渡す方法を、限られた時間内で用意できなかったので割愛します。

ナルバイト

これはバックスラッシュを含めたユーザーのログイン時の処理を調べる過程で、Input::xssClean()できっちりとナル文字(0x00)を削除していることを確認できました。エンコードされたナル文字も何段階に渡って削除をしています。

改行

Input::xssClean()で復帰(0x0d)は削除しています。改行(0x0a)については調べきれませんでした。

配列

こちらも時間切れです。

まとめにならないまとめ

さて、たいへん大雑把に見てみました。バックエンドのユーザーも、フロントエンドのメンバーも、どちらのログインのフォームで長さの検査はしていないことは思わぬ結果でした。もちろん、フォームで行ったとしても直接HTTPで送り付けられる可能性は避けられません。しっかりとリクエストトークンを処理して送らないと受け付けられないのでハードルは高そうに思えますが。

戻る

コメント

コメントを追加

6と2を加算してください。

Copyright © 2011-2024 Takahiro Kambe all rights reserved.