PostgreSQL 행 단위 보안(RLS)으로 만드는 LMS — 웹 서버가 뚫려도 회원 DB 전체가 새지 않는 이유
레거시 PHP LMS는 웹 서버가 DB 전체 권한을 가진 계정으로 접속하는 경우가 많아, 웹셸 하나로 회원 DB 전체가 덤프됩니다. PostgreSQL RLS와 최소 권한 설계로 피해 범위를 줄이는 WEBHEADS의 데이터 접근 구조를 설명합니다.
한 줄 요약: 웹셸 사고가 대형 유출로 커지는 이유는 웹 서버가 'DB 전체를 읽을 수 있는 계정'을 쓰기 때문입니다. WEBHEADS(웹헤즈) LMS는 PostgreSQL의 행 단위 보안(Row Level Security, RLS)을 사용해, 요청한 사용자가 볼 수 있는 행만 DB가 직접 돌려주도록 설계했습니다.
레거시 구조의 문제: 전통적인 PHP 솔루션은 config.php 같은 파일에 DB 접속 아이디와 비밀번호를 평문으로 적어 두고, 그 계정 하나로 모든 쿼리를 실행합니다. 권한 확인은 PHP 코드 안의 if 문이 맡습니다. 이 구조에서는 웹셸로 설정 파일 하나만 읽으면, 공격자가 같은 계정으로 DB에 직접 접속해 회원·결제·수강 테이블을 통째로 내려받을 수 있습니다. 애플리케이션 코드의 권한 검사는 공격자가 그 코드를 거치지 않는 순간 의미가 없어집니다.
RLS가 바꾸는 것: RLS는 권한 검사를 애플리케이션이 아니라 DB 엔진에 둡니다. 예를 들어 수강 기록 테이블에 'user_id가 현재 로그인한 사용자와 같은 행만 조회 가능'이라는 정책을 걸면, 어떤 경로로 쿼리가 들어오든 DB가 다른 사람의 행을 돌려주지 않습니다. 관리자 여부는 사용자가 수정할 수 없는 별도 권한 테이블과 보안 함수로 확인하며, 사용자 프로필에 적힌 값으로 권한을 판단하지 않습니다.
최소 권한과 비밀 정보 분리: 브라우저에 내려가는 키는 공개용 키뿐이고, 이 키로는 RLS 정책이 허용한 범위만 접근할 수 있습니다. 결제 연동, 메일 발송처럼 높은 권한이 필요한 작업은 서버 함수 안에서만 실행되고, 그 비밀 키는 코드 저장소나 화면 파일에 들어가지 않습니다. 결과적으로 화면 코드가 전부 공개되어도 DB 전체에 접근할 수 있는 정보는 드러나지 않습니다.
고객사별 분리와 함께 쓸 때: WEBHEADS는 구축형 고객사마다 독립 서버·독립 DB를 제공하고, 그 안에서 다시 RLS로 사용자별 접근을 나눕니다. 고객사 사이에는 물리적 분리, 고객사 안에서는 행 단위 분리를 적용하는 이중 구조입니다. 한 고객사의 문제가 다른 고객사로 번지지 않고, 한 계정의 문제가 전체 회원으로 번지지 않도록 하는 것이 목표입니다.
보안 담당자가 확인할 수 있는 증거: RLS는 '말'이 아니라 정책 정의로 확인할 수 있습니다. WEBHEADS는 요청 시 테이블별 RLS 적용 여부, 정책 목록, 관리자 권한 판별 방식, 개인정보 열람 로그 구조를 문서로 제공합니다. 또 정책 누락을 찾는 자동 점검을 정기적으로 돌려, RLS가 꺼진 테이블이나 지나치게 넓은 정책이 생기면 바로 수정합니다.
자주 묻는 질문 — RLS를 쓰면 속도가 느려지지 않나요? 정책 조건에 맞는 인덱스를 함께 설계하면 체감할 만한 차이는 거의 없습니다. 오히려 권한 검사가 DB 한곳에 모여 있어 코드마다 조건을 반복하다 생기는 누락을 줄일 수 있습니다. 데이터 보호 기준 전체는 보안 센터 페이지에서 확인하실 수 있습니다.
관련 글
주식회사 웹헤즈 · 대표전화 02-540-4337 · 도입 문의