문제와 판단 기준

설정 파일에 운영용 API 키가 들어간 채 저장소에 올라갔다면 어떻게 해야 할까? 파일을 지우고 새 커밋을 올린 뒤 저장소까지 비공개로 바꾸면 대응을 끝내도 될까?

아닙니다. 파일을 안 보이게 만드는 일과, 이미 복사된 키로 더 이상 접근할 수 없게 만드는 일은 다릅니다. GitHub도 민감한 데이터의 이력을 정리하기 전에 노출된 시크릿을 폐기하거나 교체하도록 안내합니다. 저장소를 정리해도 다른 사람이 가져간 복제본까지 회수할 수는 없습니다.[1]

먼저 노출된 자격 증명이 행사할 수 있는 권한을 막아야 합니다. 이어서 정상 서비스의 사용처를 교체하고 이미 발급된 세션과 노출 기간의 사용 흔적을 확인해야 합니다. 다만 사고 중의 긴급 차단과 평상시의 키 교체는 같은 작업이 아닙니다. 가용성 때문에 옛 키를 잠깐 유지할 수 있는지는 별도로 판단해야 합니다.[3][6]

먼저 키의 주인과 영향을 받는 작업을 찾는다

노출 알림을 받으면 대응 기록을 만들되, 키 원문을 이슈·채팅·스크린샷에 다시 붙이지 않습니다. 기록에는 발급자와 계정, 안전하게 관리할 키 식별자, 최초 노출 가능 시각, 발견 위치, 권한, 실제 사용처를 남깁니다. 확실한 시각과 추정치는 구분합니다. OWASP도 시크릿의 담당자, 교체 방법, 교체로 끊길 수 있는 의존 관계를 문서화하도록 권고합니다.[3]

다음 질문은 이 기록을 채우기 위한 실무 확인 판단 원칙입니다.

  • 무엇이 노출됐는가? API 키, OAuth 토큰, JWT 서명용 개인키, TLS 개인키 중 무엇인지 발급자와 용도를 확인합니다. 파일 확장자만으로 판단하지 않습니다.
  • 무엇을 할 수 있는가? 특정 작업만 가능한지, 데이터 조회·수정이나 추가 자격 증명 발급까지 가능한지 확인합니다. 운영·개발 환경과 연결 계정도 구분합니다.
  • 어디까지 퍼졌고 어디서 쓰는가? 공개 저장소와 비공개 저장소의 접근 범위를 구분하고 애플리케이션·워커·예약 작업·CI·외부 연동 담당자를 찾습니다.

대응 책임자는 이 조사를 모두 끝낼 때까지 차단을 미루지 않습니다. 노출된 유효 자격 증명은 침해됐을 수 있다고 취급하고 차단과 사용처 조사를 병행하는 것이 출발점입니다.[2]

서비스 작동 방식

서비스 앞단에서 요청을 분류하고 방어 — 요청과 차단 기록을 살펴 방어 규칙을 조정하고 인증서와 접근 통제를 함께 관리합니다.

폐기부터 할까, 새 키 배포부터 할까

OWASP의 노출 대응 원칙은 신속한 폐기와 교체입니다. 아래 구분은 그 원칙을 서비스 의존성에 적용하기 위한 편집자의 판단 기준입니다. 정해진 시간 동안 노출 키를 계속 사용해도 된다는 유예 규칙이 아닙니다.[3]

공개된 운영 키이거나, 권한이 크거나, 설명되지 않는 사용이 보이면 차단이 우선입니다. 정상 작업이 중단되더라도 발급자가 제공하는 비활성화·폐기와 필요한 접근 차단을 실행할 근거가 충분합니다. 악용 흔적이 아직 없다는 이유만으로 노출 키를 살려두지는 않습니다. AWS IAM 키라면 비활성화와 영구 삭제가 구분되므로, 현재 효력을 끊은 뒤 의존성과 삭제 절차를 정리합니다.[5]

반면 차단 방식에 선택지가 있고 서비스 중단의 영향이 큰 경우에는 제한된 전환 구간을 검토할 수 있습니다. 이때는 발급자가 신·구 자격 증명의 동시 운용을 지원하는지, 전환 중에도 노출 키의 위험한 사용 경로를 실제로 막을 수 있는지부터 확인합니다. 확인된 통제가 있고 악용 징후가 없는 상황에서만 책임자와 전환 종료 시각·중단 조건을 정해 새 값 배포를 먼저 진행합니다. 통제 적용이 불확실하거나 전환이 실패하면 노출 키 사용을 중단하는 쪽으로 돌아갑니다. 저장소 비공개 전환이나 모니터링만으로 이 조건을 충족했다고 보아서는 안 됩니다.

발급자에서 이미 만료·폐기된 값임을 확인했다면 불필요한 재발급까지 할 필요는 없습니다. 다만 그 값이 유효했던 동안의 사용과 남은 세션을 조사할 필요는 여전히 있습니다. 새 키를 만들었다는 사실 자체는 옛 키가 무효라는 증거가 아닙니다.

교체 완료는 저장소가 아니라 실제 사용처에서 확인한다

새 시크릿은 노출 경로를 막은 뒤 신뢰할 수 있는 관리 경로로 배포합니다. 시크릿을 보관하는 시스템만 바꿔놓고 사용처를 확인하지 않으면 대응 기록이 비게 됩니다. 이 글에서는 다음과 같이 완료 증거를 나누어 남길 것을 제안합니다.

새 값의 적용 증거에는 어떤 시크릿 버전이 어느 서비스에 적용됐는지, 필요한 재시작·재배포를 했는지, 실제 업무 동작이 성공했는지를 적습니다. 웹 화면의 상태 확인만으로 끝내지 말고 비동기 워커, 예약 배치, CI 작업처럼 실행 시점이 다른 경로도 확인합니다. 운영 작업을 시험할 때는 소유하거나 명시적으로 허가받은 범위에서 비파괴 검증을 사용합니다.

옛 값의 차단 증거에는 발급자의 관리 화면·관리 API에서 확인한 비활성화 또는 폐기 상태, 조치 시각, 적용 범위를 남깁니다. 노출된 키를 제3자 시스템에 다시 넣어 작동하는지 시험하지 않습니다. GitHub 경고를 닫거나 파일에서 문자열을 지운 것만으로 이 증거를 대신할 수 없습니다.[2][5]

권한 축소도 별도 작업입니다. AWS IAM에서는 IAM 사용자·역할에 부여한 권한을 검토해야 하며 새 키 문자열을 발급하는 것만으로 권한이 줄지 않습니다. 필요한 작업만 허용하도록 정책을 줄이고 사용처를 분리해야 한다면 신원과 권한 경계도 함께 설계합니다.[6]

복구 계획에도 같은 원칙을 적용합니다. 새 배포에 문제가 생겼다고 노출된 옛 키를 다시 활성화하지 않습니다. 이전 코드가 새 자격 증명으로 작동하도록 되돌리거나 해당 기능을 일시 중지하는 경로를 준비합니다. 키를 다시 노출하는 설정·이미지로 돌아가는 것은 복구 완료로 기록하지 않습니다.

API 키·토큰·서명 키·인증서는 끝내는 조건이 다르다

AWS 장기 키를 꺼도 임시 세션은 따로 살핀다

장기 키로 AWS STS 임시 자격 증명을 발급받았을 가능성이 있다면 그 경로를 별도로 조사합니다. AWS는 임시 자격 증명의 권한을 차단하는 절차와 IAM 역할 세션을 철회하는 절차를 제공합니다. 역할 세션 철회는 특정 시각 이전에 발급된 세션의 권한을 거부하는 방식이며 그 역할을 공유하는 정상 사용자·작업도 영향을 받습니다.[7][8]

따라서 기록에는 원래 키의 상태 외에 영향을 받은 역할, 세션 발급 시각, 차단 정책을 남깁니다. 정책 전파 지연과 다른 역할로 이어진 접근도 고려합니다. 서비스 연결 역할과 IAM Identity Center가 관리하는 세션에는 일반 역할과 다른 제약·절차가 있으므로 동일한 조치를 일괄 적용하지 않습니다.[7][8]

OAuth 토큰은 재발급 경로와 이미 발급된 토큰을 나눈다

Auth0에서는 새 토큰을 발급받는 데 쓰는 refresh token(갱신 토큰)을 폐기할 수 있습니다. 다만 사용한 API와 테넌트 설정에 따라 해당 토큰만 처리하는지 관련 grant(권한 부여 관계) 범위까지 처리하는지가 달라집니다. 한편 API 접근에 쓰는 access token과 사용자 인증 정보를 담는 ID token은 서버에 저장한 세션 쿠키와 같은 방식으로 폐기할 수 없다고 안내합니다.[11][12]

따라서 refresh token 폐기만 보고 기존 access token, 애플리케이션 자체 세션, 외부 서비스 토큰까지 모두 종료됐다고 판단하지 않습니다. 발급자별로 재발급 차단과 기존 접근 차단의 적용 범위를 확인하고 남는 유효 기간과 필요한 추가 통제를 기록합니다.

서명 키 회전은 옛 키에 대한 신뢰 철회와 다르다

