2017.08.10

Node.js서 악성코드 발견··· 오픈소스 신뢰 모델 '흔들'

Fahmida Y. Rashid | CSO
소프트웨어 개발은 기본적으로 신뢰를 바탕으로 한다. 특히 오픈 소스를 이용할 때는 더 그렇다. 그러나 최근 Node.js 패키지 관리 레지스트리인 npm에서 악성 패키지 39개가 발견됐다는 소식은 이러한 신뢰 모델이 얼마나 취약한지 다시 한번 일깨워줬다.



7월 19일과 7월 31일 사이에 핵태스크(hacktask)라는 이름의 계정이 기존 npm 패키지와 비슷한 이름의 일련의 패키지를 npm에 게시했다. 이 패키지는 개발자가 일반적인 기능을 구현할 때 처음부터 코드를 작성할 필요 없도록 도와준다.

문제는 잘못해서 혹은 악의적인 의도로 엉뚱한 패키지가 코드에 추가되면 응용 프로그램에 악성 코드가 생긴다는 점이다. npm의 CTO CJ 실베리오는 “이러한 패키지에는 일부러 사용자가 속기 쉬운 이름을 붙인다. 여기에 속아 넘어간 사용자로부터 유용한 정보를 빼내려는 악의적인 의도다"라고 말했다.

진화에 나선 npm은 핵태스크 계정을 폐쇄하고 해당 계정과 관련된 패키지를 모두 삭제했다. 또한 해당 사용자의 이메일 주소가 더 이상 npm을 사용할 수 없도록 했다. 실베리오는 “이메일 주소 정도는 쉽게 다른 것으로 바꿀 수 있어 완벽한 예방 조치라고 하기는 어렵지만 기본적으로 필요한 조치는 마쳤다"라고 말했다.

실제로 패키지 소유자가 비슷한 이름을 사용하는 것을 막을 방법은 없다. 단순히 이름이 비슷하다고 해서 악의적인 의도가 있다고 단정할 수도 없다. 그러나 이번 핵태스크 사례는 단순한 우연의 일치가 아니었다. 핵태스크가 게시한 패키지는 원래 패키지와 기능이 똑같을 뿐만 아니라 데이터 복사본을 다른 곳으로 전송할 수 있는 기능도 갖추고 있었다. 예를 들어, 환경 변수에 의해 저장된 정보를 제3자 서버로 전송하는 'crossenv' 패키지는 개발자가 이를 cross-env이라는 유명한 환경 변수 설정 패키지로 착각했을 가능성이 있다.

공격자와 절도범이 환경 변수를 노리는 이유는 계정 인증 정보, 타 응용 프로그램과 서비스, API에 접근할 수 있는 인증 토큰 및 키와 같은 귀중한 정보가 저장돼 있기 때문이다. 환경 변수는 보통 젠킨스(Jenkins), 트래비스씨아이(TravisCI), 팀 파운데이션 서버(Team Foundation Server), 뱀부(Bamboo) 등 지속적 통합 서버에 여러 개의 비밀 토큰을 저장한다.

npm에 악성 패키지가 추가되지 않도록 막는 검사 기능이 없다는 것은 이미 널리 알려진 사실이다. 악성 패키지는 발견되는 대로 제거되므로 공동체 차원에서 경계를 늦추지 않고 악용 사례를 신고하는 것이 중요한 이유다.

정확한 패키지가 다운로드 됐는지 패키지 이름을 확인하고 코드가 예상치 못한 행동을 하는지 점검하는 것은 개발자의 몫이다. 실제로 많은 기업이 응용 프로그램에 취약점과 악성 패키지가 없는지 검사하기 위해 블랙 덕 허브(Black Duck Hub), 스니크(Snyk) 등 소스 코드 스캐너를 이용한다. 스니크는 핵태스크 패키지 전부에 대한 탐지 기능을 자체 데이터베이스에 추가했다.

npm 측은 악성 패키지가 많이 다운로드 되지 않았다고 설명하지만, 기업 개발 팀은 핵태스크 계정에서 온 핵태스크 패키지 중 어느 하나라도 사용되고 있지는 않은지 즉시 확인해야 한다.

