사람 눈에만 보이지 않는 취약점
오래전에 "화면에서만 안 보이게 해주세요" 라는 요구에 따라 화면에서 회원가입 기능이 감춰진 적이 있다. 시간이 흘러 회원가입 경로가 없으니 가입되면 안 되는 테스트 환경에서, 테스트 자동화로 생성된 것이 아닌 외부 IP에 의해 만들어진 계정이 발견되었다.
'뭐지?' 화면 어디에도 가입 버튼이 없는데 어떻게 계정을 만든 걸까?
최근 고객사의 요청에 따라 자체적으로 만든 동적 애플리케이션 보안 테스팅(DAST)까지 수행한 결과까지 전달했던 터라, 그나마 다른 서비스보다 안전할 것이라 믿었던 만큼 허탈함은 더 컸다. 의심스러운 요청 기록을 따라 코드를 상세히 분석해 보니 사람 눈에 보이지 않았던 결함들이 수두룩 발견되었다.
비정상적인 요청을 감지하지 못하는 환경
우리는 왜 의심스러운 계정 생성을 알아채지 못했을까? 알고보니, 이 테스트 환경은 외부 공격자의 수상한 접근이나 정찰 활동을 전혀 눈치챌 수 없는 구조적 한계를 안고 있었다.
운영 환경과 다르게 이 테스트 환경에는 Amazon GuardDuty 또는 VPC Flow Logs와 같은 최소한의 감시 기록조차 남지 않도록 설정되어 방치된 상태였다. 비인가 포트 스캔이나 비정상적인 요청이 있었음에도 인프라 레벨에서 사전에 감지하고 차단할 수 있는 기반이 테스트 환경에는 단 하나도 작동하지 않았다.
테스트 환경임에도 사내망 IP 대역으로 제한하지 않고 인터넷에서 접근이 가능한 외부 도메인이 연결되어 있었다. 회사의 대표 도메인 아래에 서브도메인을 두고 있었기에, 인증서 투명성(CT) 로그나 도메인 열거(브루트포스)만으로도 테스트 환경 도메인을 쉽게 알아낼 수 있다는 점을 간과했다.
"화면에서만 숨겨주세요"
발견된 계정은 시스템 관리자만 만들 수 있어야 했고, 화면 어디에도 회원가입 경로는 없었다. 자동화 E2E 테스트 계정 패턴과도 달라 외부 누군가가 직접 생성한 것이 분명했다.
가입 버튼도 없는 화면에서 어떻게 계정이 만들어졌을까?
깃(Git) 히스토리를 확인하고 나서야 이유는 명확해졌다. 과거 요청을 반영했던 개발자가 프론트엔드 화면 코드만 삭제하고 백엔드 API는 그대로 남겨두었던 것이다. 테스트 엔지니어는 요구사항대로 화면에서 보이지 않으니 기능이 제거된 것으로 보고 통과시킨 것으로 보인다.
브라우저 화면의 링크와 버튼을 타고 다니며 취약점을 찾는 DAST 스캐너의 특성상, 프론트엔드에서 사용하지 않은 채 백엔드에만 남아있는 경로는 애초에 검증 대상에 포함되지 않는 사각지대 였던 것이다.
공격자는 화면이 아니라 코드를 본다
'AI에 해킹 맡기니 2분 만에 침투거점 확보…'라는 뉴스 기사처럼, 지금은 자동화 도구와 AI 에이전트로 숨은 취약점을 순식간에 훑어내는 시대다. 사람은 브라우저 화면(UI)을 보지만, 공격자와 스캐너는 도메인과 코드, 그리고 백엔드 엔드포인트를 본다.
이 테스트 환경의 도메인은 외부에 공개되어 있지 않은데 어떻게 알고 접속한 걸까?
crt.sh 같은 인증서 투명성(Certificate Transparency) 로그 서비스로 서브도메인을 확인할 수도 있지만, 무엇보다 공격자는 AWS IP 대역 전체에 접속해 SSL/TLS 인증서와 서버 응답을 무차별 수집한다. 사내망으로 제한하지 않고 인터넷에 퍼블릭하게 열어둔 이상 도메인 주소는 결코 비밀로 지켜낼 수 없었다.
이어 프론트엔드에 남겨진 흔적들과 노출된 경로들을 토대로 화면 뒤에 숨겨진 회원가입 API를 특정했을 것으로 보인다.
계정 생성 시 이메일 인증 단계 부재
정작 백엔드에는 외부에 그대로 노출된 가입 API 엔드포인트가 남아 있었다. 평소 시스템 관리자가 계정을 직접 생성해 주는 구조였기에 가입 절차에 별도의 이메일 인증 단계조차 마련되어 있지 않았던 것이다.
공격자는 브라우저 화면을 통하지 않고 curl 같은 도구로 백엔드 엔드포인트에 직접 HTTP 가입 요청을 보냈고, 백엔드 API에서는 일회용 임시 메일에 대한 인증도 없이 해당 요청을 그대로 처리했다. 그렇게 계정을 생성한 공격자는 다른 API 요청들을 파라미터 조작으로 몇 가지 시도해본 뒤 곧바로 계정을 삭제하고 흔적을 지웠다.
취약점을 가진 시스템인지 가볍게 사전 조사한 흔적 같다.
정말로 사용하지 않을 기능이라면 백엔드 엔드포인트와 비즈니스 로직까지 완전히 도려냈어야 했다. 하지만 "화면에서만 안 보이게 해달라"는 요구를 기계적으로 수용해 눈앞의 화면만 치워버렸고, 보이지 않는다는 이유로 모두가 잊고 안도했던 안일한 대응이 결국 부메랑이 되어 돌아왔다.
감시의 공백 속에서 찾아낸 흔적
다우오피스 해킹 사례처럼 사내에 오래 자리 잡은 솔루션이라고 해서 안전하다고 안심해서는 안 된다. 수많은 릴리즈를 거치며 급하게 덧댄 임시 조치들이 쌓여 기본 인증과 인가의 경계를 무디게 만들었을 뿐이다.
인프라 레벨의 감시 로그가 전무한 상황에서 유일한 단서는 웹 애플리케이션 앞단에 배치해 둔 Nginx의 액세스 로그였다. 고객사 환경 구조에 맞추기 위해 띄워둔 프록시 서버 덕분에 최소한의 요청 기록이라도 건질 수 있었던 것이다. 구체적인 유입 전 과정은 알 수 없었지만, 공격자가 남긴 요청 기록을 전수 조사하기 시작했다.
파라미터 취약점 조사
로그를 분석해 보니 공격자는 다른 사용자의 아이디를 주입하며 파라미터 취약점을 찔러본 흔적이 있었다. 응답 본문이 로그에 남지 않아 패킷 크기와 실제 응답을 일일이 대조하며 요청을 재현해 보았다.
대부분 403 권한 오류로 막혔지만, 200 응답을 받은 경로에서 전화번호 필드가 암호화되지 않은 평문 그대로 조회되는 취약점이 확인되었다. 가상 번호라 다행이었지, 테스트를 위해 실제 운영 데이터의 일부라도 복제되어 방치되어 있었다면 치명적인 개인정보 유출 사고로 이어질 뻔한 아찔한 순간이었다.
데이터 파기 정책 부재
더존비즈온이 서비스 계약이 종료된 기업들의 데이터를 삭제하지 않고 보관했던 사례처럼, 일반적인 서비스와 다르게 기업용 솔루션은 데이터 파기 정책이나 자동 삭제 기능 자체가 없는 경우가 많다. 일반인들은 서비스를 오랫동안 쓰지 않으면 약관에 따라 데이터가 자동으로 없어지겠지 믿겠지만, 솔루션 환경에서는 이를 전혀 보장할 수 없다. 취약점을 막는 것만큼이나 목적을 다한 데이터를 제때 완벽하게 파기하는 기본이 지켜지지 않는다면 테스트 서버는 언제든 터질 수 있는 시한폭탄이 된다.
요청은 없었지만 위험했던 다른 경로
AI 에이전트로 시스템 코드를 상세히 분석해 보니, 계정을 생성해 일부 요청만 해보고 삭제했던 공격자가 미처 호출하지 않았던 불필요한 경로들이 많이 남아 있었다.
과거 개발 과정에서 테스트 편의를 위해 만들었던 엔드포인트가 미처 삭제되지 못하고 방치되어 있었던 것이다. 민감한 정보들을 응답하는 경로는 아니었지만 세부 권한 검증이 제대로 되지 않은 경로들이 다수 확인되었다.
아무튼 위험 가능성을 인지하자마자 사용하지 않는 경로들을 Nginx와 인프라 레벨에서 우선적으로 차단했다. 이어 외부 IP 대역의 접근을 전면 차단하고 VPN으로 사내망에서만 접속할 수 있도록 조치했다.
방치되기 쉬운 관리용 엔드포인트
남겨진 요청 로그를 살펴보니 공격자가 Spring Boot Actuator 엔드포인트 경로들을 호출한 흔적이 있었다. 다행히도 이번 테스트 서버에는 이 엔드포인트들이 노출되어 있는 상태는 아니었다.
하지만 이번 사건을 계기로 개발 환경들을 긴급 점검해 보니, 최근 신규 서비스를 위해 추가된 다른 개발 서버 중 하나가 위험한 엔드포인트들까지 반환할 수 있게 노출 설정된 상태로 확인되었다.
management:
endpoints:
web:
exposure:
include: "*"env,configprops: 환경 변수와 내부 데이터베이스 설정값 노출heapdump: 메모리 속 비밀번호와 세션 토큰 등 민감 정보 유출shutdown: 원격에서 서버 프로세스를 강제로 종료
물론 해당 서버는 다른 서비스들을 위해 내부적으로만 사용되는 환경이었지만, 만약 신경 쓰지 않고 외부 도메인을 연결해 설정했다면 치명적인 취약점을 그대로 외부에 노출해 버릴 뻔한 위험한 상태였다.
개발 편의나 모니터링을 이유로 Actuator 엔드포인트 노출 설정을 인증 없이 열어두는 순간, 공격자는 화면 뒤를 더듬어볼 필요도 없이 시스템에서 사용하는 비밀번호와 토큰 등 민감 정보와 치명적인 권한들을 쉽게 취득할 수 있다.
AI 시대, 눈에 보이지 않는 취약점
'보안 인증'은 통과…해커 앞에선 '무용지물'이라는 보도나 금융권 해킹에 번아웃이 온 보안 인력들의 실태가 보여주듯, 국가 보안 인증(ISMS-P)을 통과했거나 전문 보안 인력이 매달리는 조직이라도 보이지 않는 사각지대를 완벽하게 통제하기는 어렵다.
사람이 직접 설계하고 검증하던 시절에도 이런 구멍이 남았는데, AI 에이전트로 코드를 빠르게 찍어내는 지금은 어떨까? 공격자 역시 AI로 손쉽게 허점을 파고드는 시대에, 개발 현장에서는 "AI가 안전하다고 했어" 라며 스스로 검증하지 않는 미트 프록시(Meat Proxy)와 '바이브 코딩' 이 흔해졌다. 눈앞의 화면만 정상 동작하면 코드 리뷰 없이 넘어가니, 보이지 않는 백엔드와 인프라의 구멍은 인지조차 못하는 것이다.
시스템에서 불필요한 경로나 기능들은 나중에 활용하려고 남겨두지 말고 과감하게 없애는 선택 이 필요하다. 화면뿐만 아니라 백엔드 엔드포인트까지 도려내고, 개발 환경이라도 최소한의 감시와 접근 제어를 유지하며 데이터를 제때 파기하는 기본이 지켜져야 보이지 않는 위협을 막을 수 있다.
HTTP2Shell 같은 외부 취약점에 대한 처리도 중요하지만, 정작 애플리케이션 내부에 쌓여 있는 수많은 취약점들을 어떻게 발견하고 조치하는 게 좋을지 막막하기만 하다. 취약점 발견 후 수정을 커밋하는 건 좋은데 빠르게 배포할 순 있나?