노출된 키 추적 및 폐기

사이버 보안Beginner
지금 연습하기

소개

지원 요약 작업은 고객 티켓을 읽고 짧은 요약을 게시합니다. 누군가 저장소의 최신 예제에서 API 키를 지웠지만 그 값을 사용한 요청이 여전히 성공합니다. 여러분은 이 경고를 조사하는 유지보수 담당자입니다.

먼저 정상 요청 흐름을 이해한 뒤 과거 증거를 찾고 자격 증명을 식별하여 폐기합니다. 로컬 가상 제공자, 준비된 두 터미널 역할, Key Manager를 사용합니다. 기본적인 터미널 사용 능력이면 충분하며 Git, API 요청, 키 폐기는 여기서 설명합니다.

API로 티켓 읽기

이 단계에서는 티켓 읽기 요청을 보내고 응답을 알아보는 방법을 배웁니다. 지원 티켓은 고객의 도움 요청입니다. 요약 작업은 티켓 묶음을 읽고 짧은 요약을 서비스에 돌려주는 준비된 프로그램입니다. 연동은 한 프로그램이 다른 프로그램과 함께 일하는 것을 뜻합니다.

이 단계를 시작하려면 실습 인터페이스에서 Workstation 탭을 선택합니다.

이 실습의 로컬 교육용 제공자는 가상 고객과 키를 사용합니다. API는 실제 요청 인증과 권한 검사를 수행하지만 특정 클라우드 제공자의 복제본은 아닙니다. 실제 계정이나 외부 대상은 사용하지 않습니다.

두 터미널 역할 사용하기

Workstation은 유지보수 터미널로 예제 설정이 있는 /home/labex/project/repository에서 열립니다. Integration은 작업의 비공개 런타임 설정을 소유한 keyworker 계정으로 실행됩니다. 명령마다 지정된 터미널을 사용하세요. 디렉터리를 바꿔도 계정은 바뀌지 않습니다. Key Manager 탭은 별도 운영자 로그인으로 자격 증명을 관리합니다.

Workstation에서 pwd는 현재 디렉터리를 출력하고 ls는 파일 이름을 나열합니다.

다음 명령을 실행하기 전에 Workstation 탭으로 전환합니다.

pwd
/home/labex/project/repository
ls

README.md와 summary-example.ini가 보여야 합니다. 저장소 예제이며 실행 중인 작업이 읽는 비공개 파일은 아닙니다.

요청 인터페이스 이해하기

API는 프로그램 요청을 받는 서비스 인터페이스입니다. 엔드포인트는 작업과 경로의 조합입니다. 여기서는 GET /v1/tickets가 티켓을 읽고 POST /v1/summaries가 요약을 게시합니다. http://127.0.0.1:8000은 이 VM의 로컬 서비스로, 127.0.0.1은 현재 머신이고 8000은 수신 대기 포트입니다.

요청에는 프로그램 인증에 쓰는 비밀값인 API 키가 포함됩니다. 키는 이름이 붙은 요청 메타데이터인 Authorization 헤더로 전달됩니다. 이 제공자는 Bearer 다음에 비밀값을 요구합니다. 연습용 가상 키를 실제 자격 증명과 혼용하지 마세요.

Workstation 탭으로 전환합니다. 읽기 요청을 보냅니다. curl은 HTTP 요청을 보내고 -s는 진행 표시를 숨기며 -H는 헤더를 제공합니다. 작은따옴표는 공백과 쿼리 구분자 ?를 같은 인수로 유지합니다. batch=demo는 연습 데이터를 선택합니다.

curl -s -H 'Authorization: Bearer lab_key_support_exposed' 'http://127.0.0.1:8000/v1/tickets?batch=demo'

응답은 이름 있는 필드와 값으로 구성된 JSON입니다. batch는 데이터셋 이름이고 items는 목록입니다. 티켓에는 id와 subject가 있습니다. request_id는 매번 달라질 수 있는 감사 식별자로 비밀값이 아닙니다. 제목 Delivery question을 찾아보세요.

데모 요약 게시하기

이 단계에서는 준비된 worker로 방금 읽은 티켓을 서비스가 수신하는 요약으로 만듭니다. 이전 단계는 읽기 요청만 수행했지만 이 프로그램은 결과도 게시합니다.