각 프로젝트의 종속성을 살펴보는 것만으로는 부족하다. 제3자 프로젝트를 사용하는 팀은 해당 프로젝트에도 악성 패키지가 없는지 확인해야 한다. 실제로 악성 crossenv 패키지를 사용한 일부 깃허브(GitHub) 프로젝트가 발견되기도 했다. 따라서 해당 프로젝트 이용자라면 누구나 무심코 데이터 탈취 코드를 자신의 프로그램에 추가했을 가능성이 있다. 종속성을 검사하는 여러 툴이 있지만, 명령줄, 파워셸(PowerShell) 또는 얀(Yarn)을 통해서도 핵태스크 패키지가 사용 중인지 확인할 수 있다.

종속성은 마치 몸 안에 또 다른 인형을 품고 있는 러시아 인형 '마트료시카'처럼 여러 층에 걸쳐 있다. 악성 패키지가 전부 제거되었는지 확인하려면 프로젝트와 하부 프로젝트를 일일이 파헤치는 수밖에 없다. 악성 패키지 중 어느 하나라도 발견되면 비밀 토큰이 노출됐을 가능성이 있으므로 모조리 다시 생성해야 한다.


어떤 경우에는 핵태스크 패키지가 정상적인 패키지와 이름이 같고 버전 번호만 달라서 혼란을 유발하곤 한다. 따라서 잠재적인 악성 패키지를 탐색할 때에는 버전 번호와 패키지 출처를 모두 확인해야 한다. 예를 들면, mysql.js, nodesqlite, mariadb와 같은 이름으로 Node.js 데이터베이스 패키지를 가장한 여러 개의 패키지가 발견됐는데, 버전 번호는 실제 패키지와 달랐다.

현재 탐지 가능한 악성 패키지는 이미 게시된 것으로 한정되지만, 개발자는 패키지 범위(@범위/패키지-이름)를 이용해 사용자가 엉뚱한 패키지에 속는 일을 방지할 수 있다. 사용자가 실수로 엉뚱한 패키지를 설치할 확률을 낮춰 주는 기능이다. 이렇게 하면 패키지 이름 뿐만 아니라 범위 이름까지 모두 잘못된 철자가 입력돼야만 엉뚱한 패키지가 설치된다.

Node.js 개발자 이반 아쿨로프는 개발자에게 자신만의 타이포스쿼팅(typo-squatting)을 권고했다. 패키지 이름의 흔한 오타 이름까지 직접 사용해 악용의 여지를 막는 방법이다. 그는 "이러한 오타 이름으로 빈 패키지를 게시한 후 사용자에게 올바른 이름과 더 이상 사용되지 않는 npm 명령어를 알려주면 사용자가 엉뚱한 패키지에 속는 일도 줄어들 것이다"라고 말했다.

라이브러리 형태나 다른 소스로부터 복사해 붙여 넣은 코드 블록인 제3자 코드가 예상치 못한 행위나 해로운 행위를 하지 않도록 확인하는 것도 중요하다. 그러나 코드 저장소 또한 패키지 이름이 너무 비슷한 타이포스쿼팅 사례와 기타 악의적인 시도를 구별하는 방법을 찾아야 한다. npm 레지스트리에는 README 파일에 스팸 메시지가 포함된 패키지가 올라오기도 했는데 npm은 이를 탐지해 제거하기 위해 보안회사 스마이트(Smyte)와 협력 중이다. 악성 패키지 탐지를 위한 다른 프로젝트도 진행 중이지만 아직은 초기 단계이다.

^리프트 시큐리티(^Lift Security)의 애덤 볼드윈은 핵태스크의 소유가 아닌 패키지에 악성 코드가 추가됐을 가능성 때문에 공용 레지스트리에 있는 다른 모든 패키지를 검사했다. crossenv 패키지의 데이터 전송 스크립트를 사용하는 다른 패키지를 찾기 위해서다, 현재 핵태스크의 소유가 아닌 패키지 중에서 이런 악성 스크립트를 포함한 패키지는 없는 것으로 확인됐다.

실베리오는 “우리는 ^리프트 시큐리티와 노드 시큐리티 프로젝트(Node Security Project)에서 진행 중인 공용 레지스트리 패키지 정적 분석을 지원하고 있다. 그러나 이를 통해 모든 문제를 발견할 수 있는 것은 아니다"라고 말했다. ciokr@idg.co.kr 
2017.08.10

