프로덕션 VPS의 침해

발행: (2025년 12월 11일 오전 04:41 GMT+9)
10 min read
원문: Dev.to

Source: Dev.to

초기 증상

보안 사고는 종종 조용히 찾아와 경고음이나 극적인 알림 없이 발생합니다. 우리는 주말이든, 다운타임이든, 혹은 일상적인 감시가 조금 흐트러질 때조차도 예상치 못한 순간에 프로덕션 환경에 침투합니다.

조용한 일요일 저녁, 뭔가 확인하려고 프로덕션 앱을 열었지만 로드되지 않았습니다. 오류 페이지도, 타임아웃도 없고, 단지 스플래시 화면만 보이는 빈 화면이었습니다. 일시적인 문제라고 생각하고 VPS에 SSH를 시도했지만 연결이 계속 타임아웃되어 청구서 연체로 인한 셧다운이라고 추측했습니다.

몇 차례 시도 끝에 SSH 프롬프트가 드디어 나타났지만, 머신은 유난히 느렸습니다. ls 같은 간단한 명령조차 3~4초가 걸렸습니다.

첫 번째 조사

로그인하자마자 시스템이 고통스럽게 느려졌습니다. 저는 다음을 실행했습니다:

top

그리고 /usr/bin/rsyslo에 위치한 rysyslo 라는 프로세스가 대략 80 % CPU, 상당량의 RAM, 그리고 거의 모든 디스크 공간을 차지하고 있는 것을 보았습니다. Ubuntu는 이런 바이너리를 제공하지 않으며, 빠른 검색 결과 악성 코드임이 확인되었습니다. 서버가 침해된 것입니다.

의심스러운 바이너리를 삭제하고, 익숙하지 않은 서비스를 제거했으며, 악성 프로세스를 종료했습니다. 부하가 감소하고 시스템이 정상적으로 동작했지만, 이러한 간단한 조치만으로는 침해가 완전히 사라지지 않을 수 있다는 점을 알고 있었습니다.

악화

다음 날 아침에도 앱은 여전히 접근이 불가능했고, SSH는 몇 분씩 연결을 거부하며 불안정했습니다. 결국 접근을 회복했을 때 top은 다음을 보여주었습니다:

  • xmrig – 악명 높은 암호화폐 채굴 도구
  • 무작위 이름을 가진 여러 위장 바이너리
  • 시스템 프로세스를 가장한 가짜 커널 스레드
  • 메모리를 잡아먹는 monarx-agent 라는 미스터리 프로그램
  • 내가 실행하지 않은 Node 프로세스

이 프로세스들을 종료해도 효과가 없었습니다; 공격자는 영구성을 확보해 두었습니다.

영구성 메커니즘

악성 서비스를 스캔한 결과 두 개의 systemd 유닛을 발견했습니다:

  • alive.service
  • lived.service

두 유닛 모두 다음 경로의 스크립트를 가리키고 있었습니다:

/tmp/runnv/alive.sh
/tmp/runnv/lived.sh

유닛 파일 내용은 다음과 같습니다:

Restart=always
RestartSec=5s

이 스크립트들은 지속적으로 채굴기를 다운로드·복구·재시작했으며, 삭제 후 몇 초 만에 다시 나타났습니다. 따라서 모든 종료나 삭제가 금세 무력화되었습니다.

영향 및 데이터 백업

시간이 지나면서 VPS는 점점 더 불안정해졌습니다:

  • SSH가 반복적으로 멈추거나 끊김
  • 시스템 작업이 끔찍하게 느려짐
  • 메모리 사용량이 예측 불가능하게 급증
  • 로그에 이상 징후가 나타남
  • 제거해도 monarx-agent 가 다시 나타남

루트 권한 수준의 침투가 이루어진 상황에서 운영체제 자체를 신뢰할 수 없게 되었습니다. 저는 머신이 완전히 사용할 수 없게 되기 전에 중요한 데이터를 추출하는 것이 최우선 과제가 되었습니다.

백업 절차

