SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

OWASPでビルトイン・セキュリティ

SQLインジェクション対策の極意はSQL文を組み立てないことにあり

OWASPでビルトイン・セキュリティ 第4回


脆弱性の確認

 ここまでは正常系のお話です。郵便番号と国別コードを外部から指定できる場合、このプログラムにはSQLインジェクション脆弱性があります。攻撃例を紹介しましょう。郵便番号に1を指定したうえで、国別コードに以下を指定します。

jp WHERE 1 <> ? UNION SELECT CONCAT(cardname, ':', cardnumber, ':', expire, ':', secret) FROM ecsite.cardinfo --

 ストアドプロシージャで生成されるSQL文は下記のとおりです。プレースホルダ「?」には値1を埋めています。

SELECT address FROM zip_jp WHERE 1 <> 1 UNION SELECT CONCAT(customer_id, ":", cardname, ":", cardnumber, ":", expire, ":", secret) FROM ecsite.cardinfo -- WHERE zipcode=?

 上記に出てくるUNIONは2つの問い合わせ結果を1つにまとめる演算です。1番目のSELECT文はWHERE句が 1 <> 1 すなわちFALSEなので1件もヒットしません。2番目のSELECT文は、カード情報を保持するecsite.cardinfoというテーブルから、カード登録名(cardname)、カード番号(cardnumber)、有効期限(expire)、セキュリティコード(secret)を連結したものを返します。この攻撃の結果として、以下が表示されます。

TARO YAMADA:1234567890123456:062017:543

 SQLインジェクション攻撃により、クレジットカード情報が漏洩しました。

ストアドプロシージャ内であってもSQL文を動的に組み立ててはいけない

 先のサンプルでストアドプロシージャを用いているのにSQLインジェクション脆弱性が混入してしまった理由は、SQL文を動的に組み立てているからです。そして、この例は、組み立てられたSQL文の文字列は、PREPARE文により準備されているので、「プリペアードステートメントを使っているがSQLインジェクション脆弱性がある」という例にもなっています。

 SQL文を動的に組み立てないためには、以下のような方法があります。

  • 国別のテーブルを1つのテーブルにまとめ、国を表す列を追加する
  • 国の数が少なければ、国毎のSQL文を用意し、切り替えるようにする

 これらの方法が取れない場合は、国名コードが英字2文字であることを確認して、違反している場合はエラーとして処理を停止するか無効な値(NULLなど)を返す方法(入力値検証)が考えられます。

 下記は、郵便番号を1つのテーブルzipに統合するという方針によるストアドプロシージャの修正例です。SQL呼び出し1つだけなので、もはやストアドプロシージャにする必要もないくらいですね。国名コードの型も従来のTEXT型から、VARCHARとして文字数も可能な限り制限しています。

CREATE PROCEDURE zip2address(IN zipcode VARCHAR(10), IN country VARCHAR(2))
BEGIN
  SELECT address FROM zip WHERE zip.country=country AND zip.zipcode=zipcode;
END

 この場合、先のJavaによるサンプルコードの実行結果は以下のようにエラーになります。

com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'country' at row 2

 「countryとしてデータが長すぎる」というエラーメッセージが表示されています。これは、countryの型をVARCHAR(2)に制限したことによる効果ですが、仮にTEXT型のままだった場合もSQLインジェクション攻撃は成功せず、空の結果が返るだけです。

次のページ
ストアドプロシージャの呼び出しでSQL文を動的に組み立てる場合

この記事は参考になりましたか?

OWASPでビルトイン・セキュリティ連載記事一覧

もっと読む

この記事の著者

徳丸 浩(OWASP Japan)(トクマル ヒロシ)

1985年京セラ株式会社入社、1995年、京セラコミュニケーションシステム株式会社(KCCS)転籍。携帯電話向けインフラ、プラットフォームの企画・開発を担当。Webアプリケーションのセキュリティ問題に直面し、研究、社内展開、寄稿などを開始する。2004年に、KCCS社内ベンチャーとしてWebアプリケ...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/9204 2016/02/04 21:21

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー