Enhancement(機能追加・改善) #1741
完了XSS 脆弱性、 CSRF 脆弱性のテストを完備できるように体制を整える
Kousuke Ebihara さんが約14年前に追加. 13年以上前に更新.
100%
説明
XSS 脆弱性、 CSRF 脆弱性のテストを完備できるように体制を整える
http://www.openpne.jp/archives/5532/#m-5 も参照のこと。
- XSS 脆弱性のテストをできるかぎりテンプレート化する
- CSRF 脆弱性のテストをできるかぎりテンプレート化する
- これらのテストの動作を妨げないように、既存の functional test をメンテナンスする
- XSS, CSRF 脆弱性のテストの書き方についてマニュアルを作り、人海戦術ですべてのアクションについての両脆弱性のテストを完備できるようにする
Kousuke Ebihara さんが約14年前に更新
XSS 脆弱性のテストについては http://github.com/ebihara/OpenPNE3/commits/36-functional-test-improvement にて動いています。
Kousuke Ebihara さんが約14年前に更新
マニュアルはこんな感じか
テスト作成手順¶
まずリストを確認し、 XSS の functional test が作られていないアクションについて、テストを作成します。
作業に入る前に、リストのテストを作成したいアクションの欄をマークしてください。
リストの更新が終わったら、そのアクションの全テンプレートを確認します。テンプレート中にユーザ入力値に基づいて動的に生成される箇所があれば、その出力についてテストを記述する必要があります。
本来はユーザ入力値に限らず、動的な値を埋め込むすべての場所に対して、 HTML 出力を意図している場合を除いて、 HTML 特殊文字のエスケープがおこなわれているかどうかを確認するべきですが、作業量や難易度等を考慮し、今回はそこまではおこなわず、あくまでユーザ入力値に限定します。
DB 内データの出力に関するテスト¶
まず、そのテンプレート中でモデルから得られる値を埋め込んでいるすべての箇所を列挙します。
XSS 脆弱性テスト用のテストデータ (test/fixtures/xss_test_data.yml) を確認し、テストに必要な情報がなければ作成します。
テストデータは以下のような形式になっています。
Member: html_member_1: id: 1055 # it means "XSS (X-55)" name: "<&\"'>Member.name ESCAPING HTML TEST DATA" is_active: 1
文字列を受け入れるフィールドに対して、テスト用の文字列を指定する以外には普通の fixture と変わらずに記述できます。
テスト用の文字列は、かならず、以下のような書式でなければなりません。
<&"'>モデル名.カラム名 ESCAPING HTML TEST DATA
こうして挿入されたテストデータが表示されるアクションのためのテストにおいて、 opTesterHtmlEscape が提供するメソッド群を利用することで、意図通りのエスケープがおこなわれているかどうかを確認することができます。
そのアクションの出力に存在する、「Member.name」の値がすべてエスケープされているかどうかを確認するには、以下のように opTesterHtmlEscape::isAllEscapedData() を実行します。
$browser = new opTestFunctional(new opBrowser(), new lime_test(null, new lime_output_color())); $browser ->info('member/profile') ->get('member/1055') ->with('html_escape')->begin() ->isAllEscapedData('Member', 'name') ->end()
反対に、そのアクションの出力に存在する、「Member.name」の値がすべてエスケープ*されていないかどうか*を確認するには、 opTesterHtmlEscape::isAllRawData() を実行してください。
$browser = new opTestFunctional(new opBrowser(), new lime_test(null, new lime_output_color())); $browser ->info('member/profile') ->get('member/1055') ->with('html_escape')->begin() ->isAllRawData('Member', 'name') ->end()
また、モデルの値の出力が op_truncate() によって truncate される場合は、 opTesterHtmlEscape::countEscapedData() や opTesterHtmlEscape::countRawData() を用いてください。これは、モデル名やカラム名の他に、期待するデータの数や op_truncate() に渡されている引数も受け付けます。以下は、 op_truncate($string, $width = 36, $etc = '', $rows = 3) を使用したモデルの値の出力が 3 つ存在することをテストする場合の例です。
$browser = new opTestFunctional(new opBrowser(), new lime_test(null, new lime_output_color())); $browser ->info('member/profile') ->get('member/1055') ->with('html_escape')->begin() ->countEscapedData(3, 'Member', 'name', array( 'width' => 36, 'etc' => '', 'rows' => 3, )) ->end()
それ以外のユーザ入力値に関するテスト¶
それ以外のユーザ入力値についても、変則的ではありますが、同じようにしてテストをおこなうことができます。
たとえば、アクションの出力中に含まれるリクエストパラメータ html の出力をテストしたい場合、以下のように記述してください。
$browser = new opTestFunctional(new opBrowser(), new lime_test(null, new lime_output_color())); $browser ->info('member/profile') ->get('member/1055', array('html' => opTesterHtmlEscape::getRawTestData('request', 'html'))) ->with('html_escape')->begin() ->isAllEscapedData('request', 'html') ->end()
これにより、 <&"'>request.html ESCAPING HTML TEST DATA という値の出力をテストすることになります。
opTesterHtmlEscape::getRawTestData() および opTesterHtmlEscape::isAllEscapedData() の第一引数や第二引数の値は、そのアクション内でユニークなものになっていればなんでも構いません。
Kousuke Ebihara さんが約14年前に更新
対応するべきアクションの一覧(作業進捗状況の一覧になるべきもの)は http://spreadsheets.google.com/pub?key=0Ain-euBnqQDLdElHWS1DbFBzRWthMnZUdmZxTlpnQnc&hl=en&output=html にあります (まだ作成途中です)
Kousuke Ebihara さんが約14年前に更新
https://spreadsheets.google.com/pub?key=0Ain-euBnqQDLdGxzMnoyOFhBaUlQUVJnS0Y0YXNzZlE&output=html
ここで進捗管理がおこなえるようにしました。この扱い方等のルールについても、なるべく早く準備します。
とり急ぎ。
Kousuke Ebihara さんが約14年前に更新
http://redmine.openpne.jp/projects/op3/wiki/Rule_of_functional_test_for_36x
この作業についてのルールを書きました。
誠二 天重 さんが10年以上前に更新
- 関連している Bug(バグ) #1877: functional test で特定のパラメータで checkElement() を呼び出すとエラーになる を追加