Node.js서 악성코드 발견··· 오픈소스 신뢰 모델 '흔들'

Fahmida Y. Rashid | CSO
소프트웨어 개발은 기본적으로 신뢰를 바탕으로 한다. 특히 오픈 소스를 이용할 때는 더 그렇다. 그러나 최근 Node.js 패키지 관리 레지스트리인 npm에서 악성 패키지 39개가 발견됐다는 소식은 이러한 신뢰 모델이 얼마나 취약한지 다시 한번 일깨워줬다.



7월 19일과 7월 31일 사이에 핵태스크(hacktask)라는 이름의 계정이 기존 npm 패키지와 비슷한 이름의 일련의 패키지를 npm에 게시했다. 이 패키지는 개발자가 일반적인 기능을 구현할 때 처음부터 코드를 작성할 필요 없도록 도와준다.

문제는 잘못해서 혹은 악의적인 의도로 엉뚱한 패키지가 코드에 추가되면 응용 프로그램에 악성 코드가 생긴다는 점이다. npm의 CTO CJ 실베리오는 “이러한 패키지에는 일부러 사용자가 속기 쉬운 이름을 붙인다. 여기에 속아 넘어간 사용자로부터 유용한 정보를 빼내려는 악의적인 의도다"라고 말했다.

진화에 나선 npm은 핵태스크 계정을 폐쇄하고 해당 계정과 관련된 패키지를 모두 삭제했다. 또한 해당 사용자의 이메일 주소가 더 이상 npm을 사용할 수 없도록 했다. 실베리오는 “이메일 주소 정도는 쉽게 다른 것으로 바꿀 수 있어 완벽한 예방 조치라고 하기는 어렵지만 기본적으로 필요한 조치는 마쳤다"라고 말했다.

실제로 패키지 소유자가 비슷한 이름을 사용하는 것을 막을 방법은 없다. 단순히 이름이 비슷하다고 해서 악의적인 의도가 있다고 단정할 수도 없다. 그러나 이번 핵태스크 사례는 단순한 우연의 일치가 아니었다. 핵태스크가 게시한 패키지는 원래 패키지와 기능이 똑같을 뿐만 아니라 데이터 복사본을 다른 곳으로 전송할 수 있는 기능도 갖추고 있었다. 예를 들어, 환경 변수에 의해 저장된 정보를 제3자 서버로 전송하는 'crossenv' 패키지는 개발자가 이를 cross-env이라는 유명한 환경 변수 설정 패키지로 착각했을 가능성이 있다.

공격자와 절도범이 환경 변수를 노리는 이유는 계정 인증 정보, 타 응용 프로그램과 서비스, API에 접근할 수 있는 인증 토큰 및 키와 같은 귀중한 정보가 저장돼 있기 때문이다. 환경 변수는 보통 젠킨스(Jenkins), 트래비스씨아이(TravisCI), 팀 파운데이션 서버(Team Foundation Server), 뱀부(Bamboo) 등 지속적 통합 서버에 여러 개의 비밀 토큰을 저장한다.

npm에 악성 패키지가 추가되지 않도록 막는 검사 기능이 없다는 것은 이미 널리 알려진 사실이다. 악성 패키지는 발견되는 대로 제거되므로 공동체 차원에서 경계를 늦추지 않고 악용 사례를 신고하는 것이 중요한 이유다.

정확한 패키지가 다운로드 됐는지 패키지 이름을 확인하고 코드가 예상치 못한 행동을 하는지 점검하는 것은 개발자의 몫이다. 실제로 많은 기업이 응용 프로그램에 취약점과 악성 패키지가 없는지 검사하기 위해 블랙 덕 허브(Black Duck Hub), 스니크(Snyk) 등 소스 코드 스캐너를 이용한다. 스니크는 핵태스크 패키지 전부에 대한 탐지 기능을 자체 데이터베이스에 추가했다.

npm 측은 악성 패키지가 많이 다운로드 되지 않았다고 설명하지만, 기업 개발 팀은 핵태스크 계정에서 온 핵태스크 패키지 중 어느 하나라도 사용되고 있지는 않은지 즉시 확인해야 한다.

