MENU

SQLインジェクション — 入力欄からデータベースを乗っ取る古典攻撃

SQLインジェクション アイキャッチ
SQLインジェクション

SQLインジェクションは、Webフォームやクエリ文字列に入力された文字列が、そのままサーバ側のSQL文に連結されてしまう実装の隙を突き、攻撃者が任意のSQL文をデータベースに実行させてしまう脆弱性です。1998年にハッカー雑誌Phrack誌54号の論考「NT Web Technology Vulnerabilities」(Rain Forest Puppy)でその手口が広く知られるようになりました。以後OWASP Top 10では2003年の初版から2021年版に至るまで一貫してインジェクションが上位に居続け、Webアプリケーション開発者なら避けて通れない最重要脆弱性であり続けています。

目次

この記事の目次

  1. クエリ文字列に細工を混ぜる
  2. Heartland・TalkTalk・大規模流出史
  3. プリペアド文と最小権限が基本
  4. コマンド・LDAP・XPathとの違い
  5. まとめ

クエリ文字列に細工を混ぜる

クエリ文字列に細工を混ぜる

古典的なSQLインジェクションの例は、ログインフォームのユーザー名欄に「' OR '1'='1」と入力するだけで認証を突破できてしまう、というものです。サーバ側で SELECT * FROM users WHERE name = '入力値' AND pass = '入力値' という形に文字列連結でSQL文を組み立てていると、入力に含まれる引用符でリテラルが閉じられ、後続の「OR '1'='1」によって条件式が常に真になり、全ユーザーが認証通過扱いとなります。極めて単純な仕掛けですが、現代でもCMSやレガシーシステムで発見が続く息の長い欠陥です。

実害はログイン回避にとどまりません。UNION SELECTを使ってテーブル一覧やパスワードハッシュを引き出す情報抽出型、条件分岐の真偽でレスポンス差を観測するブラインドSQLインジェクション、応答時間で結果を推定する時間ベース型、サーバ機能を悪用してファイル読み書きやOSコマンド実行に至る型まで、発展系は数多く存在します。WebアプリのDBコネクション権限が高すぎる環境では、結果としてDB自体やサーバ全体を奪われる事案も起きます。

Heartland・TalkTalk・大規模流出史

Heartland・TalkTalk・大規模流出史

SQLインジェクションは1998年のPhrack 54号で詳述されて以降、無数の事件を生んできました。象徴的な事件の一つが2008年に発生した米決済処理大手Heartland Payment Systemsの大規模流出で、アルバート・ゴンザレス被告らがSQLインジェクションを突破口にネットワーク内部へ侵入し、1億3千万件のクレジットカード番号が流出した、と米司法省の起訴状にも記されています。クレジット業界の事件として歴代有数の規模で、PCI DSS強化への大きな契機となりました。

英国では2015年、通信事業者TalkTalkで約16万件の顧客情報が流出する事件があり、後の刑事手続きにより、犯人はSQLインジェクションを使って侵入していたことが明らかになりました。他にも2011年のソニー・ピクチャーズ事件、2012年のヤフー・ボイス事件、2014年のジョーミラー氏事件など、いずれもSQLインジェクションが起点とされています。OWASP Top 10の2021年版でも「インジェクション」はA03として高順位を保持しており、古典攻撃でありながら現役の脅威であることがうかがえます。

プリペアド文と最小権限が基本

プリペアド文と最小権限が基本

SQLインジェクション対策の王道は「文字列連結でSQL文を組み立てない」ことに尽きます。プリペアドステートメント(パラメータ化クエリ)を使えば、入力値はSQLの文法構造とは別経路で渡されるため、どんな文字を入れられても構文を破壊できません。PHPのPDO、JavaのPreparedStatement、Pythonの各DB-API、Node.jsのmysql2やpgなど主要ライブラリには標準で備わっており、Hibernate・SQLAlchemy・Active RecordなどのORMも通常の使い方をしていれば内部でパラメータ化を行います。

アプリケーション層の防御に加え、DBユーザーの権限を最小化する設計も欠かせません。「Webアプリ用のDBユーザーには参照系と限定的なINSERTだけを許可する」のように分けておけば、万一インジェクションが成立してもDROP TABLEや管理テーブル参照は防げます。エラー応答に内部SQL文をそのまま出さない、ログには詳細を残しつつ画面には抽象的なメッセージを返す、WAFで既知の攻撃パターンを抑え込む、といった多層防御を重ねることで、古典攻撃でありながら現代でも消えない脅威に十分対抗できます。

コマンド・LDAP・XPathとの違い

コマンド・LDAP・XPathとの違い

SQLインジェクションは「入力をSQL文に混ぜ込む」攻撃ですが、同じ「インジェクション」の語は他のクエリ言語や処理系にも適用されます。OSコマンドインジェクションは、シェル経由で外部コマンドを実行している処理に細工した入力を渡し、; や | を起点に別コマンドを連結させてサーバ全体を奪取する攻撃です。影響範囲が一気に拡大するためSQLi以上に致命的になりがちで、対策はexecvや配列引数APIの利用、そもそもシェルを介さない設計が王道です。

LDAPインジェクションは認証ディレクトリへのクエリ、XPathインジェクションはXMLデータベースへのクエリ、テンプレートインジェクションはJinja2やFreemarkerなどのテンプレート評価器を狙うものです。いずれも「ユーザー入力を構文の一部に直結させない」「DSLごとに用意された安全なバインド機構を使う」という基本原則は同じで、SQLインジェクション対策の発想がそのまま応用できます。「文字列連結が悪、構造化APIが正」というメンタルモデルを持つことが、家族全員に対する共通解になります。

まとめ

SQLインジェクションはWeb開発の歴史と並ぶ古さを持ちながら、なお現役で被害を生み出す厄介な脆弱性です。プリペアドステートメントの徹底、DBユーザーの最小権限、エラーメッセージの抽象化、WAFによる多層化を組み合わせれば、四半世紀以上前の手口に大規模流出を許す事態は確実に防げます。「文字列連結でSQLを組み立てない」という一行のルールが最大の防壁です。

※本記事はIT用語辞典の手書きドラフトです。公開前に最新情報・出典を確認のうえ加筆修正してください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

目次