セキュリティ

INPUT · スライド

攻撃の手口と防ぎ方

01 / 12

攻撃は必ず「穴」から入る

手口の名前は山ほどあるけれど、入口は3つしかないよ。

  • コードの穴 … 入力の扱いが甘いところを突かれる
  • 人の油断 … だまされて自分で開けてしまう
  • … 数で押されて動かなくなる

このうち、いちばん自分に関係があるのは1つ目だよ。攻撃はサーバの奥から降ってくるものではなく、自分が書いたコードの、外から来た文字をそのまま使っている行から入ってくる。

そういう「突かれる弱点」のことを 脆弱性 と呼ぶ。脆弱性は消して回るものではなく、見つけて直し続けるものだよ。だから後半では、直すやり方と、直しきれない間にどこで食い止めるかを見ていく。

02 / 12

SQL インジェクション ― 文字をつないで SQL を作ると

SQL を書いた経験があるなら、この攻撃はいちばんぞっとするはずだよ。

入力された名前で検索したくて、文字列をつないで SQL を組み立てたとする。ふつうの名前なら何も起きない。でも入力が ' OR 'A'='A だったらどうなるだろう。

つないだ結果は「名前が空、または A = A」という条件になる。A = A はいつでも成り立つので、表の全員ぶんが返る-- を混ぜればその先を丸ごとコメントにできるし、; をつければ別の文を足すこともできる。

狙われているのはデータベースの弱点ではなく、文字をつないだ自分のコードだよ。攻撃者は入力欄に文字を打ちこんだだけで、こちらの SQL の構文そのものを書きかえている。

const n = req.nameconst sql =  "SELECT * FROM users" +  " WHERE name = '" +  n + "'"n が  ' OR 'A'='AWHERE name = ''  OR 'A'='A'→ 全員ぶんが返る

03 / 12

防ぎ方は「値を値として渡す」

対策の考え方はひとつだけ。入力された文字が、SQL の記号として解釈されないようにすることだよ。

いちばん確かなのが プレースホルダ。SQL の中に ? の穴を空けておいて、値は別枠で渡す。こうすると ' が来ても、それは「文字としての '」であって構文の区切りにはならない。文字をつないで作らないので、そもそも書きかえる隙がない。

プレースホルダが使えない場面では、' のような特別な意味をもつ文字を無害な形に置きかえる(エスケープ)。これも狙いは同じだよ。

ここで気をつけたいのが、似ているけれど別の攻撃の対策と混ぜないこと。試験ではわざと並べてくる。

  • HTML タグを別の文字列に置きかえる → クロスサイトスクリプティングの対策
  • ../ を含む入力を弾く → ディレクトリトラバーサルの対策
  • 入力の長さを制限する → 長さの問題(バッファオーバフローなど)の対策
// 値は値として渡すdb.query(  "SELECT * FROM users" +  " WHERE name = ?",  [n])

04 / 12

クロスサイトスクリプティング ― 受け取った文字をそのまま出す

今度は出すときの穴だよ。投稿されたコメントを画面に出すつもりで innerHTML に入れたとする。

コメントが <img src=x onerror="..."> だったら、それは文字ではなくタグとして解釈される。読み込みに失敗した瞬間に onerror の中身が動く。つまり攻撃者が書いた JavaScript が、見ている人のブラウザで動くわけだよ。

動く場所が「訪問者のブラウザ」だというのが、この攻撃の要点。Cookie を抜かれたり、偽のログイン欄を出されたりする。これを クロスサイトスクリプティング(XSS)と呼ぶ。

防ぎ方は、出すときに HTML のタグとして解釈されない形に置きかえること(エスケープ)。textContent に入れれば、タグの形をした入力もそのままただの文字として表示される

SQL インジェクションと並べると分かりやすいよ。入るときの穴が SQL インジェクション、出るときの穴が XSS

// 危ないel.innerHTML = comment// 入った文字が動く<img src=x onerror="...">// 文字として置くel.textContent = comment

05 / 12

もう2つの「入力を信じた」穴

クロスサイトリクエストフォージェリ(CSRF)は、ログイン済みの人に代わりに押させる攻撃だよ。

罠のページを見せると、そこから勝手に本物のサイトへリクエストが飛ぶ。ブラウザは Cookie を自動でつけて送るので、サーバから見ると本人が操作したように見えてしまう。退会や送金をさせられるのがこれ。防ぐには、その画面で発行した合言葉(トークン)が付いているかを確かめる。

