情報処理安全確保支援士 2016年 春期 午前2 問21
問題文
“アカウント”表に対して、SQL文を実行したとき、“アカウント”表の全ての行が取得される入力パラメタはどれか。ここで、入力パラメタのエスケープ処理は行わない。また、“;” は SQL文の終端として解釈されるものとする。

選択肢
ア:' OR '--' = '--(正解)
イ:' OR ユーザ名 = 'ユーザ名
ウ:'-- OR 1 = 1
エ:¥' OR 1 = 1 ' ;--
🔒 解説は解答すると表示されます
SQLインジェクション【午前2解説】
正解の理由
ア の入力を元のSQL文中の
'入力パラメタ' にそのまま代入すると、WHERE節は次のように展開されます。WHERE ユーザ名 = '' OR '--' = '--';
ここで
'--' = '--' は文字列比較で同じ文字列を比較しているため常に真(TRUE)になります。WHERE句が「何か OR TRUE」となれば行はすべて選ばれるため、全行が取得されます。重要なのは '--' がクォートで囲まれているため、コメント記号として扱われず文字列リテラルとして評価される点です。よってこの入力で確実に全行取得が実現します。解法ステップ
- 元のSQLの構造を確認する(パラメタはシングルクォートで囲まれている)。
- 各選択肢をそのまま代入してSQLがどのように展開されるかを文字列として書き出す。
- 展開後のWHERE条件が論理的に常に真になるかを判定する(例:恒真式 OR TRUE)。
- コメント記号(--)が文字列リテラル内か外かを区別し、コメント化されるかどうか確認する。
選択肢別の誤答解説
-
ア
展開例:WHERE ユーザ名 = '' OR '--' = '--';
解説: 最初の'で元のリテラルが閉じられ、その後OR '--' = '--'が有効な論理式になる。'--'はクォート内の文字列なのでコメント扱いにならず、比較は TRUE になるため全行取得。 -
イ
展開例:WHERE ユーザ名 = '' OR ユーザ名 = 'ユーザ名';
解説: この式は「ユーザ名が空文字」または「ユーザ名が文字列'ユーザ名'である」場合に真となる。一般的なデータでは全行が必ず真になるとは限らないため、全行取得は保証されない。 -
ウ
展開例(読み取り方による):- 入力が先頭にクォートを含む場合、
WHERE ユーザ名 = ''-- OR 1 = 1';のようにクォート不整合や文字列リテラル内の--になるためコメント化されない。 - コメント化させたい場合は
--がクォート外に出ていなければならない。提示の形式では正しくクォートを閉じつつ--をコメント化する構造になっていないため、期待する「コメントで残りを無視して OR 1=1 を有効化」が成立しない。結果として安全でもしくは構文エラーになる可能性が高い。
- 入力が先頭にクォートを含む場合、
-
エ
展開例(例示):WHERE ユーザ名 = '¥' OR 1 = 1 ' ;--';(表記が不揃いでDB依存)
解説:¥(円マーク)や不揃いなクォート、末尾の;--を混在させたこの入力は、多くの場合クォートの不整合や構文エラーを引き起こす。さらに;はSQL文の終端とされるため、その扱いはDBや実行環境に依存する(追加文が分離される等)。したがって確実に全行を返すとは言えない。
よくある誤解
- コメント記号
--は見えれば常にコメントになる
→ 誤り。--がコメントとして機能するのはクォート(文字列リテラル)の外側にある場合のみ。クォート内は単なる文字列であり、コメントにはならない。 - セミコロン
;を入力すれば必ず追加入力でSQLを分割できる
→ 環境依存。多くのSQL実行環境やAPIでは複数ステートメントを許可しない設定がある。さらに問題文で「;は SQL文の終端として解釈される」とある場合はそもそもそれ以降は別文扱いになり、狙いが変わる。 - 単に
OR 1=1を入れれば必ず全件取得できる
→ 重要なのはそのOR 1=1をSQLの式として実行させるために、まず外側のクォートを適切に閉じること。クォートを閉じられなければ文字列扱いになり効果がない。
補足コラム
攻撃側が最も簡単に利用する方法は「既存のクォートを閉じる → 恒真条件を入れる → 残りをコメント化して構文を整える」というパターン(例:
' OR 1=1 --)。ただし、この手法は次の防御で防げます。- プレースホルダやプリペアドステートメントを使ってパラメタ化する(推奨)。これにより入力は常に値として扱われ、クォートの破壊が起きない。
- 入力のエスケープ(SQLエンジン依存だが、単独エスケープはミスを生みやすい)。
- 最小権限のDBユーザ運用や複数ステートメントの禁止設定。
簡単な安全化例(疑似コード、Python DB-API風):
# 悪い例(文字列連結、脆弱)
sql = "SELECT ID, ユーザ名, メールアドレス FROM アカウント WHERE ユーザ名 = '" + user_input + "';"
# 良い例(パラメタ化)
cur.execute("SELECT ID, ユーザ名, メールアドレス FROM アカウント WHERE ユーザ名 = %s;", (user_input,))
FAQ
Q: '--' が文字列とコメントのどちらになるかはどう判断する?
A: SQLパーサは字句解析でクォートの開始・終了を認識します。
A: SQLパーサは字句解析でクォートの開始・終了を認識します。
' で囲まれた部分は文字列リテラル扱いとなり、その内部にある -- は文字列データです。-- がコメントになるのはクォートの外側にある場合だけです。Q: この問題のようにエスケープ処理をしていない場合の最善の防御は?
A: パラメタ化(プリペアドステートメント)を最優先で導入すること。加えて権限の最小化や入力検証も行う。
A: パラメタ化(プリペアドステートメント)を最優先で導入すること。加えて権限の最小化や入力検証も行う。
Q: DBによってコメントの仕様は違う?
A: 基本的な
A: 基本的な
--(行コメント)や /* ... */(ブロックコメント)は広く使われますが、細かい扱い(例えば -- 後にスペースが必要かどうか)は実装依存のことがあるため、攻撃や防御の検討では対象DBの仕様を確認する必要があります。関連キーワード: SQLインジェクション、クォート閉じ、コメント記号、パラメータ化、文字列リテラル、エスケープ処理

\ せっかくなら /
情報処理安全確保支援士を
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

