CodeGym /コース /SQL SELF /セキュリティ設定でよくあるミスとその防止方法

セキュリティ設定でよくあるミスとその防止方法

SQL SELF
レベル 48 , レッスン 4
使用可能

「データベースのセキュリティは、いいパスワードみたいなもんだよ。どんなに複雑なキーを作っても、それを付箋に書いてモニターに貼ってたら意味ないよね。」だから、僕らの目標は、セキュリティ機能をちゃんと設定するだけじゃなくて、よくあるミスを避けること。そうしないと、全部の努力が水の泡になっちゃうからね。

1. 権限を与えすぎたロールの使用

開発者って、アクセス制限をかけるのが怖くて、つい広い権限を持つロールを作っちゃうことが多いんだ。例えば、SUPERUSERALL PRIVILEGESを付与しちゃう。「まあ、必要になるかもしれないし!」って感じ。でも、権限を与えすぎると、セキュリティの大穴になるよ。

権限を与えすぎた例:

GRANT ALL PRIVILEGES ON DATABASE university TO student_role;

この場合、student_roleはデータベースの全データにフルアクセスできちゃう。本当はデータの読み取りだけでよかったのに、テーブルの削除や構造変更、管理者のアクセスまで奪えちゃう。

どうやって防ぐ?

最小限の権限だけを持つロールを作ろう。これを「最小権限の原則」って言うんだ。例えば、読み取り専用ロールはこんな感じ:
GRANT CONNECT ON DATABASE university TO student_role;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO student_role;

このやり方なら、student_roleができることが明確になる。つまり、DBに接続して読み取りだけ。

2. 機密データの暗号化がない

例えばusersテーブルで、パスワードを平文で保存してるとしよう:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username TEXT NOT NULL,
    password TEXT NOT NULL
);

もし悪意のある人がこのテーブルにアクセスできたら、全ユーザーのパスワードがバレちゃう。これは、家の鍵を玄関マットの下に置いてるのと同じだよ。

これを防ぐには、 パスワードをpgcryptoで暗号化しよう。例えば:

CREATE EXTENSION IF NOT EXISTS pgcrypto;

INSERT INTO users (username, password)
VALUES ('johndoe', pgp_sym_encrypt('secure_password', 'encryption_key'));

パスワードの確認には復号化を使う:

SELECT username
FROM users
WHERE pgp_sym_decrypt(password::BYTEA, 'encryption_key') = 'secure_password';

機密情報を平文で保存しちゃダメ、絶対!

3. SQLインジェクションを無視する

SQLインジェクションは、今でも超よくある攻撃手法だよ。その理由は、開発者がまだ文字列連結でクエリを作っちゃうから。例えば:

DO $$
DECLARE
    username TEXT := 'John';
    query TEXT;
BEGIN
    query := 'SELECT * FROM users WHERE username = ''' || username || ''';';
    EXECUTE query;
END $$;

もし悪意のある人がユーザー名の代わりにJohn' OR '1'='1を送ったら、usersテーブルの全データが漏れちゃう。

どうやって防ぐ? パラメータ化クエリを使おう:

PREPARE user_query (TEXT) AS
SELECT * FROM users WHERE username = $1;

EXECUTE user_query('John');

こうすれば、変数が安全に渡されて、インジェクションの心配なし!

4. pg_hba.confの設定ミス

pg_hba.confは、IPアドレスごとのアクセス制御のメインツール。設定ミスすると、必要以上に広いアクセスを許しちゃう。

悪い設定例:

host    all     all     0.0.0.0/0       trust

この一行で、誰でもどのDBにも、どのIPからでもパスワードなしで接続できちゃう。

どうやって防ぐ? 特定のIPだけにアクセスを許可して、認証方式はmd5scram-sha-256を使おう:

host    university    student_role    192.168.1.0/24    md5

これなら、student_roleはローカルネットワークからパスワード付きでしかアクセスできない。

pg_hba.confを変更したら、忘れずにこのコマンドで反映しよう:

pg_ctl reload

5. ROW LEVEL SECURITYの誤用

RLSは強力だけど、設定ミスや有効化忘れだと意味ない。例えば、アクセス制御ポリシーを書いても、RLSがオフだと効かない:

CREATE POLICY my_policy ON users
USING (username = current_user);

-- でもRLSが有効じゃない!
SELECT * FROM users; -- 全行見えちゃう!

どうやって防ぐ? RLSを有効にするのを忘れずに:

ALTER TABLE users ENABLE ROW LEVEL SECURITY;

そして、ポリシーがちゃんと効いてるか確認しよう:

SET ROLE student_role;

SELECT * FROM users; -- ポリシーに合う行だけ見える。

6. 管理者の操作を考慮しない

たまにDB管理者が全データにフルアクセスできるけど、実は業務にそこまで必要ないことも。管理者アカウントが乗っ取られたら、リスクが増えるだけ。

どうやって防ぐ? ロールを分けて使おう。管理作業用にはデータアクセス権なしのロールを作る:

CREATE ROLE admin_role WITH LOGIN CREATEDB CREATEROLE;

データアクセス用には、最小権限の別ロールを作る:

CREATE ROLE data_analyst_role;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO data_analyst_role;

ユーザーの役割に応じてロールを割り当てよう:

GRANT admin_role TO some_user;
GRANT data_analyst_role TO another_user;

7. ログが足りない

ログをちゃんと設定しないと、怪しい動きに気づいた時にはもう手遅れってことも。

ログがない例:

-- postgresql.confに何も設定なし
log_statement = 'none';

どうやって防ぐ? 最低限のログは有効にしよう:

log_statement = 'all'
log_connections = on
log_disconnections = on

これで、全クエリ・接続・切断が見えるようになるよ。

もっと細かく監査したいなら、pgAudit拡張を使うのもアリ:

CREATE EXTENSION pgaudit;

8. 古い認証方式の使用

passwordみたいな古い認証方式は、もう十分なセキュリティじゃないよ。

どうやって防ぐ? もっと安全なscram-sha-256に切り替えよう:

ALTER SYSTEM SET password_encryption = 'scram-sha-256';

そして、ユーザーのパスワードも更新しよう:

ALTER USER student_role WITH PASSWORD 'new_secure_password';

こういう問題は小さく見えるかもしれないけど、どれも大きなセキュリティホールになる可能性があるよ。君の仕事は、DBに接続しようとする全ユーザーを「ちょっと怪しいかも?」って思って運用すること。いわゆる「信じるけど、ちゃんと確認する」ってやつ。これで、セキュリティ設定だけじゃなく、よくあるミスも防げるはず!幸運をつかんで、データをしっかり守ろう!

1
アンケート/クイズ
データ暗号化入門、レベル 48、レッスン 4
使用不可
データ暗号化入門
データ暗号化入門
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION