20201107_アウトプット(セキュリティについて)

アプトプット画像

学んだこと 7時間

  • 脆弱性とは、Webアプリケーションにおいて悪意のある人に攻撃を仕掛けられる際の弱点のこと。

  • 次のような被害が想定される。
    ①個人情報を勝手に閲覧される
    ②Web内容が改ざんされる
    ③Webページ自体が利用不可能になる

  • 4つの攻撃と対策について学ぶ。
    (1)JavaScriptによるセキュリティ攻撃
    (2)セッションを用いたセキュリティ攻撃
    (3)不正なリクエストを行うセキュリティ攻撃
    (4)SQLによるセキュリティ攻撃

(1)JavaScriptによるセキュリティ攻撃

JavaScriptを利用した攻撃方法をXSSクロスサイトスクリプティング )という。

XSSとは?

ユーザーのクライアント側で、悪意のあるプログラム(Script)を埋め込み、サイトの利用者を攻撃する手法。

どんな種類があるの?
  • 反射型XSSと格納型XSSの大きく2つがある。

  • 反射型XSSは、「ユーザーが自由に書き込める場所」に「悪意のあるページへ遷移させる」罠(URLやアラート表示)を仕掛けて「遷移したこと」によって個人情報等を抜き取る手法。

  • 格納型XSSは、「脆弱性のあるアプリ」に「ユーザーが正規のサイトだと思って入力させる」罠を仕掛けて、個人情報等を抜き取る手法。

XSSの対策は?
  • 罠を仕掛けられないように、エスケープ処理をすること。(HTMLにおいて意味を持つ「”」や「<」を、ただの文字列に置き換える文字参照を用いること。)

  • Ruby on Rails のヘルパーメソッド<%= %>特殊文字エスケープに対応しているので、ヘルパーメソッドを用いることがXSS対策に繋がる。

  • ただし、上記方法はリロードしない間の非同期通信では使えないので、非同期通信を行っているJavaScriptの実装部分に、エスケープ(サニタイジング)を行うと良い。


(2)セッションを用いたセキュリティ攻撃

セッションIDを盗み出すまたは乗っ取る攻撃を「セッションハイジャック」という。

セッションとは?(復習)

セッションとは、データを一時的に保存しておく仕組み。
このセッションの保存先となるものがクッキー。
このクッキーが一般的には狙われる。

セッションIDとは?

一人ひとりに付与される固有の情報。(ユーザー及その状態を識別する)

セッションハイジャックされるとどうなるの?

三者の手に渡ってしまうと、そのユーザーになりすまして、クレジットカード情報や個人情報を窃取したり、SNSを乗っ取ることが可能になってしまう。

セッションハイジャックの対策は?
  • フレームワークを用いること(推測可能なセッションIDを生成しないため)

  • XSSの対策を講じること(特殊文字をただの文字列にしたり、ヘルパーメソッドを用いたりすること)

  • 安全なインターネット環境を用いること
    *インターネット通信を暗号化する仕組みをSSL(Secure Socket Layer)という。
    https://というようにsがついていると暗号化されている。
    *Herokuなどのプラットフォームでは自動で暗号化してくれるが、独自でサーバーを契約する場合には自身でSSLに対応する必要あり。

  • ログイン後にセッションIDを変更する。(常に変更し続け、セッションIDが固定化しないようにするため)


(3)不正なリクエストを行うセキュリティ攻撃

サーバーサイド側で、重要な処理(決済・メール送信・パスワード変更)を本人になりすまして(判別できずに)処理できてしまう攻撃を「CSRFロスイト:サイトをまたいだ、エスォージェリ:リクエストの偽装)」という。

どんな風な流れで、その攻撃が行われるの?

①攻撃者が、ユーザーの情報を盗み出す悪意Webサイトを用意。
②ユーザーが、別の脆弱性のあるWebアプリにおいてログイン。その状態で①のサイトリンクをクリックしてしまう。(セッションハイジャックが成立)
③②の情報を元に、攻撃者は脆弱性のあるWebアプリに不正リクエスト。
脆弱性のあるWebアプリは、リクエストが不正なものなのか判別できず、購入などの処理が実行される。(CSRFが成立)

CSRFの対策はどんなリクエスト時に行う?
  • 勝手に処理が実行されては困るようなリクエストに対して実装する。(例:購入確定、ユーザー情報更新など)

  • 具体的にはHTTPメソッドがPOSTやDELETEなどのデータベース情報を書き換えるためのリクエストの時に対策しよう。

CSRFの対策とは?
  • パスワードを再入力させる。

  • リクエストへ「トークン」(秘密情報)を埋め込む
    トークンとは?:一度だけ使用可能なパスワードのこと。
    *ログイン時に、一度だけ使用できるパスワードを発行し、埋め込むことで、現在、本人のログイン情報+本人からのリクエストであるかを判別できる。

トークンはRuby On Railsに実装されているの?
  • 実装されている。(フォームのヘルパーメソッドなど)

  • ただし、HTTPメソッドがGETでは、トークンが発行されないので、重要な処理のHTTPメソッドが何か注意すること

トークンが存在するHTTPメソッド】
POST ・ DELETE ・ PATCH ・ PUT
厳密にいうと、POST以外の3つのHTTPメソッドは、一部のブラウザがメソッドをサポートしていない場合があるので、「POST」として読み替えてトークン🔑を発行している。

ここまでのまとめ

総合的にセキュリティ対策することが大事!
XSS対策だけ、CSRF対策だけでは意味なし)


(4)SQLによるセキュリティ攻撃

SQLインジェクション💉とは?

入力フォームから送信した値により、アプリケーションが本来想定しないSQLを実行させ、データベースを改ざんしたり、不正に情報を入手する攻撃手法のこと。

SQLインジェクションの対策は?
  • 意味のある特殊文字エスケープさせること。(つまり、ただの文字列にすること)

  • より厳格なSQL文の生成を行うこと。(つまり、プレースホルダーを使ったり、フレームワークから、SQLにデータを取りに行く時に、その命令文を包んで外から編集できないようにすること。)

SQLインジェクション」を通して、SQLの理解深まったこと

メンターさんに聞いて理解が深まった!忘れないうちにメモ。

【わからなかったところ】

  • 疑問点1:SQLにおけるシングルクォーテーションの役割

  • 疑問点2:「?」がプレースホルダーとは?(よくわからない)

  • 疑問点3:「ただの文字列」に変換するのはわかったけれど、find_by_sqlで変数に代入するのはなぜ?

