40歳の未経験からプログラミングスクールを受講して二十九日目

8月17日月曜日

おはようございます。昨日の晩寝付けなくて、今日の朝寝坊してランニングにいけなかった懺悔です。その他のルーティンは、きっちりとやっております。朝のランニングを夜に補うつもりです。

 

今日の学習

脆弱性

脆弱性(ぜいじゃくせい)とは、アプリケーションなどにおいて、セキュリティの弱点を作り出す仕様上の問題点のことをいいます。つまり、「Webアプリケーション上で悪意のある者に攻撃を仕掛けられる際の弱点」と言い換えることができます。

XSSクロスサイトスクリプティング

XSSとは、攻撃者が脆弱性のあるWebアプリケーション上に、悪意のあるJavaScriptのプログラム(スクリプト)を埋め込み、そのサイトの利用者を攻撃する手法です。

 

このスクリプトを埋め込んで実行させることが「スクリプティング」に該当します。

 

反射型XSS

ユーザーが悪意のあるURLをクリックすると、脆弱性のあるWebアプリケーション上でスクリプトが実行されるようにする手法です。

 

それぞれのステップについて説明します。

①ユーザーにURLをクリックさせる
悪意のある者が、ユーザーに悪意のあるURL(脆弱性のあるWebアプリケーションへ遷移するURLに細工をしたもの)をクリックさせます。ユーザーにクリックさせる方法は、メールで送付したり、掲示板などに書き込んだりします。

②ユーザーがクリックすると脆弱性のあるWebアプリケーション上でスクリプトが動く
上記の悪意のあるURLには、脆弱性のあるWebアプリケーション上で発火するスクリプトが仕込まれています。すると、ユーザーが脆弱性のあるWebアプリケーションのページを開くと、そのスクリプトが発火します。

スクリプトが発火すると、悪意のある者のサーバーへ個人情報が送られる
直前のステップで発火したスクリプトは、個人情報を抜き取るようなものでした。クリックしたユーザーの個人情報が悪意のある者のサーバーへ記録されてしまいました。

この様に、URLをクリックすると即座にレスポンスとしてスクリプトが実行されることから、「反射型」と呼ばれます。

また、上図のように別のサイト(またはメールなど)から、脆弱性のあるWebアプリケーションへ遷移したあとにスクリプトが実行されます。これが「クロスサイトスクリプティング」の「クロスサイト(Webサイト間をまたぐ)」を意味します。

格納型XSS

脆弱性のあるWebアプリケーションの投稿などに、悪意のあるスクリプトを埋め込み、ユーザーがそのWebアプリケーションを訪れたときにスクリプトが発火するようにする攻撃手法です。

 

それぞれのステップについて説明します。

①悪意のある者が、脆弱性のあるWebアプリケーションにスクリプト付きの投稿をする
フォームとして投稿する際に、スクリプトを埋め込んで投稿をします。

②ユーザーがその投稿があるページを訪れるとスクリプトが発火する
スクリプトが埋め込まれた投稿のページを開くと、そのスクリプトが発火します。または、画像にマウスを合わせるとスクリプトが発火するような仕掛けになっていることもあります。

スクリプトが発火すると、悪意のある者のサーバーへ個人情報が送られる
直前のステップで発火したスクリプトは、個人情報を抜き取るようなものでした。ユーザーの個人情報が悪意のある者のサーバーへ記録されてしまいました。

このように、脆弱性のあるWebアプリケーションにスクリプトを格納し、ユーザーが訪れたタイミングで発火するようになっていることから「格納型」と呼ばれます。

アプリケーションのSQLの不備を利用して、データベースシステムを不正に操作されることがあります。

このような攻撃方法をSQLインジェクションと言います。

SQLインジェクション

「Webページのテキスト入力欄」や「URL」などにSQL文の断片を埋め込むことで、データベースを改竄したり不正に情報を入手する手法のことです。

入力フォームから送信した値によりアプリケーションが想定しないSQL文を実行させ、攻撃を行います。

 

例えば、フォームを送信するときの文書の中に、ユーザーの権限を変更するようなSQLを仕込んで送信します。すると、サーバーサイドでそのSQL文が実行され、ユーザー権限が変更されてしまような処理が行われます。

SQLインジェクションの対策

それでは、SQLインジェクションに対して、どのような対策が行うべきなのか考えていきましょう。

一般的なSQLインジェクションの対策方法を学ぼう

この方法は、手作業でSQL文を記述し、サーバーサイドを実装する場合の対策方法です。Ruby on Railsを学んできた方々においてはあまり馴染みのない方法と言えるでしょう。ここでは、SQLの詳細について登場するため、まずは流れを掴んでいただければ問題ありません。

SQLインジェクション脆弱性を一般的に解消するためには、SQL文を組み立て実行される際にSQL文を変更されることを防ぐことです。SQL文の変更を防ぐには以下の2つの対策方法があります。

対策①:意味のある文字列の変換
基本的な対策としてあげられるものが、SQLにおいて意味を持つ特殊文字エスケープです。SQL文中では「'」が文字列の終端を意味していることがポイントです。

たとえば、データベース内に格納されたuser_idとpasswordが一致すると、ログインなどの認証を認めるアプリケーションを考えてみましょう。

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

1

2

-- $uiduser_id)と$pwdpassword)はユーザのフォームの入力値

SELECT * FROM users WHERE user_id='$uid' AND password='$pwd'

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

1

2

$uid  tarou

$pwd  ' OR 'A'='A

すると前述のSQL文は以下のようになります。

1

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

もし、特殊文字である「'」をエスケープしていなかった場合、WHERE句の中ではuser_id='tarou' AND password=''と'A'='A'の2つの条件を判定することになります。この2つの文はORでつながっているため、どちらかがtrueの場合は認証が認められてしまいます。'A'='A'は確実にtrueのため、user_idとpasswordが一致していなくても認証が通ってしまいます。

しかし、特殊文字をきちんとエスケープした場合はユーザからの入力の「'」は単なる文字列として扱われるため、password=' ' OR 'A'='A'という一連の文字列となり、SQL文は実行されません。実際にエスケープを行う場合は、フォームから「'」を含む文字列が送信された場合に、別の記号で置き換えるような実装をすることで実現できます。

対策②:より厳格なSQL文の生成
ユーザからの値をSQLへ反映する前に、SQL文の構造を確定する仕組みをとることで、より厳格に対策できます。SQL文確定後にユーザからの値を入れて実行するためユーザの入力値によってSQL文が変更されることはありません。

先ほどの例を用いると、データベースに対する処理を行う前に、以下のSQLを用意しておきます。

1

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

ここで、user_idとpasswordの値として「?」が使われており、これをプレースホルダーといいます。

 プレースホルダ

プレースホルダーはユーザの値が入力されるまでの一時的な仮引数のようなものです。あらかじめ確定したSQLにおいて、可変の値が入力される箇所に配置します。

このようにプレースホルダーを用いて設定すれば、「usersテーブルにおいてuser_idとpasswordの組み合わせが一致するかどうかを判定できる」という構文を事前に確定することができます。この後ユーザからどのような値が入力されようとも、上記の構文の中でSQLが実行されることになり、SQLインジェクションを防ぐことが可能です。

すなわち、passwordとして' OR 'A'='A'と入力をしても、これらは単純な文字列として認識されます。