ラボ演習 input2

これはセキュアなソフトウェア開発に関するラボ演習です。 ラボの詳細については、概要をご覧ください。

タスク

正規表現を使って、特定の形のテキスト入力の検証を練習しましょう。

背景

この演習では、Expressフレームワーク(バージョン4)とexpress-validatorライブラリを使用して、JavaScriptで書かれたサーバー側のプログラムに簡単な入力検証を追加します。

しかし、今回は正規表現を使って、特定のデータ値に対する入力検証を行います。 多くのプログラムには、特殊なデータの値があり、正規表現によって簡単にテストできるものがあります。

以下のコードは、/partsというパスに対するgetリクエストに対するハンドラをセットアップするものです。 このコードは、例えばhttp://localhost:3000/parts?id=AX-794-7に対するリクエストによって実行されます(localhostで実行し、3000番ポートで待ち受けている場合)。 もし検証でエラーがなければ、コードはパーツのIDを表示します。 検証でエラーがあった場合には、HTTPのエラーコード422(処理できないコンテンツ/"Unprocessable Content")をエラーメッセージとともに返します。 このステータスコードは、リクエストが何らかの理由で無効であることを意味します。

この場合では、適切な入力検証を実装する必要があるでしょう。 そこで、入力が一定の長さを超えていないこと、ある特定のパターンにマッチしていることを確認する必要があります。 input1のラボで書いたように、このプログラムは、クロスサイト・スクリプティング(XSS)と呼ばれる、まだ説明してない脆弱性があります。 この脆弱性については、より良い入力検証を行うことで完全に防ぐことができるでしょう。

タスクの詳細

このアプリケーションでは、パーツIDのフォーマットは常に、2文字の大文字アルファベット(AからZまで)、ハイフン(-)、1桁以上の数字、ハイフン(-)、1桁以上の数字、となっています。

タスクを完了するには、以下を実行します。

  1. app.get'/parts'という最初のパラメータの後に、コンマで区切られた新しいパラメータを追加します
  2. この新しいパラメータをquery('id')で始め、検証のためにidパラメータを選択するようにします。(このラボでは、この部分は書かれていません)
  3. ピリオド(.)を追加し、検証要件isLength()を追加します。
  4. このisLengthメソッドは、カッコ内にオプショナルの引数として、最小値や最大値といった情報を与えるオブジェクトを取ることができます。 今回は、最大値のみ検証したいので、isLength({max: 最大値})というような形になるはずです。 JavaScriptをよく知っている方は、この長さ(Length)の値はUTF-16での文字単位で表されることもご存知でしょう。今回の目的には問題ありません。

また、入力が正規表現を使ったパターンにマッチしていることも検証する必要があります。 この場合は、以下のように行います。

  1. さらにピリオド(.)と検証要件matches()を追加します。
  2. カッコの中にスラッシュ(/)、続けてマッチさせる正規表現のテキスト、最後にスラッシュ(/)を与えなければいけません。 JavaSriptでは、正規表現はスラッシュ(/)によって囲まれて表現されます。
  3. 正規表現の全体がマッチするようにしてください(つまり、^$を使いましょう)。
  4. また、大文字一文字にマッチさせるパターンは、[A-Z]であることを忘れずに。

必要に応じて、「ヒント」ボタンと「諦める」ボタンを使用してください。

演習 ()

下記のコードを、クエリパラメータidが80文字以下であり、パーツIDのフォーマット要件に合致している場合にのみ受け入れられるように変更してください。 フォーマットは、2文字の大文字アルファベット(AからZまで)、ハイフン(-)、1桁以上の数字、ハイフン(-)、1桁以上の数字、です。

// Expressフレームワークとexpress-validatorライブラリのセットアップ
const express = require("express");
const app = express();
const { query, matchedData, validationResult } =
    require('express-validator');

// リクエストの実装 (例:http://localhost:3000/parts?id=1)
app.get('/parts',

  (req, res) => { // /partsが現れたときに実行
    const result = validationResult(req); // エラーを取得
    if (result.isEmpty()) { // エラーがない場合
      const data = matchedData(req); // マッチしたデータを取得
      return res.send(`You requested part id ${data.id}!`);
    }
    res.status(422).send(`Invalid input`);
  })


このラボは、Linux FoundationのDavid A. Wheelerによって開発されました。