👩{順番に見ていこう!

【疑問点1の解決】SQLにおけるシングルクォーテーションの役割👉SQL文の捉え方とは

(1)ここで、認証に用いられるSQL文は以下になります。

-- $uid(user_id)と$pwd(password)はユーザーのフォームの入力値
SELECT * FROM users WHERE user_id='$uid' AND password='$pwd'

(2)ここに、以下のように入力します。

$uid  tarou
$pwd  ' OR 'A'='A

(3)すると前述のSQL文は以下のようになります。(ダメな例)

SELECT * FROM users WHERE user_id='tarou' AND password='' OR 'A'='A'

上記(1)〜(3)で言いたいことは、「ただの文字列」にしないと(エスケープしないと)パスワードが上書きされてしまうよ、ということ。

ここで初めて知った概念

SELECT構文は最優先されること(「'」無視)
  • SQLORANDWHEREというようなSELECT構文は、シングルクォーテーションで囲われていても、SELECT構文化するよ。
    👉なので、(2)でシングルクォーテーションで囲われているのに、(3)ではちゃんとORの役割果たしている。
「文字列」の時にデフォルトは「''」を2つ用意すること。(「'」補完)
  • シングルクォーテーションが一つ欠けていても補完するよ。
    👉なので、(2)の一番後ろにシングルクォーテーションなくても(3)で補完されている。

    【疑問点2の解決】「?」がプレースホルダーとは?(よくわからない)👉プレースホルダーの捉え方

以下の「?」をプレースホルダーという。

SELECT * FROM users WHERE user_id=? AND password=?

簡単にいうと
👨{「?」の部分に、これからidとパスワードいれるから!受け入れの準備よろしくね!
ということ。

予め宣言しておくことで
「ここにidとパスワード入れる構文なんだな〜」
ということがわかり、ここにユーザーが特殊文字にあたる値を入れても、SELECT * FROM users WHERE user_id=? AND password=?の構文自体は崩されないということ。

すなわち、さっきの' OR 'A'='A'を入力した時、「ただの文字列」と認識される。



【疑問点3の解決】「ただの文字列」に変換するのはわかったけれど、find_by_sqlで変数に代入するのはなぜ?👉find_by_sqlメソッドを使用する際のSQLインジェクション脆弱性

  • (前提として・・・)Ruby on Railsにおいて、ActiveRecordのメソッドを使用する場合はSQLインジェクションが問題になることはほとんどない。なので、SQL文を書かなくていい場合には、書かないようにしよう。(ActiveRecordを活用しよう)

  • (結論として、これから行うことは)find_by_sqlメソッドを使用するときは、脆弱性があるので、①検索入力される文字をただの文字列にすること、②入力された文字を検索する際のSQL命令文についてもその命令文を包んで外から編集できないようにすることの2つを対策する。


データベースから、探したい情報があるか探すことのできる「検索機能」について、find_by_sqlメソッドを使うには以下のような実装をする。

def self.search(search)
  if search != ""
    search = "%#{search}%"
    Tweet.find_by_sql(["select * from tweets where text like ? ", search])
  else
    Tweet.all
  end
end
上記のコードの状況説明と、ここで知った概念
  • "#{ }"式展開を活用して、変数searchに代入している。(代入することによって、その次の文で「ただの文字列の検索入力内容」としてデータベースから情報を取ってくることができる)

  • %%で囲まれているのはLIKE句。
    *「%〇〇」だと「〇〇で始める」
    *「%〇〇%」だと「〇〇を含む」
    *「〇〇%」だと「〇〇で終わる」という意味。

  • Tweet.find_by_sql(["第一引数", 第二引数])は「「第二引数」の文字を「第一引数」命令文(条件)で、Tweetモデルから見つけてきて!」という意味になる。

  • そして、命令文(データベースからどのように情報を取ってくるか)の「第一引数」を「””」で囲むことによって、外から命令文が編集されることはないまま、データベースからデータを取ってくる時に、「””」が外れて、条件が適用され、データベースから情報を取得して来る。(つまり、入力フォームに入力された内容によって、データベースに対するSQL文が操作されない、改ざんされないということ)

  • find_by_sql内において、プレースホルダーを利用するには角カッコで囲むルール。



積み残し(復習したいこと)

  • Formオブジェクト(モデルの存在しないデータを更新)

  • Rails勉強会→50%

  • カラムの追加方法、ロールバック

  • デプロイ方法



感想

今までの知識では、セキュリティ対策と言えば「(詳細はわからないけど)ファイアウォールのような守ってくれるソフトをいれる」というくらいの知識だった。 しかし、今回の学習を通して、アプリを作る段階で「悪さをさせない仕組み」を作ることが大事と知ることができた。 具体的には、
●狙われやすい場所:入力フォーム・URLなど、ユーザーがリクエストを行うタイミング(特にHTTPメソッドがGET以外の時)
●狙われる内容:セッションID、データベースの情報など。取得することによって、決済処理・SNS乗っ取り・個人情報取得等が出来るところ
●対策:フレームワークの活用、セッションIDをまめに更新する仕組みを取り入れる、トークンといって1回限りのパスワード発行の仕組みを取り入れる、リクエストを行うタイミングで「ただの文字列にする」・「データベースを操作する命令文を変えさせない」コードを書く。そして、それらを総合的に行うことが安全性を高める上で大事。
ということを学べた。
今日学んだことも、セキュリティ対策の一部だと思うので、自分がわかっていないことを自覚して、これからもアプリのセキュリティ対策の知識と取り入れて実践していきたい。