Auth0의 서명 키 회전은 옛 키로 서명한 토큰을 즉시 무효화하는 절차가 아닙니다. 이전 키를 폐기하는 단계가 따로 있습니다. 또한 애플리케이션이나 API Gateway가 공개키 집합인 JWKS를 주기적으로 가져오는지, 인증서를 수동으로 고정해 두었는지에 따라 변경 작업이 달라집니다.[13][14]

유출된 서명 키를 다룰 때는 새 키로 발급되는지만 확인하지 말고, 각 검증 지점이 옛 키를 더 이상 신뢰하지 않는지도 확인 대상으로 넣습니다. 이때 정상 토큰이 거절되거나 재로그인이 필요해질 수 있는 범위를 함께 정합니다.

TLS 인증서 파일과 개인키 노출을 혼동하지 않는다

공개 인증서와 개인키는 다릅니다. Let’s Encrypt는 발급 인증서를 Certificate Transparency 로그에 기록하며 개인키가 유출됐을 때는 해당 인증서를 폐기해야 한다고 안내합니다. 개인키 침해가 의심되면 폐기 사유도 keyCompromise로 구분합니다.[15]

개인키 노출이라면 같은 개인키를 유지한 재발급을 해결책으로 삼지 말고, 새 키 쌍과 인증서 배포, 옛 인증서 폐기를 함께 계획합니다. Let’s Encrypt의 안내도 폐기 정보를 확인하는 브라우저를 제한적으로 설명하므로, 인증서 폐기 요청 하나가 모든 클라이언트의 접근을 즉시 차단한다고 약속해서는 안 됩니다.[15]

Git 이력 밖으로도 정리 범위를 넓힌다

키의 효력을 끊은 뒤에는 남은 노출 경로를 정리합니다. 확인 범위에는 현재 브랜치뿐 아니라 다른 브랜치·태그·과거 커밋, pull request의 참조, fork와 협업자의 복제본을 넣습니다. GitHub는 이력 재작성이 커밋 해시와 서명, PR 검토, 협업자의 작업에 영향을 줄 수 있다고 설명합니다. 무조건 force push부터 할 작업은 아닙니다.[1]

운영 쪽에서는 CI 로그, 빌드 캐시와 이미지, 배포 아티팩트, 설정 파일, 테스트 데이터와 내보낸 자료를 확인 대상으로 삼습니다. Docker는 빌드 인자와 환경 변수로 전달한 시크릿이 최종 이미지에 남을 수 있어 secret mount 등을 사용하도록 안내합니다. 현재 소스가 깨끗해졌다는 확인을 이미 배포된 이미지까지 깨끗하다는 뜻으로 확대하지 않습니다.[16]

.gitignore에 파일을 추가하는 것도 사후 정리를 대신하지 못합니다. Git 공식 문서에 따르면 이미 추적 중인 파일은 이 설정의 영향을 받지 않습니다.[4]

정리 결과에는 제거한 위치, 접근을 제한한 위치, 직접 회수할 수 없는 복제본을 구분해 남깁니다. 외부에 복사된 값은 모두 삭제했는지 확인하기 어렵습니다.

서비스 작동 방식

관측에서 복구와 개선까지 이어지는 운영 — 서비스 지표와 경보를 기준으로 대응하고 변경 이력과 사후 보고를 다음 개선에 연결합니다.

증거는 보존하되, 시크릿 원문을 다시 퍼뜨리지 않는다

증거 보존은 긴급 차단을 늦추지 않는 범위에서 병행합니다. 로그를 정리하기 전에 조사에 필요한 증거를 접근 제한된 위치에 보존합니다. 시크릿이 포함된 로그는 원문을 일반 티켓에 복사하는 대신 증거 보관 위치와 식별자를 연결합니다. 노출된 로그의 정리와 증거의 무결성 보존은 함께 설계해야 합니다.[3]

AWS CloudTrail에서는 요청 주체와 임시 자격 증명의 세션 정보를 확인할 수 있습니다. 다만 accessKeyId가 항상 제공되는 것은 아니며, 역할 세션 요청에는 원래 장기 키가 아니라 임시 자격 증명의 키 ID가 기록됩니다. 키 하나만 검색하고 조사를 끝내지 않는 이유입니다.[9]

기록이 없는 이유도 확인해야 합니다. CloudTrail Event history는 최근 90일의 관리 이벤트를 리전별로 보여주며 데이터 이벤트는 포함하지 않습니다. 이 화면에서 이상이 없었다는 사실만으로 데이터 조회·유출이 없었다고 결론낼 수 없습니다. 실제 활성화돼 있던 데이터 이벤트와 서비스별 로그의 보존 범위를 따로 확인합니다.[10]

