2026년 9월 22일, ThreatDown 연구자들은 CARBONATO 봇넷을 설명했습니다. 이 봇넷은 비밀번호 없이 열린 Docker API를 통해 서버에 접근하여 호스트에서 AI 에이전트를 실행하고, 가장 먼저 언어 모델의 키를 찾습니다. SSH 키와 액세스 토큰은 그 다음입니다. VPS에서 컨테이너에서 파서가 실행되고 .env 파일에 OpenRouter 또는 OpenAI 키와 프록시 로그인 정보가 있다면, 이는 귀하의 위험 프로필입니다. 아래는 공격 방식에 대한 분석과 이 접근을 차단하는 15분 체크리스트입니다.
발견된 내용: 4.3GB의 이미지와 GH0ST라는 이름의 에이전트
모든 것은 운영자들이 닫지 않은 Docker 레지스트리에서 시작되었습니다. ThreatDown에 따르면, 이 레지스트리에는 59개의 리포지토리, 234개의 이미지 태그 및 4.3GB의 데이터가 포함되어 있었습니다. 이 아카이브는 2024년 10월부터 2026년 8월까지의 기간을 포함하며, 즉 봇넷은 설명되기 전 거의 2년 동안 작동했습니다. 리포지토리에는 XMRig 마이너와 fsociety/agent와 같은 이름의 이미지가 발견되었습니다.
보고서에 따르면 감염 체인은 다음과 같습니다:
- 스캐너는 Docker API가 TCP 2375에서 인증 없이 열려 있는 호스트를 찾습니다.
- 이 API를 통해 웜은 특권 컨테이너를 시작하고 호스트의 파일 시스템을 마운트합니다. 이 시점부터 그는 사실상 머신의 root 권한을 가집니다.
- 운영자의 인프라로의 역 SSH 터널이 설정되고, 그들의 키로 SSH 서버가 설치됩니다.
- 고정은 cron, systemd 타이머, rc.local 및 OpenRC를 통해 이루어지며, 파일은 변경 불가능한 것으로 표시됩니다. 감시 프로세스는 무언가를 삭제하면 이미지를 다시 다운로드합니다.
- 컨테이너는
systemd-resolved로 위장하고, 프로세스는 커널 스레드[kworker/u2:0]로 위장합니다. - 매 5분마다 스크립트는 이웃 서브넷 /24와 Docker 브리지에서 다음 열린 포트 2375를 찾습니다.
전파는 완전히 자동화되어 있으며 AI에 의존하지 않습니다. AI는 이미 점령된 서버 내에서 발생하는 일에 대한 책임이 있습니다.
봇넷에 AI 에이전트가 필요한 이유와 LLM 키가 필요한 이유
호스트에 Hermes Agent라는 공개 프레임워크가 GH0ST라는 페르소나와 함께 설치됩니다(그의 지침은 SOUL.md 파일에 있습니다). 운영자는 Telegram에 작업을 작성하고, 에이전트는 이를 LLM 작업 게이트웨이에 지침과 함께 전달합니다. 모델은 작업을 분석하고, 터미널 명령을 작성하고, 출력을 읽고, 다음에 무엇을 할지 결정합니다. 결과는 다시 Telegram으로 전송됩니다.
에이전트의 지침에는 우선 순위가 명시되어 있습니다. ThreatDown은 다음과 같이 인용합니다: “AI API 키는 절대적인 우선 순위입니다. 먼저 유출하십시오”. 목록에는 OpenAI, Anthropic, Google, Groq, Mistral 및 OpenRouter를 포함한 14개의 모델 제공자가 있습니다. SSH 계정, 액세스 토큰 및 데이터베이스 정보는 다음 항목에 나열됩니다.
논리는 간단합니다: 도난당한 LLM 키는 즉시 무료 계산 또는 재판매할 상품으로 변환되며, 그 비용은 키 소유자가 지불합니다. 마이닝과는 달리, 이러한 도난은 CPU 부하로는 보이지 않습니다. 모델 제공자로부터의 청구서로만 알 수 있습니다.
왜 이것이 파서를 사용하는 사람들에게 중요한가
2026년의 전형적인 파싱 스택은 다음과 같습니다: VPS, 여러 컨테이너(크롤러, 큐, 데이터베이스, 헤드리스 브라우저), 페이지 분석을 위한 LLM 및 프록시 풀. 모든 비밀은 하나의 .env 파일이나 컨테이너의 환경 변수에 저장됩니다. 루트 접근 권한으로 “모든 것을 읽는” 에이전트에게는 하나의 파일로 준비된 먹잇감입니다:
- LLM 키: 이를 위해 CARBONATO가 만들어졌습니다;
- 프록시 로그인 및 비밀번호: 보고서에서는 별도로 언급하지 않지만, 루트 접근 권한이 있는 에이전트는 보는 모든 계정과 토큰을 수집하며, 프록시 크레딧은 일반적으로 근처에 있습니다;
- 클라우드 키 및 파싱 결과에 대한 데이터베이스 접근;
- 서버 자체: 동일한 아카이브에 있는 XMRig는 귀하의 크롤러 CPU가 마이닝에 사용될 것임을 의미하며, 작업은 타임아웃으로 인해 실패하기 시작합니다.
명성에 대한 별도의 문제가 있습니다. 웜이 다른 서브넷을 스캔하는 서버는 빠르게 남용 목록에 올라가며, 호스팅 제공자는 불만에 따라 이를 차단할 수 있습니다. 파싱의 경우 이는 이중 타격입니다: 서버의 IP가 표시되고, 도난당한 프록시 크레딧이 이미 귀하의 트래픽을 타인의 요청으로 소모하고 있습니다.
어떻게 포트 2375가 열리게 되었는가, 비록 당신이 그것을 열지 않았더라도
기본적으로 Docker는 로컬 UNIX 소켓을 듣고 있으며, 네트워크를 듣지 않습니다. 포트 2375는 누군가가 의도적으로 -H tcp://0.0.0.0:2375를 데몬 구성에 추가했을 때 나타납니다. 일반적으로 원격 IDE, CI 또는 컨테이너 관리 패널을 연결하기 위해 이렇게 하며, 이후 이를 잊어버립니다. Docker 문서는 데몬에 대한 접근이 머신에 대한 root 접근과 같다고 경고하며, 이를 root 비밀번호처럼 보호할 것을 권장합니다. TLS를 사용하는 암호화된 버전은 포트 2376에서 작동하며, 2375는 클라이언트 검증 없이 평문을 의미합니다.
두 번째 함정은 “내가 ufw가 있으니 괜찮아”라고 확신하는 사람들을 노립니다. Docker 문서에 따르면, 공개된 컨테이너 포트의 트래픽은 nat 테이블에서 INPUT 및 OUTPUT 체인에 도달하기 전에 리디렉션됩니다. 실제로는 이러한 포트에 대한 ufw 규칙이 작동하지 않습니다. Redis, 큐 패널 또는 -p 6379:6379로 프록시 관리자를 실행했다면, 포트는 인터넷에 노출되며 ufw status가 보여주는 것과는 관계없이 그렇습니다.
파서를 위한 15분 체크리스트
1. Docker API가 네트워크를 듣고 있지 않은지 확인하십시오
- 열려 있는 포트를 확인하십시오:
ss -tlnp | grep -E '2375|2376|dockerd'. 출력에0.0.0.0:2375또는:::2375가 있다면 즉시 닫으십시오. - 플래그가 어디서 왔는지 확인하십시오:
/etc/docker/daemon.json(키"hosts") 및 유닛systemctl cat docker(행ExecStart에-H tcp://가 포함되어 있습니다). - TCP 리스너를 제거하고 데몬을 재시작하십시오. 원격 관리를 위해서는 SSH 컨텍스트를 사용하십시오:
docker context create remote --docker host=ssh://user@server. 이 경우 외부 포트는 전혀 필요하지 않습니다. - TCP가 여전히 필요하다면 (CI, 오케스트레이터), 오직 2376만 사용하고 상호 TLS 인증 및 출처 IP의 화이트리스트를 설정하십시오.
2. 컨테이너에서 외부로 노출된 것이 있는지 확인하십시오
docker ps --format '{{.Names}} {{.Ports}}'를 실행하십시오.0.0.0.0:로 시작하는 모든 것은 ufw를 우회하여 인터넷에서 접근 가능합니다.- 서비스용 서비스(Redis, Postgres, Mongo, 큐 패널, Selenium Grid, API 프록시 관리자)는 로컬 주소에만 게시하십시오:
-p 127.0.0.1:6379:6379. 외부 접근은 SSH 터널을 통해 하십시오. - 외부 포트를 피할 수 없다면,
DOCKER-USER체인에서 필터링하십시오: Docker는 이를 덮어쓰지 않으며, 이는 컨테이너 트래픽에 적용됩니다. - 인증 없이 열린 프록시를 서버에 두지 마십시오 (3128의 Squid, “자신을 위한” 1080의 SOCKS). 스캐너는 정기적으로 이러한 포트를 찾아내며, 귀하의 IP를 통해 타인의 트래픽이 흐르고 불만이 제기됩니다.
3. 비밀을 정리하십시오
- 키를 분리하십시오: 각 서버 또는 프로젝트에 대해 별도의 LLM 키를 사용하고, 모델 제공자에게 비용 한도를 설정하십시오. $20의 한도가 있는 도난당한 키는 불편함이지만, 한도가 없는 경우는 예산의 구멍이 됩니다.
- 프록시 키도 작업에 따라 분리하십시오: 각 파서에 대해 별도의 로그인(서브 계정)을 사용하십시오. 그러면 특정 로그인의 소비를 통해 유출을 확인할 수 있으며, 나머지 작업을 중단하지 않고도 해당 로그인만 철회할 수 있습니다.
- 서비스에 20개의 키 중 두 개만 필요한 경우 전체
.env를env_file을 통해 컨테이너에 전달하지 마십시오. - 가능한 경우 서버 IP에 대한 접근을 연결하십시오: 프록시 제공자의 화이트리스트 또는 API 키를 주소로 제한하십시오.
프록시 로그인 정보를 스크립트와 컨테이너에 어떻게 저장할지에 대한 자세한 내용은 프록시 자격 증명의 안전한 저장 분석에서 다루었습니다.
4. 불필요한 권한을 제거하십시오
--privileged로 컨테이너를 실행하지 말고, 극단적인 필요가 없는 한/또는/var/run/docker.sock을 내부에 마운트하지 마십시오. 컨테이너 내부의 소켓은 호스트의 root와 동일합니다.- 헤드리스 브라우저의 경우 일반적으로
--shm-size와 seccomp 프로필로 충분합니다. “Chrome이 작동하도록 하기 위해” 특권 모드를 사용하는 것은 나쁜 타협입니다.
이미 감염되었는지 확인하는 방법
ThreatDown과 그의 보고서 분석에서는 다음과 같은 침해 징후를 제시합니다:
SOUL.md파일에 GH0ST라는 단어가 포함되어 있습니다 (예:/root/.hermes/SOUL.md);- 환경 변수 또는
.env의 행:CARBONATO_API_KEY; /usr/local/bin/.docker-network-monitor및 의심스러운/usr/sbin/systemd-logind파일;- 이름이
systemd-resolved인 컨테이너 (실제 systemd-resolved는 호스트의 서비스이지 컨테이너가 아닙니다); - Telegram API로의 예상치 못한 아웃바운드 트래픽 및 AS262145 방향으로의 역 SSH 터널;
- 주소 45.79.183.61, 213.136.79.115, 190.211.124.187와의 연결;
- cron 및 systemd에서 변경 불가능한 파일:
lsattr /etc/cron.d/* /etc/systemd/system/*는i플래그를 보여줍니다.
하나라도 징후가 일치하면, 서버를 수동으로 정리하는 것은 의미가 없습니다: 고정이 다층적이므로 감시자가 임플란트를 되돌려 놓을 것입니다. 올바른 순서는 다음과 같습니다:
- 다른 머신에서 서버에 있던 모든 키를 철회하십시오: LLM, 클라우드, 데이터베이스, 프록시.
- 최근 몇 주 동안 각 키의 소비를 제공자에게 확인하십시오. 프록시 로그인에 대한 통계는 즉시 타인의 트래픽을 보여줄 것입니다.
- 깨끗한 이미지에서 새 서버를 세우고, 새로운 키를 발급한 후 데이터를 이전하십시오. 이전 머신의 바이너리 및 cron 파일은 포함하지 마십시오.
여기서 프록시는 무엇이며 그들이 해결하지 않는 것
프록시는 CARBONATO로부터 서버를 보호하지 않습니다. 웜은 귀하의 아웃바운드 요청을 통해 오는 것이 아니라, 인바운드 포트를 통해 들어옵니다. 그러나 올바른 프록시 작업 방식은 피해를 줄입니다. 작업에 대한 별도의 로그인, 트래픽 한도 및 IP에 대한 바인딩은 유출을 “모든 잔액이 사라졌다”에서 “하나의 로그인을 철회했다”로 전환합니다.
또한 봇넷이 정기적으로 보여주는 반대 측면이 있습니다: 타인의 장치가 스스로 의심스러운 네트워크의 “레지던트 프록시”가 됩니다. 따라서 파싱을 위해서는 출처가 명확한 풀에서 제공하는 트래픽을 사용하는 것이 좋습니다. 대부분의 데이터 수집 작업에는 기가바이트당 요금이 부과되는 레지던트 프록시가 적합하며, 각 프록시의 소비가 대시보드에서 확인 가능합니다. 서비스 작업에는 강력한 안티봇 보호가 없는 경우 더 저렴한 데이터 센터 프록시가 충분합니다.
결론
CARBONATO는 제로데이 취약점이나 교묘한 익스플로잇을 사용하지 않습니다. 그는 서버 소유자들이 스스로 열어 놓은 문, 즉 비밀번호 없는 TCP 2375를 통해 들어옵니다. 그 안에서 새로운 점은 AI 에이전트가 모델 키를 먼저 가져가도록 지시받았다는 것입니다. 자신의 VPS에서 데이터를 수집하는 사람들에게 실질적인 결론이 있습니다. Docker API를 차단하고, 서비스 포트를 127.0.0.1에 게시하며, LLM 키와 프록시를 작업에 따라 비용 한도를 설정하여 분리하십시오. 이는 15분의 작업이며, 이후 귀하의 서버는 이러한 봇넷에게 흥미롭지 않은 목표가 됩니다.
