본문 바로가기
Python/pypi

pypi / pip / 파이썬 패키지 해킹 악성코드

by ahsung 2023. 5. 1.

pypi(pip), npm 과 같은 방대한 오픈소스 패키지 저장소의 안전성에 대해서 생각은 해봤지만 깊게 고민해보지는 않고 살던 찰나

유튜브 알고리즘에 관련 영상을 보고 머리속으로만 생각하던 일들을 실천해야겠다고 생각들었다..

> 본 포스팅은 python 생태계에 대해서만 자세하게 다룹니다. (npm은 몰라여~)

유튭 출처: https://www.youtube.com/watch?v=DjfpcmK62ew 

 

 

요약

해당 영상은 pypi(pip), npm 과 같은 방대한 오픈소스 패키지 생태계에서 악의적인 코드 혹은 의존성으로 생기는 문제들을 이야기하고 있다. 

 

## Left-pad 

- 11줄의 코드로 구성된, 텍스트 문자의 왼쪽에 패딩을 넣어주는 패키지

- 수 많은 패키지들이 left-pad를 사용하고 있었고, 어느날 left-pad가 npm에서 비공개로 변경된 후 끔찍한 사태가..

(추가 배포, 설치시 수 많은 패키지들의 깨지는 현상이 발생했을 것)

 

## Typosquatting attack

- 유명한 패키지의 이름과 유사한 악성코드 패키지를 공식 저장소(pypi, npm)에 업로드

 

 

고찰

영상에서는 위 2가지 외에도 다양한 사례에 대해서 설명하고 있다.

결국 문제의 원인은 수 많은 사람들이 공식 패키지 저장소에 자유롭게 업로드, 다운로드를 수행할 수 있고 타사 라이브러리에 많은 의존성을 띄는 생태계 환경이다.


파이썬의 경우 PSRT(Python Security Response Team)에서 파이썬 생태계의 보안을 지키기 위한 다양한 활동을 하고 있으나

특정 단체나 기관에서 pypi의 모든 패키지의 안정성을 책임지는 형태가 아니기 때문에, 이미 발생한 문제에 대해서는 결국 다운로드하고 사용한 당사자에게 책임이 전가된다. 

-

더보기
생각해보면 파이썬과 자바스크립트가 아닌 다른 언어들은 이토록 오픈소스 라이브러리의 사용이 쉽고 자유롭지 않다.
자바, C/C++로 개발할 당시만 생각해봐도 pypi와 같이 단일화된 공용 저장소가 있지도 않고 간편한 패키지 매니저도 없고, 보통은 공식사이트에서 SDK, API 라이브러리를 다운받아 함께 빌드한다. 
물론 자바의 경우 안드로이드를 생각해보면 build시 특정 url을 지정해서 google이나 기타 신뢰도 높은 곳으로부터 쉽게 다운받을 수 있다.
하지만 중요한건 이런 언어들 대부분이 사용화 단계로 갈 때, 공식적이고 안전한 라이브러리가 아니라면 직접 구현하는 경우가 많다.
- 경험상 best practice를 서칭하고 참고해서 개발했던적이 자주 있던 것 같다

파이썬, 자바 스크립트의 경우 수 많은 오픈소스 패키지로 엄청난 개발 속도 이점을 가질 수 있지만 양날의 검과 같은 위험을 조심해야한다.

 

 

그렇다면, 안전하게 파이썬 패키지를 사용하는 방법은 뭐가 있을까?

1. 위 영상에서는 docker와 같은 분리된 환경을 통한 개발을 추천한다.

- 대부분의 악성 패키지들은 개인정보 탈취등이 목적이기 때문에 컨테이너로 분리할 경우 개인 filesystem의 접근을 방지할 수 있다.

 

2. 여러 커뮤니티에서 이미 사용/검증된 패키지(버전 고정) 위주로 사용한다.

- pypi는 한 번 업로드된 (이름 + 버전)은 완전 고정되어 다시 업로드 할 수 없다. (삭제후 재업로드도 안된다.)
- requirements.txt에는 반드시 정상적으로 사용됬던 버전을 static하게 명시한다.
- 개인이 관리하는 프로젝트라도 한 번 이슈가 없었던 버전을 계속 쓴다면 악의적인 공격은 회피할 수 있다.
- https://github.com/pypa/packaging-problems/issues/74
- left-pad 같은 문제는 피할 수 없겠지..

 

 