각 프로젝트의 종속성을 살펴보는 것만으로는 부족하다. 제3자 프로젝트를 사용하는 팀은 해당 프로젝트에도 악성 패키지가 없는지 확인해야 한다. 실제로 악성 crossenv 패키지를 사용한 일부 깃허브(GitHub) 프로젝트가 발견되기도 했다. 따라서 해당 프로젝트 이용자라면 누구나 무심코 데이터 탈취 코드를 자신의 프로그램에 추가했을 가능성이 있다. 종속성을 검사하는 여러 툴이 있지만, 명령줄, 파워셸(PowerShell) 또는 얀(Yarn)을 통해서도 핵태스크 패키지가 사용 중인지 확인할 수 있다.

종속성은 마치 몸 안에 또 다른 인형을 품고 있는 러시아 인형 '마트료시카'처럼 여러 층에 걸쳐 있다. 악성 패키지가 전부 제거되었는지 확인하려면 프로젝트와 하부 프로젝트를 일일이 파헤치는 수밖에 없다. 악성 패키지 중 어느 하나라도 발견되면 비밀 토큰이 노출됐을 가능성이 있으므로 모조리 다시 생성해야 한다.


어떤 경우에는 핵태스크 패키지가 정상적인 패키지와 이름이 같고 버전 번호만 달라서 혼란을 유발하곤 한다. 따라서 잠재적인 악성 패키지를 탐색할 때에는 버전 번호와 패키지 출처를 모두 확인해야 한다. 예를 들면, mysql.js, nodesqlite, mariadb와 같은 이름으로 Node.js 데이터베이스 패키지를 가장한 여러 개의 패키지가 발견됐는데, 버전 번호는 실제 패키지와 달랐다.

현재 탐지 가능한 악성 패키지는 이미 게시된 것으로 한정되지만, 개발자는 패키지 범위(@범위/패키지-이름)를 이용해 사용자가 엉뚱한 패키지에 속는 일을 방지할 수 있다. 사용자가 실수로 엉뚱한 패키지를 설치할 확률을 낮춰 주는 기능이다. 이렇게 하면 패키지 이름 뿐만 아니라 범위 이름까지 모두 잘못된 철자가 입력돼야만 엉뚱한 패키지가 설치된다.

Node.js 개발자 이반 아쿨로프는 개발자에게 자신만의 타이포스쿼팅(typo-squatting)을 권고했다. 패키지 이름의 흔한 오타 이름까지 직접 사용해 악용의 여지를 막는 방법이다. 그는 "이러한 오타 이름으로 빈 패키지를 게시한 후 사용자에게 올바른 이름과 더 이상 사용되지 않는 npm 명령어를 알려주면 사용자가 엉뚱한 패키지에 속는 일도 줄어들 것이다"라고 말했다.

라이브러리 형태나 다른 소스로부터 복사해 붙여 넣은 코드 블록인 제3자 코드가 예상치 못한 행위나 해로운 행위를 하지 않도록 확인하는 것도 중요하다. 그러나 코드 저장소 또한 패키지 이름이 너무 비슷한 타이포스쿼팅 사례와 기타 악의적인 시도를 구별하는 방법을 찾아야 한다. npm 레지스트리에는 README 파일에 스팸 메시지가 포함된 패키지가 올라오기도 했는데 npm은 이를 탐지해 제거하기 위해 보안회사 스마이트(Smyte)와 협력 중이다. 악성 패키지 탐지를 위한 다른 프로젝트도 진행 중이지만 아직은 초기 단계이다.

^리프트 시큐리티(^Lift Security)의 애덤 볼드윈은 핵태스크의 소유가 아닌 패키지에 악성 코드가 추가됐을 가능성 때문에 공용 레지스트리에 있는 다른 모든 패키지를 검사했다. crossenv 패키지의 데이터 전송 스크립트를 사용하는 다른 패키지를 찾기 위해서다, 현재 핵태스크의 소유가 아닌 패키지 중에서 이런 악성 스크립트를 포함한 패키지는 없는 것으로 확인됐다.

실베리오는 “우리는 ^리프트 시큐리티와 노드 시큐리티 프로젝트(Node Security Project)에서 진행 중인 공용 레지스트리 패키지 정적 분석을 지원하고 있다. 그러나 이를 통해 모든 문제를 발견할 수 있는 것은 아니다"라고 말했다. ciokr@idg.co.kr 
X