이 단계를 시작하려면 실습 인터페이스에서 Integration 탭을 선택합니다.

Integration 탭으로 전환합니다. 같은 시연 배치로 작업 프로그램을 실행합니다. python3는 제공된 Python 프로그램을 실행하고 경로는 해당 프로그램, demo는 배치 인수입니다. 이 과정에서 Python을 작성하거나 이해할 필요는 없습니다.

다음 명령을 실행하기 전에 Integration 탭으로 전환합니다.

python3 /opt/keylab/worker.py demo
Read batch: demo (1 items)
{"batch":"demo","count":1,"subjects":["Delivery question"]}
Received batch: demo
Receiving key ID: key_support_old

첫 요청은 입력을 읽고 두 번째 요청은 요약을 게시했습니다. Received batch는 수신 API가 이를 받아들였다는 뜻입니다. key_support_old 같은 키 ID는 비밀이 아닌 라벨로, 헤더의 비밀값과 다릅니다. 이 실행은 정상 동작을 보여주며 이후 복구 실습의 지정 묶음을 완료하지는 않습니다.

과거 키를 찾아 폐기하기

이 단계에서는 과거 자격 증명을 찾아 ID를 제공자 기록과 연결하고 해당 키만 폐기합니다. 눈에 보이는 줄을 지워도 최신 파일에서 사라질 뿐 자격 증명은 무효화되지 않을 수 있습니다.

이 단계를 시작하려면 실습 인터페이스에서 Workstation 탭을 선택합니다.

현재를 먼저 보고 과거 살펴보기

Workstation 탭으로 전환합니다. cat으로 현재 예시를 출력합니다. INI 파일은 [integration]처럼 대괄호로 감싼 섹션 아래 설정을 묶습니다. 각 설정에는 이름, 등호와 값이 있습니다.

다음 명령을 실행하기 전에 Workstation 탭으로 전환합니다.

cat summary-example.ini
[integration]
key_id = key_support_old
api_key = SET_AT_RUNTIME

자리표시자는 공유 예제에 적절하지만 이전 복사본이나 서비스 측 키 상태를 알려주지는 않습니다.

Git은 프로젝트 스냅샷을 커밋으로 기록합니다. 저장소에는 현재 파일과 커밋 이력이 함께 있습니다. git log는 최신 커밋부터 보여주고 --oneline은 커밋 하나를 짧은 한 줄로 표시합니다. 전역 옵션 --no-pager는 대화형 뷰어를 열지 않고 터미널에 바로 출력합니다.

git --no-pager log --oneline

Document prepared worker, Remove credential from current example, Add integration example을 볼 수 있습니다. 왼쪽의 짧은 식별자는 달라질 수 있습니다.

HEAD는 최신 커밋이고 HEAD~2는 그보다 두 커밋 전입니다. git show는 과거 객체를 표시하며 콜론은 리비전과 파일 이름을 구분합니다.

git --no-pager show HEAD~2:summary-example.ini
[integration]
key_id = key_support_old
api_key = lab_key_support_exposed

원래 비밀값을 아직 복구할 수 있습니다. 최신 예제를 지우거나 로컬 이력을 다시 써도 다른 사람이 이미 얻은 복사본을 신뢰하지 말라고 API에 알린 것은 아닙니다.

제공자의 기록과 연결하기

Key Manager는 별도 유지보수 자격 증명인 운영자 토큰을 사용합니다. 애플리케이션 키로는 키를 관리할 수 없습니다. Workstation 탭으로 전환합니다. 준비된 로컬 토큰을 표시합니다.

애플리케이션 API 자격 증명과 구분되는 Key Manager 운영자 로그인

cat /home/labex/.config/keylab/operator-token

Key Manager 탭으로 전환하고 해당 값을 Operator token에 붙여 넣은 후 Sign in, Open Key Manager를 선택합니다. 이 토큰을 저장소 파일에 넣지 마세요. 로그인이 거부되면 같은 탭에서 Return to Key Manager를 선택하고 Workstation 탭으로 전환하여 이 VM의 운영자 토큰을 다시 복사한 후 Key Manager 탭으로 돌아가 재시도합니다. key_support_old 행과 Active 상태를 찾습니다. 범위는 허용된 작업을 설명하며 다음 실습에서 범위 선택을 배웁니다.