영향 기록은 ‘키 노출 확인’, ‘설명되지 않는 사용 발견’, ‘실제 피해 확인’, ‘로그 부족으로 미확정’을 구분합니다. 의심되는 사용이 있다면 생성된 자격 증명·리소스나 변경된 권한까지 후속 조사 대상으로 지정합니다. 키 교체 후 서비스가 정상이라는 사실은 과거에 발생한 변경을 되돌렸다는 증거가 아닙니다.

대응 기록표: 서비스 복구와 조사 종료를 분리하는 예시

아래는 설계 예시다. 실제 IXC 고객이나 대응 실적이 아닙니다. 공개 저장소에서 업로드 서비스용 IAM 키가 발견됐고, 이 키를 사용하는 웹·워커·CI와 접근 가능한 역할이 있다고 가정했습니다. 각 ‘완료’와 관찰 결과, EV로 표시한 증거 식별자 역시 가상으로 채운 값입니다. 키 원문은 사용하지 않습니다.

단계·상태담당자선택한 조치완료 증거 또는 남은 확인가용성 영향
발견 · 완료개발 리드발급자·키 식별자·권한·노출 커밋·사용처를 식별하고 담당자를 지정EV-01: 접근 제한된 사건 기록에 노출 커밋·알림 식별자와 웹·워커·CI 의존성 목록 정리 완료조사만으로 서비스 변경은 하지 않음
확산·악용 억제 · 완료클라우드 운영자공개 노출이므로 구 키를 비활성화하고 위험 권한과 관련 역할의 기존 세션을 차단EV-02: 구 키 비활성 상태 재확인. 정책 변경·기존 세션 차단 기록과 영향 역할 명시업로드와 같은 역할을 쓰는 작업이 중단됨. 읽기 기능과 영향 범위를 따로 확인
의존성 교체 · 완료배포 담당자필요한 권한으로 새 자격 증명을 배포하고 웹·워커·CI를 각각 전환EV-03: 새 시크릿 버전 적용 확인. 웹·워커·CI 검증 성공, 대기 작업 처리 재개 확인배포 중 업로드 제한 후 기능 복구. 노출 키 재활성화는 제외
영향 확인 · 진행 중보안 담당자정상 작업으로 설명되지 않는 역할 인수 이벤트 1건을 조사EV-04: 해당 세션 접근 차단 확인. 노출 기간 일부의 데이터 이벤트가 미수집돼 데이터 접근 영향은 미확정서비스 복구와 무관하게 조사 지속. 추가 제한이 필요하면 재평가
재발 방지 · 일부 완료플랫폼 담당자로그 출력 제거·변경 검토를 보완하고 사용처별 신원 분리와 단기 자격 증명 전환을 계획EV-05: 비활성 테스트 문자열 검출 확인. 신원 분리는 플랫폼 담당자의 후속 작업으로 등록하고 다음 배포 검토일에 재평가후속 변경은 따로 검증·배포하며 완료 전 효과를 주장하지 않음

이 예시의 상태는 ‘서비스 복구 완료, 영향 조사 미종료’다. 대응표를 모두 초록색으로 만들기 위해 미확정 항목을 ‘이상 없음’으로 바꾸지 않습니다.

다음 노출이 같은 장애로 이어지지 않게 한다

장기 키를 보유할 이유부터 줄입니다. AWS에서 실행하는 애플리케이션이라면 역할 기반 임시 자격 증명을 우선 검토하고 장기 키가 필요한 경로는 필요한 권한만 부여합니다.[6]

남겨야 하는 시크릿에는 담당자, 사용처, 수명, 교체 방법, 폐기 확인 방법을 붙입니다. 시크릿 저장소와 최소 권한, 코드·로그 출력 검토, 커밋·푸시 단계의 검출을 함께 운영합니다. 스캐너의 경고 수만 줄이는 대신 ‘누가 바꾸고 무엇으로 완료를 확인하는가’를 정합니다.[3]

발급자 관리 권한과 사용처가 명확하다면 내부 담당자가 공개 지침에 따라 대응할 수 있습니다. 반대로 권한이 여러 계정에 걸치거나, 서명 키·파생 세션의 경계를 모르는 경우, 악용 징후나 로그 공백 때문에 영향을 판단할 수 없는 경우에는 보안 담당자와 발급자 지원 조직을 조기에 참여시키는 편이 낫습니다. 새 도구를 구매하는 일이 노출 키의 차단보다 먼저일 필요는 없습니다.

마지막에 남길 답은 ‘파일을 지웠다’가 아닙니다. 어떤 접근을 막았는지, 어떤 사용처를 복구했는지, 어떤 영향은 확인했고 무엇이 아직 미확정인지를 증거와 함께 설명할 수 있어야 합니다.