XSS との違いはどこで何が動くかだよ。XSS は訪問者のブラウザでスクリプトが動く。CSRF はスクリプトが要らなくて、別のサイトから、訪問者が意図しない操作をさせる

もうひとつが ディレクトリトラバーサル。ファイル名を外から受け取る作りにしていると、../ を並べて公開するつもりのない場所のファイルを読まれる。パス名を組み立てる材料を外から受け取ってはいけない、という話だよ。

GET /file?name=report.pdf     ↓ 書きかえるGET /file?name=    ../../etc/passwd

06 / 12

量で潰す ― DoS と DDoS

コードに穴がなくても止められる攻撃があるよ。大量の通信を送りつけて、サービスを提供できない状態にするのが DoS 攻撃(サービス不能攻撃)だよ。

1台から送っているうちは、その相手からの通信を止めれば済む。そこで攻撃者は、あちこちの機械を乗っ取って一斉に送らせる。これが DDoS 攻撃(分散型)。送り元がばらばらなので、遮断する相手を絞れないのが厄介なところ。

このとき使われる、乗っ取られて攻撃に加担させられる機械のことを 踏み台 と呼ぶ。攻撃されている側から見ると、加害者に見えるのは踏み台の持ち主だよ。

ここが後で出てくるボットの話につながる。DDoS の弾になる機械の群れは、たいてい乗っ取られたままの一般の PC なんだ。

DoS  1台 → 標的DDoS 大量の踏み台 → 標的     攻撃者       ↓ 指令  ボット ボット ボット       ↓ 大量の通信      標的サーバ

07 / 12

パスワードを破る4つの手口

名前が似ていて取りちがえやすいので、何を固定して、何を動かすかで並べて覚えよう。

  • 辞書攻撃 … 利用者 ID をひとつ決めて、辞書に載っている単語を試す
  • ブルートフォース攻撃(総当たり攻撃) … 利用者 ID をひとつ決めて、文字の組合せを片端から試す
  • リバースブルートフォース攻撃 … 逆向き。パスワードをひとつ決めて、ID を総当たりする
  • パスワードリスト攻撃別のサイトから流出した ID とパスワードの一覧で、そのままログインを試す

この4つめが、いま現実にいちばん通ってしまう手口だよ。使い回している人がいることだけを頼りにしているので、パスワードがどれだけ長くても関係ない。長さや複雑さで防げるのは前の3つだけ。

前の3つは、何回も間違えたら止める(ログインの回数制限)ことで効かなくできる。パスワードリスト攻撃はそこも抜けてくるので、使い回さないこと自体が対策になる。

辞書攻撃  ID 固定 × 辞書の単語ブルートフォース  ID 固定 × 全文字列リバースブルートフォース  PW 固定 × ID 総当たりパスワードリスト攻撃  流出した ID と PW の組

08 / 12

人をだます ― フィッシングと標的型攻撃

ここからはコードに穴がなくても通る手口だよ。

フィッシング は、本物そっくりの偽サイトを用意して、メールなどでそこへ誘い、自分でパスワードを入力させる。攻撃者は何も破っていない。入力してもらっているだけだよ。

標的型攻撃 は、無差別にばらまくのをやめて、特定の組織を狙って作り込むやり方。ここが効くところで、「取引先からの請求書」「人事からの連絡」のように、受け取った人の業務に関係がありそうな件名と本文にしてくる。いかにも怪しい迷惑メールを警戒する感覚では引っかかってしまう。

こうした技術ではなく人の心理や不注意を突く手口をまとめて ソーシャルエンジニアリング と呼ぶよ。管理者を装って電話でパスワードを聞き出す、肩越しに画面をのぞく(ショルダハッキング)、捨てた書類を拾う、といったものも全部これ。

見分け方はかんたんで、装置ではなく人が突かれているかだよ。総当たりツールやバッファオーバフローは、人ではなく機械を突いているのでソーシャルエンジニアリングではない。

09 / 12

通信の間に割り込む ― 中間者攻撃

中間者攻撃(Man-in-the-middle)は、通信している2人のあいだに座る攻撃だよ。

両側からはふつうに相手とやり取りできているように見える。実際には、いったん攻撃者に届いてから相手へ渡されている。だから中身を読めるし、書きかえられる

盗聴だけなら暗号化で防げるけれど、この攻撃が怖いのは片方になりすまして鍵をやり取りしてしまうところ。だからこそ「相手が本物か」を確かめる仕組みが要る。そこは次のレッスンの話だよ。

