🔑

初心者による初心者のためのセキュリティ 第1号

2021/09/15に公開

はじめに

この記事は、Webエンジニアになってからまだ日が浅い私が、今まできちんと学んでこなかったセキュリティについて、自分なりに学習し、まとめたものになります。
基本的には俗にいう「徳丸本」を読んで、これからプログラミングを勉強されるような方に、できるだけわかりやすくセキュリティの基礎をお伝えすることを目的としています。
ちなみに自分の勉強も兼ねてアウトプットしているので、できるだけ定期的に書いていこうと思います。
言語・フレームワークについてはRubyやRuby on Railsを中心に書いていきます。

今回の内容

  • webアプリの機能、脆弱性
  • 入力処理におけるセキュリティ

webアプリの機能、脆弱性

脆弱性やセキュリティの話をする前に、まずはwebアプリケーションについて簡単に説明します。
webアプリケーションは、基本的にはHTTPリクエストを受けて、HTTPレスポンスを返します。
そこではフォームから情報を入力したり、データを検索したり、ファイルをアップロードしたりと、様々なことができる反面、セキュリティに問題がある部分が存在すると、せっかく作ったwebアプリケーションが攻撃を受け、自分だけではなく、友人、家族、取引先、見ず知らずの人が被害を受けたり、訴訟に発展してしまったりと想像以上の範囲に悪影響が及びます。

上記のような被害を受けないためにも、webアプリケーションの脆弱性を少しでも知り、対策を行っていくことが重要です。

有名な脆弱性について

世の中にはいろいろな脆弱性をついた攻撃が存在しますが、その中でも有名なのは「インジェクション」をされてしまうパターンです。インジェクションというなの通り、よろしくない文字列やSQLをフォームやアドレスバーに「注入」されてしまい、サイトの内容を書き換えられたり、自分のアカウントにログインされてしまったりします。
例えば、以下のような脆弱性があります。

  • XSS(クロスサイト・スクリプティング)
  • HTTPヘッダインジェクション
  • SQLインジェクション

それぞれ細かい特徴はありますが、ものすごくざっくりいうと
予期しない文字列やSQLをwebアプリの中にねじ込まれて、データの変更が行われたり、ログインされたり、情報を抜き取られてしまったりします。

恐ろしいですよね…。

入力処理におけるセキュリティ

Webアプリケーションはどんなものでも、HTTPリクエストが送られ、処理が行われ、出力されるという処理の連続です。
この入力処理のところで脆弱性があると、そこを突かれてアプリケーションに侵入されたり、重要な情報を盗み出されたりしてしまいます。そのため、そこをいかにして守っていくかを次にまとめていきます。

入力処理において必要な対策は主に下記の3つです。

  1. 文字エンコーディングの検証
  2. 文字エンコーディングの変換
  3. 入力値の検証

この中でも、私のような初心者にもわかりやすい、3.を中心に説明したいと思います。
入力値の検証というのは、いわゆるバリデーションというやつです。

例えば、フォームの入力値を数字のみ受け付ける、空文字列を受け付けないようにする、必須項目を作る、など、日常の中にも溢れていますよね。
この処理をすることで、どんな意味があるのでしょうか?

もちろん、電話番号などにhogehogeとか入れられるのを防ぐためという理由もあります。
そしてもう一つ大事なのが、脆弱性を突かれて攻撃されそうな時に、それを防ぐためという目的があります。

きちんと入力値の検証を行なっていれば仮にアプリケーションに脆弱性があっても、scriptやSQLなどは埋め込めなくなることもあります。なので、フロントエンドでの入力値検証というのはしていた方が良いということです。
ここで重要なのは、入力値の検証は、あくまでも保険的な対策にしか過ぎないという点です。

入力値の検証だけでは対策にならない

なぜ、そのようなことになるのでしょうか?入力値検証をがっつりやっておけば問題ないようにも思えます。しかし、入力値検証というのはアプリケーションの仕様によって決まるので、例えば「全ての文字を許容する」というアプリケーションの場合は入力値の検証では何も防ぐことができません。

とはいえ、先ほど書いたように、何もやらないよりはいくらかマシになるので、フォームの入力の際にはできるだけ入力値の検証(バリデーション)をかけてやっていくことが大事かと思います。

最後に、いくつかバリデーションに関連する正規表現のコードを共有して今回はおしまいにしたいと思います。

郵便番号(数値3桁-数値4桁)

# \Aは文字列の始まりを表す
# \d{数値}は何らかの数値が3つ連続するという意味
/\A\d{3}[-]\d{4}\z/

電話番号(ハイフンなし 11桁)

/\A\d{11}\z/

12時間表示の時刻(01:23:45 のようなパターン)

/\A(0[0-9]|10|11):[0-5][0-9]:[0-5][0-9]\z/

以上です。次回はXSS(クロスサイト・スクリプティング)あたりについて説明しようと思います。

Discussion