Recent API requests에서 이 키의 성공 요청을 찾습니다. 200은 API가 읽기를 수락한 상태입니다. 이력은 노출을, 요청은 자격 증명이 작동한다는 사실을 입증하지만 과거 요청을 누가 보냈는지는 증명하지 않습니다. 보고서나 로그 복사본은 필요하지 않습니다.

식별한 키 폐기하기

침해된 키만 폐기합니다. 거부 결과와 독립 가용성은 다음 단계에서 테스트합니다. 폐기는 제공자의 허용 결정을 바꾸지만 비밀값 복사본은 지우지 못합니다.

Workstation 탭으로 전환합니다. 이번에는 HTTP 상태를 표시하며 시연 티켓을 다시 요청합니다. -w는 형식화된 결과를 추가하고 \n은 새 행을 시작하며 %{http_code}는 응답 상태를 삽입합니다.

curl -s -w '\nHTTP %{http_code}\n' -H 'Authorization: Bearer lab_key_support_exposed' 'http://127.0.0.1:8000/v1/tickets?batch=demo'

응답은 HTTP 200으로 끝납니다. Key Manager 탭으로 전환합니다. key_support_old 행에서 Revoke를 선택합니다. 모든 키를 폐기하면 관련 없는 작업이 중단되므로 ID를 주의 깊게 확인합니다. 이제 행에 Revoked가 표시되어야 합니다.

노출된 지원 키는 폐기되고 모니터는 활성 상태인 Key Manager

유출 차단 및 가용성 테스트

이 단계에서는 이전 자격 증명이 거부되고 API와 독립 모니터는 사용 가능한지 테스트합니다. 관리 화면 상태도 유용하지만 실제 요청이 접근 경계를 입증합니다.

이 단계를 시작하려면 실습 인터페이스에서 Workstation 탭을 선택합니다.

Workstation 탭에서 같은 요청을 반복합니다.

다음 명령을 실행하기 전에 Workstation 탭으로 전환합니다.

curl -s -w '\nHTTP %{http_code}\n' -H 'Authorization: Bearer lab_key_support_exposed' 'http://127.0.0.1:8000/v1/tickets?batch=demo'
{"error":"Invalid or revoked key"}
HTTP 401

이 API에서 401은 제공한 자격 증명으로 인증할 수 없다는 뜻입니다. 예상한 거부는 유출 차단의 성공입니다. 연결 오류라면 서비스에 도달하지 못한 것이므로 다른 문제입니다. 서비스를 중지하는 것은 해결이 아닙니다.

Integration 탭으로 전환합니다. 작업 프로그램을 다시 실행합니다.

다음 명령을 실행하기 전에 Integration 탭으로 전환합니다.

python3 /opt/keylab/worker.py demo
HTTP 401: {"error":"Invalid or revoked key"}

이 명령은 의도대로 실패 상태로 종료됩니다. 작업이 비공개 파일에서 폐기된 값을 읽으므로 입력을 더 이상 가져올 수 없습니다. 차단 중에는 배치가 잠시 멈춰도 됩니다. 다음 실습은 이 상태에서 작업을 복구합니다.

Workstation 탭으로 돌아갑니다. 독립 모니터를 확인합니다. 자체 자격 증명과 상태 엔드포인트를 사용합니다.

다음 명령을 실행하기 전에 Workstation 탭으로 전환합니다.

curl -s -w '\nHTTP %{http_code}\n' -H 'Authorization: Bearer lab_key_monitor_only' http://127.0.0.1:8000/v1/health
{"status":"ok","integration":"monitor"}
HTTP 200

서비스와 무관한 연동은 유지하면서 노출된 자격 증명의 접근을 제거했습니다. 차단 이후 복구까지 진행해도 되며, 유효한 복구를 수행했다고 이 실습에서 실패 처리하지 않습니다.

요약

정상 연동을 살펴보고 키 ID와 비밀값을 구분했으며, Git 이력에서 비밀값을 찾아 해당 제공자 자격 증명을 폐기했습니다. 실제 요청 거부와 독립 기능의 가용성도 테스트했습니다. 줄을 삭제하는 것으로는 키가 무효화되지 않았지만 폐기하자 무효화되었습니다. 다음 실습에서는 제한된 전용 대체 키로 작업을 복구합니다.