다음 항목들을 체계적으로 백업했습니다:

  • PostgreSQL 데이터베이스 덤프 (pg_dump)
  • 애플리케이션 서버 파일
  • 미디어 디렉터리
  • 설정 파일
  • 사용자 업로드 파일
  • 필수 환경 변수
  • 리버스 프록시 설정
  • 추후 분석을 위한 로그

시스템이 거의 응답하지 않았기 때문에, 간헐적인 연결 끊김을 처리하도록 만든 커스텀 스크립트를 이용해 SSH 기반 rsync를 사용했습니다. 결국 모든 핵심 자산을 안전하게 백업하고 검증할 수 있었습니다.

서비스 종료 결정

데이터 무결성을 확인한 뒤, 애플리케이션 데이터 자체는 손상되지 않았음을 발견했습니다—공격자는 단지 암호화폐를 채굴하려고 했을 뿐이었습니다. 저는 침해된 VPS를 영구적으로 종료하고 새 인스턴스로 마이그레이션하기로 결정했습니다. 시스템은 복구가 불가능한 상태였습니다.

근본 원인 분석

다음과 같은 포렌식 데이터를 검토했습니다:

  • /var/log/auth.log
  • SSH 접근 시도 기록
  • systemd 유닛 파일 타임스탬프
  • 루트 수준 프로세스 생성 로그
  • 크론 작업
  • 알 수 없는 스크립트 출처
  • 익숙하지 않은 실행 파일
  • 열려 있는 포트 (netstat/ss)
  • /usr/bin, /tmp, /dev/shm, /usr/share/updater 에 존재하는 바이너리

로그에는 거부된 SSH 시도만 있었고, 키 유출이나 직접적인 무차별 대입 성공 증거는 없었습니다. 가장 가능성 높은 진입점은 최근 공개된 React2Shell 취약점 (CVE‑2025‑55182) 으로, 잘못 구성된 환경에서 원격 코드 실행을 가능하게 합니다. Nginx 접근 로그에는 여러 엔드포인트에 강제 POST 요청이 기록돼 있어 공격자가 취약한 웹 라우트를 이용했음을 시사합니다.

또한 해당 VPS는 방화벽이 전혀 설정되지 않은 개방형 네트워크 구성을 가지고 있었으며, 이는 클라우드 플랫폼의 엄격한 보안 그룹에 비해 공격 표면을 크게 확대했습니다.

교훈

  • 절대 애플리케이션을 루트 권한으로 실행하지 말 것. 비특권 서비스(예: PostgreSQL)는 전용 사용자로 실행되므로 안전합니다.
  • 보안 패치를 신속히 적용할 것, 특히 CVE‑2025‑55182와 같은 최신 취약점은 즉시 업데이트해야 합니다.
  • 방화벽이나 보안 그룹으로 네트워크 노출을 제한하고, 사용하지 않는 포트는 차단할 것.
  • CPU, 메모리, 디스크 사용량 이상 징후에 대한 모니터링 및 알림을 적절히 구현할 것.
  • 불변 인프라를 활용해 검증된 이미지로 서버를 재구성하고, 깊은 청소보다는 재배포를 선택할 것.
  • 중요 데이터는 정기적으로 백업하고 복구 절차를 테스트할 것.

이번 사건은 제가 다시는 무시하지 않을 원칙을 확고히 했습니다: 절대 애플리케이션을 루트 권한으로 실행하지 말 것.

Back to Blog

관련 글

더 보기 »

현실이 사라질 때

2024년 12월, 페이‑페이 리는 가득 찬 스탠포드 강당에 낡은 엽서를 들어 보였다—반 고흐의 *The Starry Night*는 세월에 따라 색이 바래고 주름이 잡혀 있었다. 그녀는 그것을…

알고 계셨나요? (Part 3)

Google Cloud Shell을 환경으로 사용하여 코딩할 수 있습니다! JavaScript, .NET 등 다양한 도구가 포함되어 있습니다. 무엇보다도, 설치할 수 있습니다.