파이썬으로 상용 애플리케이션을 배포할 때, 안전하게 패키지를 관리할 수 있는 방법은 뭐가 있을까?

이제부터 알아가야된다 ㅎㅎ..

안타깝게도 1시간정도 서핑해봤을 때, 정형화된 안전한 방식은 존재하지 않았고 일단 개인적인 고민에 의거한 내용을 끄적여보고

(나중에 시간 남을 때 더 리서치해보겠다아~)

 

1. 개인이 아닌 신뢰도가 높은 단체나 기관이 인증한 혹은 관리하는 패키지만 사용한다.

예로 파이썬에서 가장 흔하게 사용하는 http 라이브러리 "requests"는 파이썬 재단에서 공식 스폰을 받고 있다.

- https://github.com/psf/requests

 

GitHub - psf/requests: A simple, yet elegant, HTTP library.

A simple, yet elegant, HTTP library. Contribute to psf/requests development by creating an account on GitHub.

github.com

- 그외 django, flask, fastapi, pydantic, sqlalchemy 등등 "개인"이 아닌 신뢰도가 충분한 특정 단체, 기관에서 관리중인 패키지들이 있다.

- 높은 신뢰도는 수 많은 사람들이 얼만큼 사용하는가와 커뮤니티, 사이트의 소개와 스폰중인 재단등으로 확인 할 수 있다.

- 최대한 "개인" 관리자인 pypi 패키지는 상용 앱에는 사용하지 않는다.

 

2. 직접 개발해서 사용한다.

- 단순 명료하다. 직접 개발해서 사용하면 문제가 없다.

django와 같은 프로젝트를 보면, 이미 비슷한 기능을 수행하는 수많은 라이브러리들이 많으나 django안에서 중복으로 구현된 사이드 라이브러리들이 많다. 왜일까? 

django는 상용 웹 애플리케이션을 위한 프레임워크를 지향하고 있다. 당연 타사 라이브러리와의 의존성을 지양하는게 아닐까 개인적으로 생각해본다.

- ex) django의 DB 라이브러리 https://docs.djangoproject.com/en/4.2/topics/db/

 

Django

The web framework for perfectionists with deadlines.

docs.djangoproject.com

 

 

그리고, 간혹 flask={???}, fastapi-{???} 와 같은 이름을 가진 extension 성격의 패키지들을 흔히 볼 수 있는데 "개인"이 관리하는 프로젝트인 경우도 많다.

물론 스폰서도 달려있고 스타도 빵빵하다면, requirement 파일에 버전을 고정해서 사용할 수는 있겠지만 상용앱에서 사용하기 찝찝하다면 직접 개발해서 사용하는 것도 나쁘지 않다.

 

직접 개발하게될 경우,  컴파일러(java와 같은 그에 준하는) 언어들의 생태계와 크게 다를 것 없을 수도 있지만

pypi가 오픈소스 패키지를 먼저 사용해보고 코드를 참고하여 직접 개발하는 것 자체도 엄청난 효율을 가져온다고 생각한다.

물론, 이 경우 라이선스를 준수해야 될 수 있다. ( 도덕적으로! 법적인 문제 없게!)

- https://integrity.mit.edu/handbook/writing-code

 

Writing Code | Academic Integrity at MIT

Writing code is similar to academic writing in that when you use or adapt code developed by someone else as part of your project, you must cite your source. However, instead of quoting or paraphrasing a source, you include an inline comment in the code. T

integrity.mit.edu

 

 

3. Custom pypi 저장소를 구축한다.

극한의 안정성을 이끌고 싶다면, 직접 pypi 저장소를 구축하고 사용하는 것이다.

1,2번과 안전하다고 판단된 패키지들만 직접 구축한 pypi 저장소에 업로드하고 사용하는 것! 

 

회사가 상용 애플리케이션의 많은 부분을 파이썬으로 구축한다면 괜찮은 방법이라고 생각한다.

( pip의 -i, --trusted-host 옵션으로 커스텀 pypi 저장소를 지정하여 다운로드 할 수 있다.)

 

 

 

댓글