手前で使われる手口もひとつ知っておこう。DNS キャッシュポイズニング は、名前を引く先にでたらめな対応を覚えこませて、偽のサーバへ誘導する。アドレス欄の名前は正しいのに、着く先だけが違うので気づきにくい。

本来  あなた ── サーバ中間者攻撃  あなた ─ 攻撃者 ─ サーバ

10 / 12

マルウェアの見分け方

悪いことをするソフトウェアをまとめて マルウェア と呼ぶ。試験ではどう増えるか・何をするかで聞かれるので、そこで分けて覚えよう。

  • ウイルス … ほかのプログラムやファイルに寄生して増える。宿主が要る
  • ワーム … 宿主が要らず、単独で自分の複製を作ってネットワーク越しに広がる
  • トロイの木馬 … 増えない。役に立つソフトのふりをして単独のプログラムとして潜み、条件がそろうまで待つ
  • ボット … 乗っ取ったあと、外からの命令を待って動く。DDoS の弾にされる
  • ランサムウェア … ファイルを勝手に暗号化して、戻す代わりに金を要求する
  • スパイウェア … 気づかれないまま居座って、個人情報や操作の履歴を集めて送り出す

ボットに指令を出す側のサーバを C&C サーバ(コマンド&コントロール)と呼ぶよ。乗っ取られた大量の機械と C&C サーバをまとめて ボットネット。攻撃者は自分の手を動かさず、C&C サーバから「あそこを攻撃せよ」「情報を集めて送れ」と指示するだけになる。

迷ったら自分で広がるかどうかで切ろう。自分で広がるのがワーム、待っているのがトロイの木馬とボットだよ。

ウイルス  宿主に寄生して増えるワーム  単独で自ら感染を広げるトロイの木馬  正体を隠して潜むボット  外からの命令で動くランサムウェア  暗号化して金を要求するスパイウェア  情報をこっそり送り出す

11 / 12

境界で止める ― ファイアウォールと DMZ

穴を全部ふさげたと言い切れることはないので、入る前に止める仕組みも置く。その境目に立つのが ファイアウォール だよ。

いちばん基本の動きが パケットフィルタリング。1つずつのパケットについて、送信元・宛先のアドレスとポート番号を見て、通すか捨てるかを決める。決めごとの一覧(ルール)を上から順に当てて、当たったところで打ち切る作りが多いよ。

ここで問題になるのが、外に見せたいサーバの置き場所。Web サーバは外から来てもらわないと意味がないけれど、そこに顧客データの入ったデータベースまで置いたら、Web サーバが破られた時点で全部持っていかれる。

そこで境界にもう1つ部屋を作る。外からも中からも届くけれど、そこから中へは限られた通信だけ、という中間の区画が DMZ だよ。

外から見せるものを DMZ に、守りたいデータを内部に置く。これがこの仕組みの答えで、そのまま試験の正解になる。

インターネットファイアウォール   ├── DMZ   │    Web サーバ   └── 内部セグメント        DB サーバ

12 / 12

中身を見て止める ― IDS・IPS・WAF

パケットフィルタリングが見ているのは宛先と番号だけ。中身は見ていないので、80番で正しく届く形をしていれば通ってしまう。だから中身を見る道具を足すよ。

  • IDS(侵入検知システム) … 怪しい通信や挙動を見つけて知らせる。止めはしない
  • IPS(侵入防止システム) … 見つけたうえでその場で止める
  • WAF(Web Application Firewall) … HTTP のやり取りの中身まで見て、Web アプリの脆弱性を突く攻撃を遮断する

WAF の持ち場をはっきりさせておこう。アプリの脆弱性への攻撃を、手前で遮断するもの。だから SQL インジェクションのような入力による攻撃を止められる。逆に、脆弱性を見つけて直すことも、OS にパッチを当てることも、開発中の不具合を検知することも WAF の仕事ではない。ここが選択肢で必ず混ぜられる。

本筋の対策はやはり脆弱性そのものを減らすことだよ。OS やライブラリの修正パッチを当て続ける、入力値を検証する、そして ペネトレーションテスト(実際に攻撃して侵入できるか試す)で穴の残りを確かめる。手前で止める道具は、直すまでの時間を稼ぐためのものだよ。

パケットフィルタリング  アドレスとポートを見るIDS  怪しい通信を見つけるIPS  見つけたら止めるWAF  HTTP の中身まで見て止める