皆さんこんばんは!
プロジェクトがデスマーチで毎日の帰りが24時過ぎ!ポンコツエンジニアのGONです。
今日も帰りににわか雨に遭遇して散々な目に会いました。
プロジェクトに鎮火の雨は降らないのになんなんでしょうか。
前回までに人生賭けた求人サービスを構築するために『PHP』『postgreSQL』『AWS』を選んだ理由や、
サービス名の由来、求職者様向け&企業様向け機能のご紹介、面談の採用確率UP方法、
『PHP』『postgreSQL』『AWS』の実機練習用サイトをご紹介させていただき、
さらに『SQL』『PHP』『AWS』の基本的な操作方法について書かせていただきました。
今日はセキュリティに関するご説明第2弾!
『SQLインジェクション』について語らせていただきます。
インジェクションとは「注入する」という意味で、
『SQLインジェクション』とはその名のとおりWebアプリケーションの入力欄などに不正なSQL文を送り込み、
データベースを意図しない形で操作しようとする攻撃手法です。
運営側が意図しないSQLを外部から実行される事で、情報流出や不正アクセスにつながります。
さて、それでは『SQLインジェクション』についてご説明します。
例えば、プログラムが次のようにSQLを組み立てているとします。
const sql =
"SELECT * FROM users WHERE email = '" +
email +
"' AND password = '" +
password +
"'";
攻撃者がメールアドレス欄に次のような値を入力します。
' OR 1=1 --
すると、実際に実行されるSQLは次のようになります。
SELECT *
FROM users
WHERE email = '' OR 1=1 --'
AND password = '';
ここで、
OR 1=1 は常に真(TRUE)
-- はSQLのコメント開始を意味し、それ以降が無視されるため、
パスワード条件が実質的に無効になり、意図しない認証成功につながる可能性があります。
攻撃が成功する=好きなSQLを実行出来る、となると、例えば次のような被害が考えられます。
個人情報の閲覧(応募者情報、企業情報など)
データの改ざん(求人内容や応募状況の変更)
データの削除
管理者権限の不正取得
データベース構造の調査
恐ろしいですね。
ではどうすれば防げるのか
最も重要なのはパラメータ化クエリ(プレースホルダー)を使うことです。
await client.query(
"SELECT * FROM users WHERE email = $1",
[email]
);
こうする事で、入力値はSQLの命令として解釈されず、単なるデータとして扱われます。
のため、' OR 1=1 -- のような文字列が入力されても、SQLの構造を変更することはできません。
PostgreSQLでの対策の基本は以下になります。
・プレースホルダー($1, $2 など)を必ず使用する
・SQL文を文字列連結で組み立てない
・データベースユーザーには必要最小限の権限だけを付与する
・エラーメッセージにSQLやデータベースの詳細を表示しない
・入力値の形式チェック(メールアドレス、数値など)も併用する
『SQL』のセキュリティ基礎『SQLインジェクション』とその対策について説明させていただきましたが、いかがでしょうか。
システムを攻撃する側は、システムを保守する側よりもWebサービスやSQLの仕組みに精通していることが多く、
その知識をなぜか悪い方向に利用します。
このため、システムを保守する側は、ちょっとした対策を怠るだけでそこに付け込まれてしまい、大事故に繋がってしまうので、頭の片隅に置いておきましょう。
さて、偉そうに『SQLインジェクション』について語らせていただきましたが、SQLインジェクション対策も万全にしたサービスが以下です。(攻撃してみろのフリではないですよ。絶対に攻撃しないでください)
企業の方、エンジニアの方に使っていただけると嬉しいです。
▼求人マッチングサービス【ヴェテラン】
https://veteran-work.com/
「セキュリティ対策ならもっとあるだろ!」
など様々なご意見いただけますとモチベーションが上がるのでよろしくお願いいたします!
本日もお疲れ様でした。
明日も頑張りましょう。