암호화 · Encryption
내용을 알아볼 수 없게 바꾸고, 올바른 키를 가진 사람이 다시 원문으로 복호화할 수 있게 하는 방식입니다.
보안 용어를 외우는 데서 끝내지 않고 “왜 필요한지, 무엇을 검사해야 하는지”까지 설명합니다. 로그인·API·파일·개인정보를 다룰 때 초보 개발자가 놓치기 쉬운 권한 규칙을 실제 개발 상황과 비슷한 예시로 살펴보세요.
누가 볼 수 있는지, 데이터가 변조되지 않았는지, 문제가 생겼을 때 복구할 수 있는지까지 함께 생각합니다.
내용을 알아볼 수 없게 바꾸고, 올바른 키를 가진 사람이 다시 원문으로 복호화할 수 있게 하는 방식입니다.
입력값을 일정한 길이의 값으로 바꾸는 방식입니다. 보통 원문 복원을 목적으로 하지 않으며 비밀번호 검증이나 파일 무결성 확인 등에 사용됩니다.
브라우저와 서버 사이 통신을 암호화해 중간에서 내용을 훔쳐보거나 바꾸기 어렵게 만드는 웹 통신 방식입니다.
비밀번호만 확인하지 않고 인증 앱, 문자, 보안키 같은 추가 수단을 한 번 더 확인하는 방식입니다.
인증은 “누구인가?”를 확인하고, 권한은 “그 사람이 지금 이 작업을 해도 되는가?”를 확인합니다. 실제 사고를 막으려면 두 검사가 모두 필요합니다.
“당신이 누구인지” 확인합니다. 로그인, 인증번호, 생체인증 등이 여기에 해당합니다.
예: 민수 계정으로 로그인에 성공했다 → 민수라는 사실은 확인됨.
“민수가 이 자료를 보고·고치고·지워도 되는지” 확인합니다.
예: 민수가 로그인했더라도 지영의 비공개 프로젝트를 볼 권한은 없을 수 있음.
온라인 문서함을 만들었다고 가정해봅시다. 사용자가 자신의 105번 문서를 열면 브라우저가 서버에 /api/documents/105 같은 요청을 보냅니다.
문제는 ③번을 빼먹었을 때 생깁니다. 106번 문서가 다른 사람 것인데도 서버가 “106번이 있네”만 확인하고 내용을 보내면, 데이터베이스를 직접 침입하지 않아도 정보가 노출될 수 있습니다.
팀 프로젝트 서비스에서 초대받은 사람에게는 자료를 읽을 권한만 주고, 소유자에게만 수정·삭제 권한을 줄 수 있습니다.
| 사용자 | 조회 | 수정 | 삭제 |
|---|---|---|---|
| 프로젝트 소유자 | 허용 | 허용 | 허용 |
| 읽기 전용 초대 사용자 | 허용 | 거부 | 거부 |
| 관계없는 사용자 | 거부 | 거부 | 거부 |
따라서 서버에서는 조회(Read), 수정(Update), 삭제(Delete) 각각에 대해 권한 검사를 해야 합니다.
로그인한 사용자의 상태를 일정 시간 유지하는 방식입니다. 세션이 있다고 해서 모든 기능 권한이 자동으로 생기는 것은 아닙니다.
로그인이나 기기 연결 뒤 요청자의 신원을 증명할 때 사용하는 값입니다. 토큰이 유효한지와 별개로 “이 자료에 접근할 권한”도 확인해야 합니다.
필요한 기능에 필요한 권한만 줍니다. 조회만 필요한 사용자에게 수정·삭제 권한까지 주지 않는 것이 대표적입니다.
자료의 OwnerId, WorkspaceId, TeamId 같은 범위가 현재 요청자의 범위와 맞는지 서버에서 확인하는 습관이 중요합니다.
API는 화면과 서버가 데이터를 주고받는 통로입니다. 문제는 API 자체보다, 서버가 요청자의 자격과 자료의 소유관계를 제대로 검사하지 않을 때 생깁니다.
내 예약이 /api/reservations/7301로 조회된다고 해봅시다. 누군가 7302를 요청했을 때 7302가 다른 사용자의 예약이라면 서버는 로그인 여부만 확인하고 응답하면 안 됩니다.
로그인했나? → 예 → 7302번 예약 전송
로그인했나? → 예 → 7302번 예약 소유자가 현재 사용자와 같은가? → 아니오 → 거부
이처럼 객체의 ID를 직접 바꿔 다른 사람 자료에 접근할 수 있는 유형을 흔히 IDOR라고 부르고, API 보안에서는 BOLA(Broken Object Level Authorization)라는 표현도 자주 사용합니다.
숫자 7301 대신 긴 UUID를 사용하면 추측하기는 어려워질 수 있습니다. 하지만 그 주소가 로그, 공유 링크, 브라우저 기록 등으로 알려졌을 때 권한 검사가 없다면 여전히 문제가 됩니다.
AI에게 “프로젝트 관리 기능을 만들어줘”라고만 하면 생성·조회·수정·삭제 기능은 구현해도 서비스가 의도한 권한 규칙까지 정확히 알 수는 없습니다. 권한은 서비스마다 다르기 때문입니다.
AI가 코드를 작성하더라도 이 규칙을 바탕으로 서버 권한 검사와 실패 테스트를 같이 요구하는 것이 좋습니다.
전문가처럼 공격 방법을 외울 필요는 없습니다. “어떤 검사가 빠졌을 때 생기는 문제인지”를 이해하면 개발 중 요구사항을 더 정확히 설명할 수 있습니다.
다른 자료의 ID를 넣었을 때 서버가 소유권·권한을 검사하지 않아 남의 자료를 조회·수정·삭제할 수 있는 접근통제 문제입니다.
예방 핵심요청마다 현재 사용자와 자료의 Owner/Workspace 범위를 서버에서 확인합니다.
사용자 입력 등에 악성 스크립트가 섞여 다른 사용자 브라우저에서 실행되는 문제입니다.
예방 핵심출력 인코딩, 안전한 DOM 처리, 입력값 검증과 CSP 등을 함께 고려합니다.
입력값이 SQL 명령의 일부처럼 해석되어 데이터베이스 명령이 의도와 다르게 바뀌는 문제입니다.
예방 핵심문자열로 SQL을 이어 붙이지 말고 파라미터화된 쿼리 등을 사용합니다.
로그인된 사용자의 브라우저를 이용해 사용자가 원하지 않은 요청을 보내게 만드는 문제입니다.
예방 핵심SameSite 쿠키, CSRF 토큰, 요청 출처 확인 등 서비스 구조에 맞는 방어를 적용합니다.
비밀번호나 인증 코드를 매우 많이 반복해서 시도하는 공격입니다.
예방 핵심Rate Limit, 잠금 정책, MFA, 이상 시도 탐지 등을 사용합니다.
진짜 서비스처럼 보이는 메시지나 화면으로 사용자를 속여 계정정보나 결제를 유도하는 방식입니다.
사용자 주의주소, 발신자, 로그인 화면을 확인하고 의심 링크에서 비밀번호를 입력하지 않습니다.
프론트 화면에 보이면 안 되는 값과 사용자가 올린 파일을 어떻게 다뤄야 하는지 설명합니다.
외부 서비스가 “허가된 프로그램의 요청인지” 구분할 때 사용하는 비밀값입니다. 공개 저장소나 프론트 JavaScript에 그대로 넣으면 안 되는 키가 많습니다.
API 키나 DB 접속정보처럼 소스코드에 직접 적고 싶지 않은 설정값을 별도로 관리할 때 자주 사용합니다.
사용자가 올린 파일은 이름이나 확장자만 믿지 말고 실제 형식, 크기, 허용 종류, 저장 위치를 검사해야 합니다.
주소만 알면 누구나 열 수 있는 파일이라면 개인정보 자료에는 적합하지 않을 수 있습니다. 접근 권한이 필요한 파일은 서버에서 권한 검사를 해야 합니다.
보안을 “기능 다 만든 다음에 추가하는 작업”으로 미루지 말고, 기능을 설계할 때부터 누가 무엇을 할 수 있는지 같이 적어두는 것이 좋습니다.
폼, URL, 파일명, API 요청 등 사용자가 보낸 값은 잘못되거나 조작될 수 있다고 생각하고 검사합니다.
조회·수정·삭제 요청마다 현재 사용자가 해당 자료에 접근할 권한이 있는지 확인합니다.
기능별로 소유자·편집자·읽기 전용·관리자가 무엇을 할 수 있는지 표로 적어두면 AI에게도 정확히 전달할 수 있습니다.
브라우저로 내려가는 JavaScript는 사용자가 확인할 수 있다고 생각해야 합니다.
정상 동작만 확인하지 말고 다른 사용자 ID, 만료 토큰, 권한 없는 수정·삭제 요청이 실제로 실패하는지도 확인합니다.
운영체제, 라이브러리, 서버 프로그램의 보안 업데이트를 미루지 않습니다.
백업이 있다는 사실만 믿지 말고 실제로 복구되는지 확인합니다.
테스트용 설정과 실제 사용자용 환경을 분리하면 테스트 데이터나 비밀정보가 운영에 섞이는 위험을 줄일 수 있습니다.
“이 기능은 작동만 하면 되는 것이 아니라 서버에서 사용자별 권한을 검사해야 합니다. 조회·수정·삭제 각각의 허용 대상을 명시하고, 다른 사용자의 ID나 다른 Workspace ID를 넣었을 때 반드시 거부되는 테스트도 만들어 주세요.”