BPFDoor 오탐 확인법: BPF 필터와 8000 포트 추적
BPFDoor 점검에서 나온 BPF 필터와 8000 포트 경고를 프로세스·실행 파일·소켓 소유자까지 따라가 실제 침해와 정상 동작을 구분한 방법을 설명한다.
이 글의 목차점검 대상 전체에서 같은 기준으로 증거를 모았다8
Linux 서버에 BPFDoor 점검 스크립트를 실행했더니 BPF 필터와 특정 포트가 의심 항목으로 표시됐다.
보안 점검 결과에 Suspicious가 보이면 빨리 결론을 내리고 싶어지지만, 그 단어는 침해 확정이 아니라 확인할 신호에 가깝다.
BPFDoor는 Linux에서 동작하는 백도어 악성코드다.
백도어는 정상 인증 절차를 거치지 않고 시스템을 원격으로 제어할 수 있게 숨겨 둔 통로를 뜻한다.
이 악성코드는 Berkeley Packet Filter인 BPF로 들어오는 패킷을 살펴보다가 약속된 매직 패킷을 받으면 동작할 수 있다.
매직 패킷은 공격자가 악성코드를 깨우기 위해 정해 둔 특별한 패턴의 네트워크 데이터다.
BPF 자체는 악성 기능이 아니다.
Linux의 정상 네트워크 도구도 필요한 패킷만 골라 받기 위해 BPF 필터를 사용하므로 필터가 있다는 사실만으로 침해를 판정하면 오탐이 생긴다.
백신이 문서 안의 위험한 문자열을 발견했다고 해서 문서 작성자가 공격자라고 단정할 수 없는 것과 비슷하다.
탐지 신호는 “어디를 볼지”를 알려 주지만, 그 기능을 어떤 프로세스가 어떤 목적으로 쓰는지는 별도 증거로 확인해야 한다.
점검 대상 전체에서 같은 기준으로 증거를 모았다
운영과 개발 환경의 점검 대상 Linux 서버 전부에 같은 스크립트와 판정 기준을 적용했다.
Linux용 스크립트를 적용할 수 없는 다른 운영체제는 억지로 같은 결과에 섞지 않고 비적용 대상으로 분리했다.
호스트마다 다음 여덟 영역을 확인했다.
- 악성코드가 중복 실행을 막기 위해 남길 수 있는 뮤텍스 파일을 찾았다.
- 재부팅 뒤 다시 시작하게 만드는 자동 실행 설정을 확인했다.
- 프로세스가 붙인 BPF 필터를 확인했다.
- 네트워크 계층의 패킷을 직접 받는 RAW 소켓을 확인했다.
- 의심스러운 환경변수를 확인했다.
- 알려진 의심 포트의 소유자를 확인했다.
- 루트 권한 프로세스의 실행 파일과 명령행을 확인했다.
- 알려진 악성 파일과 외부 제어 서버인 C2 흔적을 확인했다.
C2는 Command and Control의 약자로 공격자가 감염 시스템에 명령을 보내고 결과를 받는 서버다.
각 항목은 단독 판정값이 아니라 같은 프로세스와 파일을 여러 방향에서 좁혀 가는 단서로 사용했다.
첫 번째 경고는 systemd-networkd의 LLDP였다
여러 서버에서 BPF 필터가 반복 탐지됐다.
악성코드 설명과 겹치는 단어만 보면 위험해 보였지만 필터의 소유 프로세스는 systemd-networkd였다.
systemd-networkd는 Linux의 네트워크 인터페이스와 주소를 관리하는 정상 시스템 서비스다.
해당 필터는 같은 네트워크 구간의 장비 정보를 교환하는 LLDP 트래픽을 처리하는 동작과 연결돼 있었다.
LLDP는 Link Layer Discovery Protocol의 약자로 스위치와 서버가 서로의 장비 정보를 알리는 프로토콜이다.
BPF 사용 여부만 보지 않고 프로세스 경로, 서비스 상태와 필터가 필요한 네트워크 기능을 함께 대조해 정상 동작으로 판정했다.
여기서 중요한 기준은 정상 프로세스 이름을 보았다고 바로 끝내지 않는 것이다.
악성코드가 정상 이름으로 위장할 수 있으므로 실제 실행 파일 경로, 패키지 소유 정보, 시작 시각과 서비스 관리자의 상태를 함께 봐야 한다.
두 번째 경고는 8000 포트의 주인을 찾았다
다른 경고는 8000 포트였다.
포트 번호는 네트워크 요청이 도착할 프로그램을 구분하는 번호일 뿐이고, 같은 번호를 정상 서비스와 악성코드가 모두 사용할 수 있다.
포트를 연 프로세스와 소켓을 읽기 전용 명령으로 확인했다.
sudo ss -0pb
sudo lsof -i :8000ss -0pb는 PACKET 계열 소켓과 연결된 프로세스 및 BPF 정보를 확인할 때 사용했다.
이 명령은 소켓 상태를 읽을 뿐 설정을 바꾸지 않는다.
옵션을 나누면 -0은 PACKET 계열 소켓, -p는 소켓을 연 프로세스, -b는 연결된 BPF 필터 정보를 요청한다.
sudo가 필요한 이유는 다른 사용자의 프로세스와 필터 정보가 일반 권한에서는 일부 가려질 수 있기 때문이다.
lsof -i :8000은 8000 포트를 사용 중인 프로세스와 파일 정보를 보여 준다.
포트를 닫는 명령이 아니라 어느 프로세스가 소유하는지 좁히기 위한 조회다.
확인된 프로세스를 Docker의 컨테이너 정보와 대조했고, 사내에서 사용 중인 Portainer 관리 통신으로 판정했다.
Portainer는 Docker 같은 컨테이너 환경을 관리하는 도구다.
포트 번호가 알려진 의심 목록에 있다는 사실보다 현재 호스트에서 누가 왜 그 포트를 쓰는지가 판정에 더 가까운 증거였다.
예를 들어 개발 서버의 8000 포트는 웹 애플리케이션, 관리 도구나 테스트 API가 쓸 수 있다.
반대로 회사 서비스 목록에 없는 실행 파일이 루트 권한으로 같은 포트를 열고 낯선 외부 주소와 통신한다면 번호가 같아도 조사 우선순위는 훨씬 높다.
정상이라는 판정에도 반증 조건을 남겼다
오탐으로 분류할 때는 “유명한 프로세스라서 괜찮다”는 설명으로 끝내지 않았다.
같은 이름을 흉내 낸 프로세스가 아닌지 다시 뒤집어 볼 조건을 남겼다.
프로세스의 실행 파일이 배포판 패키지가 설치한 경로와 다른지 확인한다.
실행 파일이 삭제된 상태로 메모리에서 계속 동작하는지 확인한다.
부모 프로세스, 시작 시각과 명령행이 서비스 관리자 기록과 맞는지 확인한다.
예상하지 않은 RAW 소켓, 방화벽 변경이나 외부 연결이 같은 PID에서 함께 나타나는지 확인한다.
알려진 파일 해시와 경로, C2 주소가 추가로 발견되는지 확인한다.
PID는 운영체제가 실행 중인 프로세스에 붙인 번호다.
서로 다른 경고가 같은 PID로 모이면 단독 신호보다 조사 우선순위가 높아진다.
판정 상태는 다음처럼 나누는 편이 안전하다.
| 증거 상태 | 판정 | 다음 행동 |
|---|---|---|
| 배포판의 정상 실행 파일, 예상된 서비스 역할, 추가 악성 신호 없음 | 오탐 후보 | 근거를 남기고 같은 신호가 바뀌는지 관찰 |
| 소유자가 불명확하거나 실행 경로가 예상과 다름 | 추가 조사 필요 | 해시·패키지 소유·부모 프로세스·외부 연결 확인 |
| 알려진 악성 해시, C2 통신, 수상한 자동 실행이 함께 나타남 | 침해 의심 | 호스트 격리와 사고 대응 절차를 우선 |
마지막 상태에서는 운영 서버에서 명령을 계속 시도하며 원인을 좁히는 것보다 조직의 사고 대응 절차에 따라 증거를 보존하고 네트워크 영향을 제한해야 한다.
이 표는 보안 도구의 공식 판정을 대신하지 않고 조사 깊이와 대응 속도를 정하기 위한 기준이다.
이 방식은 디버깅에서도 같았다.
관찰한 사실과 해석을 분리하는 기록 방법은 재현 가능한 디버깅 노트를 만드는 과정에 정리했다.
확인한 결과
점검 대상 서버 전부에서 호스트별 점검 로그를 확보했다.
뮤텍스, 자동 실행, RAW 소켓, 의심 환경변수, 악성 파일, 의심 프로세스와 C2 항목에서 BPFDoor 침해 근거가 확인되지 않았다.
반복된 BPF 탐지는 systemd-networkd의 정상 LLDP 동작으로 확인했다.
8000 포트는 프로세스와 컨테이너까지 따라가 Portainer 관리 통신으로 판정했다.
이번 조사 범위의 결론은 점검 대상 서버 전부에서 BPFDoor 침해 근거가 없다는 것이었다.
이 판정은 당시 확보한 증거에 한정하며, 이후 같은 신호가 발생하면 실행 파일 경로와 외부 연결을 다시 대조해야 한다.
스크립트 경고가 없었다는 결과도 아니었다.
경고 두 종류가 실제로 나타났고, 경고를 만든 실행 주체와 용도를 확인해 오탐으로 제거한 것이 이번 점검의 결과다.
같은 점검을 할 때 사용할 순서
- 악성코드가 사용하는 파일, 소켓, 프로세스와 네트워크 신호를 여러 범주로 나눈다.
- 모든 호스트에서 같은 명령과 시간 기준으로 원본 로그를 보존한다.
Suspicious항목마다 PID, 실행 파일 경로, 부모 프로세스와 시작 주체를 연결한다.- 포트 번호는 소유 프로세스와 컨테이너까지 확인하고 번호만으로 판정하지 않는다.
- 정상 서비스 후보도 패키지 경로, 서명 또는 해시와 서비스 관리자 기록으로 다시 확인한다.
- 단독 신호보다 여러 독립 신호가 같은 실행 주체로 모이는지 본다.
- 침해 근거 없음, 오탐, 추가 조사 필요와 침해 확인을 서로 다른 상태로 기록한다.
- 호스트명, 사설 IP, 컨테이너 ID와 내부 이미지명은 공개 문서에서 제거한다.
모니터링 알람도 관찰값과 결론을 섞으면 같은 문제가 생긴다.
값이 없는 상태를 곧바로 장애로 해석했던 사례는 CloudWatch의 데이터 없음 판정에서 볼 수 있다.
탐지 도구의 경고는 조사 시작점이었다
BPFDoor는 BPF 필터와 매직 패킷을 이용해 눈에 띄는 수신 포트를 계속 열지 않고도 동작할 수 있어 단순 포트 검사만으로는 부족하다.
반대로 정상 네트워크 서비스도 BPF를 쓰기 때문에 BPF라는 단어만으로 악성이라고 결론내릴 수도 없다.
이번 점검에서는 스크립트가 넓게 포착한 신호를 프로세스, 실행 파일, 소켓과 서비스 역할로 좁혔다.
보안 도구의 역할은 결론을 대신하는 것이 아니라 사람이 확인해야 할 증거를 줄이는 데 있었다.
systemd-networkd의 LLDP 필터와 Portainer의 8000 포트라는 소유 관계를 확인했고, 반증 조건에서도 추가 악성 신호가 나오지 않아 이번 경고를 오탐으로 닫았다.