|
| 1 | +<!DOCTYPE html> |
| 2 | +<html lang="ja"> |
| 3 | +<head> |
| 4 | +<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
| 5 | +<meta name="viewport" content="width=device-width, initial-scale=1"> |
| 6 | +<link rel="stylesheet" href="https://best.openssf.org/assets/css/style.css"> |
| 7 | +<link rel="stylesheet" href="checker.css"> |
| 8 | +<script src="checker.js"></script> |
| 9 | +<script src="input1.js"></script> |
| 10 | +<link rel="license" href="https://creativecommons.org/licenses/by/4.0/"> |
| 11 | + |
| 12 | +<!-- See create_labs.md for how to create your own lab! --> |
| 13 | + |
| 14 | +</head> |
| 15 | +<body> |
| 16 | +<!-- For GitHub Pages formatting: --> |
| 17 | +<div class="container-lg px-3 my-5 markdown-body"> |
| 18 | +<h1>ラボ演習 input1</h1> |
| 19 | +<p> |
| 20 | +これはセキュアなソフトウェア開発に関するラボ演習です。 |
| 21 | +ラボの詳細については、<a href="introduction.html" target="_blank">概要</a>をご覧ください。 |
| 22 | + |
| 23 | +<p> |
| 24 | +<h2>ゴール</h2> |
| 25 | +<p> |
| 26 | +単純なデータ型の入力の検証を練習します。 |
| 27 | + |
| 28 | +<p> |
| 29 | +<h2>背景</h2> |
| 30 | +<p> |
| 31 | +この演習では、Expressフレームワーク(バージョン4)とexpress-validatorライブラリを使用して、JavaScriptで書かれたサーバー側のプログラムに簡単な入力検証を追加します。 |
| 32 | +ポイントは、これらの特定の技術について学ぶことではなく、一般的に安全なソフトウェアを書く方法を学ぶことです。 |
| 33 | + |
| 34 | +<p> |
| 35 | +<!-- https://expressjs.com/en/guide/routing.html --> |
| 36 | +Expressでは、システムが特定のリクエストを受け取ったときに、関数のリスト"handlers(ハンドラ)"を実行するように指定できます。 |
| 37 | +<tt>express-validator</tt>ライブラリは、バリデーションチェックを簡単に追加できるようにするための関数のセットを提供しています。 |
| 38 | + |
| 39 | +<p> |
| 40 | +以下のコードでは、<tt>/invoices</tt> パスの <tt>get</tt> リクエストに対してハンドラを設定しています。バリデーションエラーがない場合は、コードは請求書IDを表示します。 |
| 41 | +バリデーションエラーがある場合は、HTTPエラーコード422"Unprocessable Content(処理できないコンテンツ)"で応答します。 |
| 42 | +これは、何らかの理由でリクエストが無効であったことを示すステータスコードであり、エラーメッセージも表示されます。 |
| 43 | + |
| 44 | + |
| 45 | +<p> |
| 46 | +残念ながら、このプログラムは適切な入力検証を行っていません。 |
| 47 | +このアプリケーションでは、<tt>id</tt>は1から9999までの整数でなければなりませんが、そのチェックを実行していません。 |
| 48 | +そのため、このプログラムにはクロスサイト スクリプティング(XSS)と呼ばれる、まだ説明していない脆弱性があります。 |
| 49 | +このXSS脆弱性により、攻撃者は<tt>id</tt>の中に悪意のあるスクリプトを挿入することができてしまうので、ビューアーがそれを自動的に実行する可能性があります! |
| 50 | +この脆弱性は、入力検証をすることで完全に防ぐことができます。 |
| 51 | + |
| 52 | +<p> |
| 53 | +<h2>タスク</h2> |
| 54 | +<p> |
| 55 | +タスクを完了するには、以下を実行します。 |
| 56 | +<ol> |
| 57 | +<li><tt>app.get</tt>の最初のパラメータ<tt>'/invoices'</tt>の後に、コンマで区切られた新しいパラメータを追加します。 |
| 58 | +<li>この新しいパラメータを<tt>query('id')</tt>で開始して、検証用の<tt>id</tt>パラメータを選択します (開始しやすいようにこの部分は入力してあります)。 |
| 59 | +<li><tt>query('id')</tt>の後(終了のカンマの前) に、ピリオド(<tt>.</tt>)と検証要件 <tt>isInt()</tt>を追加します |
| 60 | +(<tt>isInt()</tt>は、名前付きパラメータが整数であることを検証します)。 |
| 61 | +<li><tt>isInt</tt>メソッドは、括弧内のオプションパラメーターとして、最小値と最大値を提供するオブジェクトを受け取ります |
| 62 | +(例: <tt>isInt({min: YOUR_MINIMUM, max: YOUR_MAXIMUM})</tt>) 。許容範囲を指定するには、minとmaxを設定します。 |
| 63 | +</ol> |
| 64 | + |
| 65 | +<p> |
| 66 | +注意: JavaScript の名前は大文字と小文字が区別されるため、<tt>isint</tt>では機能しません。 |
| 67 | +このパラメータの末尾をコンマで示すことを忘れないでください (開始時に入力されているテキストではこれを行っています)。 |
| 68 | + |
| 69 | +<p> |
| 70 | +必要に応じてヒントボタンを使用してください。 |
| 71 | + |
| 72 | +<p> |
| 73 | +<h2>Interactive Lab (<span id="grade"></span>)</h2> |
| 74 | +<p> |
| 75 | +<b> |
| 76 | +以下のコードは、クエリパラメータ<tt>id</tt>を入力として受け入れます。<tt>id</tt>が1から9999までの整数 (1と9999も含む) である場合にのみ、受け入れられるように変更してください。 |
| 77 | +</b> |
| 78 | +<p> |
| 79 | +<!-- |
| 80 | +You can use this an example for new labs. |
| 81 | +For multi-line inputs, instead of <input id="attempt0" type="text" ...>, use |
| 82 | +<textarea id="attempt" rows="2" cols="65">...</textarea> |
| 83 | +--> |
| 84 | +<form id="lab"> |
| 85 | +<pre><code |
| 86 | +>// Set up Express framework and express-validator library |
| 87 | +const express = require("express"); |
| 88 | +const app = express(); |
| 89 | +const { query, matchedData, validationResult } = |
| 90 | + require('express-validator'); |
| 91 | + |
| 92 | +// Implement requests, e.g., http://localhost:3000/invoices?id=1 |
| 93 | +app.get('/invoices', |
| 94 | +<input id="attempt0" type="text" size="65" spellcheck="false" |
| 95 | + value=" query('id'),"> |
| 96 | + (req, res) => { // Execute this code if /invoices seen |
| 97 | + const result = validationResult(req); // Retrieve errors |
| 98 | + if (result.isEmpty()) { // No errors |
| 99 | + const data = matchedData(req); // Retrieve matching data |
| 100 | + return res.send(`You requested invoice id ${data.id}!`); |
| 101 | + } |
| 102 | + res.status(422).send(`Invalid input`); |
| 103 | + }) |
| 104 | +</code></pre> |
| 105 | +<button type="button" class="hintButton">Hint</button> |
| 106 | +<button type="button" class="resetButton">Reset</button> |
| 107 | +<button type="button" class="giveUpButton">Give up</button> |
| 108 | +<br><br> |
| 109 | +<p> |
| 110 | +<i>This lab was developed by David A. Wheeler at |
| 111 | +<a href="https://www.linuxfoundation.org/" |
| 112 | +>The Linux Foundation</a>.</i> |
| 113 | +<br><br><!-- These go in the last form if there's more than one: --> |
| 114 | +<p id="correctStamp" class="small"> |
| 115 | +<textarea id="debugData" class="displayNone" rows="20" cols="65" readonly> |
| 116 | +</textarea> |
| 117 | +</form> |
| 118 | + |
| 119 | +</div><!-- End GitHub pages formatting --> |
| 120 | +</body> |
| 121 | +</html> |
0 commit comments