실제로 일어나는 사고를 늘어놓아 보면 특이한 공격 기법은 거의 나오지 않는다. 나오는 것은 몇 가지 반복되는 패턴이며, 그 패턴은 기술이 아니라 그 뒤에 있는 전제로 분류할 때 더 분명해진다.
① 기본값은 안전하다는 전제(아무것도 설정하지 않았다)
개발 편의를 위해 고른 기본값
자세한 오류 · 접근 가능한 관리 화면 · 넓은 권한
↓ 그대로 배포
보는 사람 누구에게나 내부 정보를 보여 준다
구조, 경로, 버전, 내부 값이 읽힌다
- 운영 환경에서 켜진 디버그 출력
- 오류 페이지에 환경 변수, 파일 경로, 스택 트레이스가 나오지 않는가? 존재하지 않는 URL을 열어 돌아오는 내용을 직접 눈으로 본다. 프레임워크별 내용은 프레임워크 가이드에 있다
- 접근 가능한 관리 화면
- 데이터베이스 관리 도구나 관리 콘솔이 인터넷에서 접근 가능하다. 인증에만 기대지 말고 IP 제한이나 네트워크 수준의 차단을 겹친다
- 설정되지 않았거나 오래된 목록에서 복사한 헤더
- 아직 중요한 헤더와 그렇지 않은 헤더 참고. 폐지된 헤더는 추가하면 해가 될 수 있다
- 방치된 약한 저장 방식
- 해싱과 솔트에서 설명한 비밀번호 저장. '암호화되어 있다'는 저장 방식에 대한 설명이 아니다
- 멈춘 업데이트
- 언어, 프레임워크, CMS를 지원 기간이 끝난 뒤에도 운영하고 있다. 의존성을 기계로 감시하기와 지원 종료가 실제로 뜻하는 것 참고
② 쓰지 않는 것은 해가 없다는 전제(아무것도 닫지 않았다)
공격 표면은 만든 것보다 쓰지 않게 된 것에서 더 많이 생긴다. 무언가를 쓰지 않게 되면, 아무도 모르는 사이에 모니터링과 검토 대상에서 빠진다.
- 공개 디렉터리에 남은 시크릿
.env, 백업, 덤프, 설정 파일. 공개 디렉터리에 절대 두면 안 되는 것 / 공유 호스팅에서의 배치- 여전히 공개된 스토리지
- 차단을 켜도 기존 공개 정책은 지워지지 않는다. 공개 버킷
- 남아 있는 DNS 레코드
- 리소스를 지우고 DNS 항목을 남기면 누구나 그 이름을 차지해 서브도메인을 가져갈 수 있다. 서브도메인 탈취
- 열려 있는 가입·관리 경로
- 공개 가입이 아직 켜져 있지 않은가? 설정을 읽지 말고 HTTP로 측정한다(인증과 인가의 차이). 추측 가능한 URL을 페이지를 '숨기는' 유일한 수단으로 두지 않는다
- 해지했다고 생각한 계정
- 서비스 해지와 계정 삭제는 다르며, 삭제하기 전까지 데이터는 남는다. 호스팅 업체가 침해당했을 때
- 오래된 키, 토큰, 권한
- 퇴사한 동료의 계정, 만료 없는 토큰, 지나치게 넓은 범위. SSH 키와 최소 권한 / 비밀번호 관리자
점검 범위를 '돌아가고 있는 것'으로 한정하지 않는다
'지금 쓰고 있는 것'으로 범위를 좁히면 이 유형은 전혀 찾을 수 없다. 서브도메인, 계정, 키, 버킷, 스테이징 환경, 외부 서비스 구독까지, 지금까지 만든 모든 것을 범위로 잡는다. 쓰지 않게 된 것도 삭제하기 전까지는 자산이다. 목록 만드는 법: 자산 점검 체크리스트.
③ 알아차릴 것이라는 전제(모니터링이 없다)
피해는 침해 자체보다 누군가 알아차리기까지 얼마나 오래 이어지느냐로 정해진다. 그리고 대부분의 환경에는 알아차릴 장치가 없다.
흔한 상태
・접근 로그는 있지만 아무도 읽지 않는다
・인증 시도의 감사 로그가 없다(그래서 나중에 '무엇이 보였는지' 재구성할 수 없다)
・요청 제한은 설정했지만 언제 작동했는지 아무도 볼 수 없다
・공개 상태가 여러 층의 조합이라 어느 하나로는 답이 나오지 않는다
결국 무슨 일이 있었는지에 대해 '모른다'고밖에 말할 수 없게 된다.
갖출 만한 최소한
・신규 가입 알림(이상한 것을 잡는 데는 신호 하나로 충분하다)
・보존 기간을 정한 인증 성공·실패 기록
・의존성 취약점의 기계 감시(사람은 따라갈 수 없다 → osv-scanner)
・제한에 걸린 기록과 급증 시 알림(요청 제한과 남용 방지)
전부 필요하지는 않다. 제대로 작동하는 알아차림 수단 하나가 사고가 길어지는 것을 막는다.
로그가 없으면 정직한 답은 '아무 일도 없었다'가 아니라 '모른다'이다
사고 대응에서 가장 위험한 것은 기록이 없다는 것을 아무 일도 없었다는 증거로 읽는 것이다. 기록이 없으면 말할 수 있는 것은 '모른다'뿐이며, 그때는 침해를 전제로 움직여 노출됐을 수 있는 것을 교체한다. 조직의 최소한은 조직을 위한 보안 기본에 있다.
④ 검증한 입력은 안전하다는 전제
입력에 대한 진짜 질문은 '이 값이 맞는가'가 아니라 '이 입력에 얼마나 많은 판단을 맡겼는가'이다. 맡긴 판단이 많을수록 검증이 따라가지 못한다.
- 값만
- 평범한 입력. 길이, 형식, 범위 검사가 통한다. 안전한 쪽
- 구조까지
- 중첩된 객체를 통째로 받아 병합하는 설계. 프로토타입 오염
- 타입까지
- 객체를 재구성하는 형식. 값 검사가 돌기 전에 공격이 성공한다. 안전하지 않은 역직렬화
- 놓이는 위치
- 업로드한 파일이 실행될 수 있는 곳에 놓인다. 파일 업로드 취약점
- 요청한 사람이 누구인지
- 요청 헤더를 믿고 클라이언트가 누구인지 정한다. X-Forwarded-For 위조와 신뢰할 프록시
맡긴 판단을 세어 보면 위험한 곳이 보인다. 그리고 근본 원인은 대개 같다. 구조로 풀어야 할 것을 검증으로 풀려고 하는 것이다. 검사를 하나 더 추가하는 것보다 받아들이는 형식을 바꾸는 편이 더 확실하다.
순서대로 하기
운영 환경이 실제로 어떻게 보이는지 본다(①)
존재하지 않는 URL, 오류가 나는 요청, 관리 경로를 HTTP로 요청해 돌아오는 내용을 본다. 설정이 아니라 출력을 읽는 것이 핵심이다. 헤더는 헤더 스캐너로 한 번에 측정할 수 있다.
지금까지 만든 것을 모두 적는다(②)
서브도메인, 계정, 키, 버킷, 외부 서비스. 요령은 '아직 돌아가는 것'으로 거르지 않는 것이다. 자산 점검 체크리스트로 목록을 만들고, 쓰지 않는 항목은 비활성화에서 멈추지 말고 삭제까지 간다.
알아차릴 수단을 딱 하나 만든다(③)
완전한 모니터링을 한 번에 갖추려 하면 대개 아무것도 남지 않는다. 신규 가입 알림, 로그인 실패 급증, 의존성 취약점 메일 중 하나로 시작한다. 실제로 울리는지 확인하는 것까지 포함해 하나다(설정했지만 확인하지 않은 모니터링은 없는 것과 같다).
입력이 정하게 둔 것을 센다(④)
외부 데이터가 값만 정하는지, 구조·타입·위치까지 정하는지 적어 본다. 값보다 많은 것을 정하는 곳은 우선적으로 바꿔야 할 곳이다.
업데이트를 장치로 만든다(①이 돌아오지 않게)
첫 번째 유형은 방치하면 반드시 돌아온다. 의존성과 프레임워크 업데이트를 기계 감시 아래 두는 것이 현실적인 유일한 답이다(osv-scanner 시작하기 / 실무용 CVE 대응 플레이북). 문서에만 있는 절차는 바쁜 날 가장 먼저 건너뛰어진다.
이 사이트의 관점: 네 가지 모두 한때는 맞았다
네 가지의 공통점은 각각 어느 시점에는 옳았다는 것이다. 개발 중에는 기본값이 합리적이었고, 쓰지 않는 것은 정말로 쓰이지 않았고, 규모가 작을 때는 정말로 알아차렸을 것이며, 입력 검증은 실제로 많은 문제를 해결해 왔다. 그래서 다시 검토되지 않는다.
우리는 한때 옳았던 전제가 언제 옳지 않게 됐는지를 정기적으로 묻자는 입장이다. 그 확인이 기술을 더 들이는 것보다 싸고 효과적이다. 그리고 성격의 차이에 주의하라. 체크리스트는 무엇을 할지 알려 주지만 왜 놓쳤는지는 알려 주지 않는다. 그 이유가 그대로라면 같은 것을 같은 곳에서 또 놓친다.
다음에 읽을 글
- 절차로: 보안 기본 체크리스트(개인·작은 팀) / 조직을 위한 보안 기본
- 점검: 자산 점검 체크리스트
- 실제 사례에서: 사고 분석(같은 패턴이 계속 다시 나온다)
- 동향: 2026년, 공격자는 취약점보다 자격 증명을 들고 오는 경우가 더 많았다
FAQ
Q보안은 어디서부터 시작해야 하나요?
개별 공격 기법을 배우는 것보다, 자기 환경이 네 가지 패턴 중 어디에 해당하는지 확인하는 편이 빠릅니다. 운영 환경 설정이 아직 기본값인가? 만들어 놓고 닫지 않은 것이 아직 열려 있는가? 무슨 일이 생기면 알아차릴 수 있는가? 외부 입력에 얼마나 많은 판단을 맡기고 있는가? 이 글은 각각의 구체적인 확인 방법과 더 자세한 글로 가는 링크를 제공합니다.
Q작은 개인 사이트에도 해당되나요?
패턴은 같고 순서가 달라집니다. 개인이나 작은 팀이라면 먼저 효과가 나는 것은 기본값 확인(운영 환경에서 디버그 출력이 켜져 있지 않은가?)과, 닫지 않은 것의 점검(공개 디렉터리의 시크릿, 쓰지 않는 서브도메인, 휴면 계정)입니다. 관찰 수단은 장치가 필요하므로 나중에 해도 되지만, 신규 가입 알림 같은 신호 하나만 있어도 문제를 알아차리지 못하는 기간이 크게 줄어듭니다.
Q체크리스트와 무엇이 다른가요?
체크리스트는 무엇을 할지 알려 주고, 이 글은 왜 놓치는지를 다룹니다. 놓친 이유가 그대로라면 항목을 나열해도 도움이 되지 않고, 같은 것을 같은 곳에서 또 놓칩니다. 네 가지 믿음은 모두 한때 맞았기 때문에 검토되지 않은 채 남습니다. 실제 절차가 필요하면 각 섹션에서 체크리스트 글로 가는 링크를 따라가세요.
Q하나만 할 시간이 있다면 무엇을 하나요?
세 번째, 알아차릴 수 있게 하는 것 하나를 고치세요. 앞의 두 가지는 방치하면 사고가 되지만, 세 번째가 없으면 사고가 났다는 사실조차 알 수 없습니다. 피해는 침해 자체보다 알아차리지 못한 채 이어지는 기간에 의해 더 크게 정해집니다. 로그를 남기거나, 알림을 하나 추가하거나, 한 달에 한 번 점검하는 것. 어느 것이든 사고가 길어지는 것을 막는 가장 효과가 큰 투자입니다.