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이 할 수 있는 게 딱 정해져: 데이터베이스 접속과 읽기만 가능!

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 $$;

만약 누군가 username에 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

이 줄은 누구나, 어떤 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. 관리자 행동을 간과하기

가끔 데이터베이스 관리자는 모든 데이터에 접근할 수 있는데, 실제 업무에 꼭 필요한 건 아닐 수도 있어. 만약 관리자 계정이 털리면 데이터 유출 위험이 커져.

어떻게 피할까? 롤을 분리해서 관리 작업만 하는 롤은 데이터 접근 권한을 빼고 만들어:

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';

이런 문제들이 사소해 보여도, 하나만 잘못해도 큰 보안 구멍이 될 수 있어. 데이터베이스를 운영할 땐, 접속하려는 모든 사용자를 잠재적 의심 대상으로 생각해야 해. "믿되, 검증하라"는 말 알지? 이제 넌 보안 설정뿐 아니라, 흔한 실수도 예방할 수 있는 무기를 가졌어. 행운을 잡고, 네 데이터는 꼭 지키자!

1
설문조사/퀴즈
데이터 암호화 소개, 레벨 48, 레슨 4
사용 불가능
데이터 암호화 소개
데이터 암호화 소개
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION