BPFDoor 악성코드: 점검 가이드와 대응 방법
최근 SKT에서 발생한 대규모 개인정보 유출로 인해 . 이번 사건은 악성코드, 특히 BPFDoor라는 악성코드가 연루된 것으로 의심되고 있어 이에 대한 대응이 필요합니다.
한국인터넷진흥원(KISA)의 BPFDoor 악성코드 점검 가이드를 바탕으로, 이 악성코드의 특징과 시스템 점검 방법을 자세히 정리한 포스팅입니다.
BPFDoor 악성코드란?
BPFDoor는 Berkeley Packet Filter(BPF)를 악용해 시스템에 침투하는 정교한 악성코드입니다. 이 악성코드는 주로 리눅스 시스템을 타겟으로 하며, 네트워크 트래픽을 조작하거나 백도어 역할을 수행해 공격자가 시스템에 지속적으로 접근할 수 있도록 합니다. SKT와 같은 대규모 통신사나 기업 네트워크가 이 악성코드의 주요 타겟이 될 수 있는데, 이는 방대한 데이터와 민감한 정보를 노리기 때문입니다.
따라서 기업 IT 관리자뿐만 아니라 개인 서버 운영자도 이 악성코드에 대한 점검과 대응이 필수적입니다.
왜 BPFDoor가 위험한가?
BPFDoor는 다음과 같은 특징 때문에 특히 위험합니다:
- 은폐성: 정상 프로세스(예: dbus-daemon, smartadm)로 위장해 탐지하기 어렵습니다.
- 지속적 접근: 백도어를 설치해 공격자가 언제든 시스템에 재접속할 수 있습니다.
- BPF 필터 악용: 네트워크 패킷 필터링을 조작해 감시를 우회합니다.
- 환경변수 조작: MYSQL_HISTFILE=/dev/null, HISTFILE=/dev/null 같은 환경변수를 설정해 흔적을 지웁니다.
보안 유출 사건에서는 이러한 특징이 대규모 네트워크 환경에서 악용되었을 가능성이 높습니다. 예를 들어, 공격자가 BPFDoor를 통해 네트워크 트래픽을 감시하거나 데이터를 외부로 유출했을 수 있습니다. 이제 KISA의 가이드를 바탕으로 시스템에서 BPFDoor를 점검하는 방법을 단계별로 살펴보겠습니다.
BPFDoor 점검 가이드: 단계별 명령어와 대응
KISA의 가이드에 따르면, BPFDoor를 점검하려면 뮤텍스/락 파일, 자동 실행 파일, BPF 필터, RAW 소켓, 환경변수, 포트, 위장 프로세스, 문자열, 그리고 YARA 룰 기반으로 총 9단계 점검이 필요합니다. 아래는 각 단계를 간단히 정리한 내용입니다.
1. 뮤텍스/락 파일 점검
악성코드는 /var/run/ 디렉토리에 크기가 0바이트인 .pid 또는 .lock 파일을 생성할 수 있습니다.
아래 명령어로 이를 확인
sudo ls -l /var/run/*.pid | awk '$5 == 0 {print $9}'
sudo ls -l /var/run/*.lock | awk '$5 == 0 {print $9}'
sudo stat -c "%a %s %n" /var/run/*.pid /var/run/*.lock 2>/dev/null | awk '$1=="644" && $2==0 {print $3}'
# 의심 파일 있으면 파일 권한 644 및 파일 생성일 확인
$ sudo ls -al /var/run/<filename>.pid
2. 자동 실행 파일 점검
악성코드는 /etc/sysconfig/ 디렉토리의 스크립트에 침투해 시스템 부팅 시 실행될 수 있습니다.
다음 명령어로 자동 실행 파일을 확인
sudo find /etc/sysconfig/ -type f -exec egrep '\[\s*-f\s+/[^]]+\]\s*&&\s*/' {} +
예를 들어, /etc/sysconfig/test에서 [-f /usr/sbin/smartadm ] && /usr/sbin/smartadm 같은 패턴이 발견되면 추가적인 점검이 필요합니다.
3. BPF 필터 점검
BPFDoor는 BPF 필터를 악용해 네트워크 트래픽을 조작합니다.
다음 명령어로 등록된 BPF 필터를 확인
sudo ss -0pb
sudo ss -0pb | grep -E "21139|29269|960051513|36204|40783"
sudo ss -0pb | grep -E "\$((0x5293))|\$((0x7255))|\$((0x39393939))|\$((0x8D6C))|\$((0x9F4F))"
참고: CentOS 6.x 이하에서는 BPF 점검이 불가능하니, 다음 단계로 넘어갑니다.
4. RAW 소켓 사용 점검
악성코드는 RAW 소켓을 사용해 네트워크 통신을 조작할 수 있습니다.
다음 명령어로 의심되는 RAW 소켓 사용 목록을 확인
# 의심 프로세스 발견 시, 프로세스 아이디 기반의 상세 점검
sudo ls -l /proc/<PID>/exe
예: /proc/13851/exe -> /dev/shm/dbus-srv_bin (삭제된 파일은 의심 대상).
5. 프로세스 환경변수 점검
BPFDoor는 환경변수를 조작해 흔적을 숨깁니다.
#아래 스크립트를 실행하여 BPFDoor 관련 환경변수를 확인
sudo ./bpfdoor_env.sh
6. 포트 점검
악성코드는 특정 포트(42391~43390, 8000)를 사용할 수 있습니다.
7. 위장 프로세스 점검
악성코드는 abrtd, udevd, atd 등으로 위장할 수 있습니다.
8. 문자열 기반 점검
의심 파일에서 특정 문자열을 검색하세요:
9. YARA 룰 기반 점검
YARA 룰(bpfdoor.yar)로 의심 파일을 분석하세요:
YARA 룰 예시:
plaintext
SKT 대규모 보안 유출 사건과 BPFDoor: 시사점
SKT 대규모 보안 유츨 사건은 대기업의 보안 체계 마저도 정교한 공격에 취약할 수 있는지를 보여줍니다. BPFDoor는 특히 은폐성이 뛰어나기 때문에, 정기적인 점검과 최신 보안 패치 적용이 중요합니다. 기업은 다음 조치를 고려해야 합니다:
- 정기적인 시스템 점검: 위 명령어를 주기적으로 실행해 의심스러운 활동을 탐지.
- 네트워크 모니터링 강화: 비정상적인 트래픽(예: 포트 42391~43390)을 감시.
- YARA 룰 활용: 의심 파일을 빠르게 분석.
- KISA 신고: 감염 의심 시 즉시 KISA 보호나라로 신고.
개인 사용자라면, 서버를 운영 중이라면 KISA 가이드를 참고해 점검하고, 최신 안티바이러스 소프트웨어를 사용하는 것이 좋습니다.
[붙임1] BPF 점검 스크립트 : bpfdoor_bpf.sh
#!/bin/bash
echo "[*] Detecting processes with active BPF usage..."
# 1. Extract PIDs directly from ss output
sudo ss -0pb | grep -oP 'pid=\K[0-9]+' | sort -u | while read pid; do
# 2. For each PID, find the executable path
if [[ -e "/proc/$pid" ]]; then
exe_path=$(readlink -f /proc/$pid/exe 2>/dev/null)
proc_name=$(cat /proc/$pid/comm 2>/dev/null)
echo ""
echo "Process Name: ${proc_name:-Unknown}, PID: $pid"
echo " → Executable: ${exe_path:-Not found}"
fi
done
[붙임2] 환경변수 점검 스크립트 : bpfdoor_env.sh
#!/bin/bash
echo "[*] Detecting processes with BPFDoor environment variable manipulation..."
echo "Target : HOME=/tmp, HISTFILE=/dev/null, MYSQL_HISTFILE=/dev/null"
CHECK_ENV=("HOME=/tmp" "HISTFILE=/dev/null" "MYSQL_HISTFILE=/dev/null")
# Process scanning
for pid in $(ls /proc/ | grep -E '^[0-9]+$'); do
if [ -r /proc/$pid/environ ]; then
env_data=$(tr '\0' '\n' < /proc/$pid/environ)
match_all=true
for check_item in "${CHECK_ENV[@]}"; do
if ! echo "$env_data" | grep -q "$check_item"; then
match_all=false
break
fi
done
if [ "$match_all" = true ]; then
echo "Warning: Process with all suspicious environment variables detected (PID: $pid)"
echo " → $(ps -p $pid -o user=,pid=,ppid=,cmd=)"
echo ""
fi
fi
done
[붙임3] vim bpfdoor.yar
rule ELF_BPFDoor
{
meta:
description = "BPFDoor Malware(ELF) Detection rule"
author = "KrCERT/CC Threat Hunting Analysis Team"
date = "2025-05-06"
hash = "c7f693f7f85b01a8c0e561bd369845f40bff423b0743c7aa0f4c323d9133b5d4"
hash = "3f6f108db37d18519f47c5e4182e5e33cc795564f286ae770aa03372133d15c4"
hash = "95fd8a70c4b18a9a669fec6eb82dac0ba6a9236ac42a5ecde270330b66f51595"
hash = "aa779e83ff5271d3f2d270eaed16751a109eb722fca61465d86317e03bbf49e4"
ver = "1.1"
strings:
$pty_1 = "/dev/ptm"
$pty_2 = "ptem"
$pty_3 = "ldterm"
$pty_4 = "ttcompat"
// for ( i = 0xA597; i <= 0xA97E; ++i )
$bind_port_1 = { C7 45 ?? 97 A5 00 00 EB }
$bind_port_2_1 = { 83 45 ?? 01 81 7D ?? 7E A9 00 00 7E }
$bind_port_2_2 = { 81 7D ?? 7E A9 00 00 7E }
// v1.1 : added new pattern "PS1=[\\u@\\h : "
$ps1 = {C6 85 ?? ?? FF FF 50 C6 85 ?? ?? FF FF 53 C6 85 ?? ?? FF FF 31 C6 85 ?? ?? FF FF 3D C6 85 ?? ?? FF FF 5B C6 85 ?? ?? FF FF 5C C6 85 ?? ?? FF FF 75 C6 85 ?? ?? FF FF 40 C6 85 ?? ?? FF FF 5C C6 85 ?? ?? FF FF 68}
// v1.1 : bpf filter modify (dbus, hald, trend-B, Trend-E)
$bpf_filter_1 = {B1 00 00 00 0E 00 00 00 48 00 00 00 16 00 00 00 15 00 ?? ?? ?? ?? 00 00 15 00 00 07 01 00 00 00 28 00 00 00 14 00 00 00 45 00 (11|1A) 00 FF 1F 00 00}
$bpf_filter_2 = {07 00 00 00 00 00 00 00 (40|48) 00 00 00 00 00 00 00 02 00 00 00 (00|01|03) 01 00 00 00 00 00 00 00 ?? ?? ?? ?? 02 00 00 00 (01|02|04) 00 00 00 61 00 00 00 (01|02|04) 00 00 00}
$bpf_filter_3 = { 07 00 00 00 00 00 00 00 40 00 00 00 0E 00 00 00 15 00 00 01 39 39 39 39 06 00 00 00 FF FF 00 00 06 00 00 00 00 00 00 00}
$bpf_filter_4 = { 48 00 00 00 10 00 00 00 15 00 01 00 BB 01 00 00 15 00 00 01 16 00 00 00 06 00 00 00 00 00 04 00 06 00 00 00 00 00 00 00}
// I5*AYbs@LdaWbsO
$md5_salt = {C6 45 ?? 49 C6 45 ?? 35 C6 45 ?? 2A C6 45 ?? 41 C6 45 ?? 59 C6 45 ?? 62 C6 45 ?? 73 C6 45 ?? 40 C6 45 ?? 4C C6 45 ?? 64 C6 45 ?? 61 C6 45 ?? 57 C6 45 ?? 62 C6 45 ?? 73 C6 45 ?? 4F}
// qmgr -l -t fifo
$pname = {C6 ?? ?? ?? FF FF 71 C6 ?? ?? ?? FF FF 6D C6 ?? ?? ?? FF FF 67 C6 ?? ?? ?? FF FF 72 C6 ?? ?? ?? FF FF 20 C6 ?? ?? ?? FF FF 2D C6 ?? ?? ?? FF FF 6C C6 ?? ?? ?? FF FF 20 C6 ?? ?? ?? FF FF 2D C6 ?? ?? ?? FF FF 74 C6 ?? ?? ?? FF FF 20 C6 ?? ?? ?? FF FF 66 C6 ?? ?? ?? FF FF 69 C6 ?? ?? ?? FF FF 66 C6 ?? ?? ?? FF FF 6F}
$solaris_1 = "(udp[8:2]=0x7255) or (icmp[8:2]=0x7255)"
$solaris_2 = "HISTFILE=/dev/null"
$solaris_3 = "MYSQL_HISTFILE=/dev/null"
condition:
uint32(0) == 0x464C457F and
(
(all of ($pty*) and (2 of ($bind_port*) or $ps1)) or //v1.1
((all of ($pty*) or $ps1) and 2 of ($bind_port*)) or //v1.1
(1 of ($bpf_filter*)) or
($md5_salt or $pname) or
(all of ($solaris*))
)
}
rule ELF_BPFDoor_Controller
{
meta:
description = "BPFDoor Malware(ELF) Controller Detection rule"
author = "KrCERT/CC Threat Hunting Analysis Team"
date = "2025-05-06"
hash = "93f4262fce8c6b4f8e239c35a0679fbbbb722141b95a5f2af53a2bcafe4edd1c"
hash = "1925e3cd8a1b0bba0d297830636cdb9ebf002698c8fa71e0063581204f4e8345"
hash = "591198c234416c6ccbcea6967963ca2ca0f17050be7eed1602198308d9127c78"
ver = "1.1"
strings:
// v1.1 : added new pattern
$pname = /\/usr\/sbin\/[a-z]{2,8}/
$str_1 = "[-] option requires an argument -- d"
$str_2 = ":h:d:l:s:b:t:"
// mov cs:magic_flag, 5571h
$magic = {C7 05 ?? ?? ?? 00 71 55 00 00}
$env_1 = "export TERM=vt100"
$env_2 = "export MYSQL_HISTFILE=/dev/null"
$env_3 = "export HISTFILE=/dev/null"
$env_4 = "unset PROMPT_COMMAND"
$env_5 = "export HISTSIZE=100"
condition:
uint32(0) == 0x464C457F and
($pname or 1 of ($str*)) and $magic and (all of ($env*))
}