エンジニアが今いちばん知りたいことに答えるイベント「MANABIYA -teratail Developer Days-」レポート

#3 teratailのQ&Aから学ぶWebセキュリティの現状

この記事を読むのに必要な時間:およそ 3 分

正しいSQLインジェクション対策とそのロジック

ここから話を発展させて,SQLインジェクション対策についての解説となりました。

SQL文の動的な組み立て方には「文字列連携」「プレースホルダ」の2種類があり,プレースホルダのほうが安全です。ではなぜ安全なのか? 静的プレースホルダ(プリペアードステートメント)は,値が入らない状態でデータベースに送り,コンパイルされた後から値を入れて実行されます。2回目も同じSQL文で値だけ違う場合は,値だけをセットし直して実行されます。なので,値が入らない状態でコンパイルされているため,値の操作でSQLの意味を変えることは原理的にできなくなります。

画像

(出展:安全なウェブサイトの作り方』⁠ p.10/独立行政法人 情報処理推進機構)

動的プレースホルダは,プログラムソースコード上ではほとんど同じなのですが,内部の動作が異なります,プログラムソース上で呼び出し側で完全な値が入ったSQLを作り,データベースに送りコンパイルして実行します。これはSQLインジェクションにならないのかというと,基本的にはならないです。なぜかというと,内部でSQLインジェクションにならないようライブラリを利用してエスケープ処理を行ってくれます。だから,ライブラリにバグがない限りは安全です。

画像

(出展:安全なウェブサイトの作り方』⁠ p.11/独立行政法人 情報処理推進機構)

静的プレースホルダは動的プレースホルダよりやや安全です。ですが,ここはメリット・デメリットで選ぶ必要があります。簡単にまとめると,以下のようになります。

  • 文字列連結による組み立ては,アプリケーションの開発者の無知や不注意によりSQLインジェクションの可能性がある
  • 動的プレースホルダはライブラリのバグによりSQLインジェクションの可能性がある
  • 静的プレースホルダは原理的にSQLインジェクションの可能性がない

ということなので,パフォーマンスか,完全なSQLインジェクション対策をか天秤にかけて,正しく選択する必要がありそうですね。

PHPのコマンドインジェクション対策について

画像

「htmlspecialchars()やintval()を使っておけば対策されると思ってい良いのでしょうか?」という質問ですが,徳丸さんの答えは「htmlspecialcharsはコマンドインジェクションとは関係ない」です。

コマンドインジェクション対策には,以下のようなものがあります。

  • そもそも外部呼び出しを避ける
  • 外部由来のデータをsystem関数に指定しない
  • 可能であれば,シェルを介在しないコマンド実行を用いる
  • system関数等の引数を安全な関数を用いてエスケープ処理をする

たとえば,PHPの外コマンド呼び出しには以下の2種類があります。

  • escapeshellarg:使用可能
  • escapeshellcmd:使用禁止

このescapeshellcmdが使用禁止になっている理由の解説もありました。シングルクオート(')がペアでなければエスケープするというものもあるため,ペアができているとエスケープされずにパラメータの追加が可能になることもあるらしいです。

ユーザが入力した文字列をmailコマンドで安全に送信したい

画像

ユーザがフォームに入力した文字列を受け取り,

echo ${入力文字列} | mail -s 'タイトル' 宛先@mail

のようにmailコマンドで送信したい,という質問です。escapeshellargを利用することによって,上記のコマンドは安全性を高めることができるようですが,teratailでは別の回答者の方が「popenを使いましょう」と答えています。では,なぜpopenが安全なのでしょうか。

質問にある脆弱なサンプルはsystem関数の引数の中に外部変数があるため,外部変数をエスケープしなければいけません。安全なサンプルは,メール本文の流し込みはfwirteでpopenプロセスを開いて値を入れています。system関数の引数ではエスケープが必要ですが,friwteのときはエスケープ不要な個所にパラメータを代入するため,エスケープを書く必要はないというのが理由です。ともあれ,メールの送信はmail関数やmailライブラリを利用して行うほうが安全ですので,利用できる場合はそちらを利用するようにしましょうということでした。

Fizzbuzzの問題とコピペプログラマ

また,現状コピペで開発するユーザーが多くいる状態を,FizzBuzzの問題とともに解説されました。

多くのエンジニアがFizzbuzzをかけないと話題になりましたが,どうしてそんなことが起きるのでしょう?

信じがたいですが,最近ではコピペでアプリケーションを完成させるプログラマもいるようです。そういったコピペプログラマはパターンマッチで書いているので,パターンから外れると急にFizzbuzzが書けない人が多く居たりします。FizzBuzzは普段のプログラムとは少し外れているので,そういったプログラマが生まれるのでしょう。

ただ,コピペでやることが問題なのではなくて,そこから勉強をしていかないのが問題ですね。そういったプログラマに対しても,Q&A等でしっかりと救いの手を差し伸べてあげることによって,安全なインターネット社会は出来上がるのでしょう。

teratail Q&Aではどうなのか?

セキュリティ系の回答者のレベルは高いように感じます。一方,質問者はセキュリティについての不安はあるがどうするのかわからない方や,残念ながらエスケープの種類が間違っている場合が多いように感じます。少しでも正しい情報を上げることによって,より安全に貢献していくと考えています。

終わりに

徳丸さんは,最後にこうまとめられていました。

  • セキュリティで「こうすれば安全」という方法はないので,個別に覚えていくのが結局は早道になる
    ― ただし「これだけは危険」という方法を覚えておき,避ける必要がある
  • 『体系的に学ぶ安全なWebアプリケーションの作り方』を読もう

『体系的に学ぶ安全なWebアプリケーションの作り方』は,現在第二版を執筆中とのこと。待てる方は少し待って第二版を買ってみましょう。第一版でも読むとよりセキュリティ対策について学べるでしょう。

著者プロフィール

上田直樹(うえだなおき)

レバレジーズ株式会社 teratail開発エンジニア

メディアグロースのために企画,フロントエンド,バックエンドの開発までを担当。趣味は野球観戦。主にセ・リーグのTwitterを分析基盤に放り込んでニヤニヤする。

コメント

コメントの記入