본문 바로가기
카테고리 없음

KISA BPFDoor 악성코드 점검 가이드 배포 관련 대응

by jaeaemin 2025. 5. 27.

 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 grep -Er '\[\s*-f\s+/[^]]+\]\s*&&\s*/' /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 필터를 확인

# 서버에 등록된 BPF 필터 확인
sudo ss -0pb
 
# 매직넘버로 악성코드 의심
sudo ss -0pb | grep -E
 
# 명령어 3-1: 서버에 등록된 BPF 필터 확인
sudo ss -0pb
 
# 명령어 3-2: BPF 필터 내 매직넘버 확인 -> 악성 코드 감염 의심
sudo ss -0pb | grep -E "21139|29269|960051513|36204|40783"
 
# 명령어 3-3: 명령어 3-2 안먹히는 경우 사용
sudo ss -0pb | grep -E "\$((0x5293))|\$((0x7255))|\$((0x39393939))|\$((0x8D6C))|\$((0x9F4F))"
 

참고: CentOS 6.x 이하에서는 BPF 점검이 불가능하니, 다음 단계로 넘어갑니다.

4. RAW 소켓 사용 점검

악성코드는 RAW 소켓을 사용해 네트워크 통신을 조작할 수 있습니다.

다음 명령어로 의심되는 RAW 소켓 사용 목록을 확인

#위 명령어로 결과가 없고, 뮤텍스/락 파일이 존재하며 BPF 점검 결과가 없을 경우, 전체 탐색을 시도
sudo lsof 2>/dev/null | grep -E "IP type=SOCK_RAW|IP type=SOCK_DGRAM" | awk '{print $2}' | sort -u | xargs -r ps -fp
#의심 프로세스 발견 시:
sudo awk '$4=="0800" && $5=="0" {print $9}' /proc/net/packet | while read inode; do sudo grep -r "ino:\s*$inode" /proc/*/fdinfo/ 2>/dev/null | awk -F/ '{print $3}' | sort -u | xargs -r sudo ps -fp; done sudo ss -apn | grep -E ":1 |:6 |:17 "

 

# 의심 프로세스 발견 시, 프로세스 아이디 기반의 상세 점검

sudo ls -l /proc/<PID>/exe

예: /proc/13851/exe -> /dev/shm/dbus-srv_bin (삭제된 파일은 의심 대상).

5. 프로세스 환경변수 점검

BPFDoor는 환경변수를 조작해 흔적을 숨깁니다.

 

#아래 스크립트를 실행하여 BPFDoor 관련 환경변수를 확인

sudo ./bpfdoor_env.sh

# 의심 프로세스 발견 시, 프로세스 아이디 기반의 상세 점검
sudo ls -l /proc/<PID>/exe

 

6. 포트 점검

악성코드는 특정 포트(42391~43390, 8000)를 사용할 수 있습니다.

 
sudo netstat -tulpn sudo netstat -tulpn 2>/dev/null | awk '{match($0, /:[0-9]+/, a); if ((a[1] >= 42391 && a[1] <= 43390) || $0 ~ /:8000/) print $0}' sudo netstat -tulpn 2>/dev/null | awk '$1=="tcp" && ($6=="LISTEN" || $6=="ESTABLISHED") {lp=substr($4,index($4,":")+1);rp=substr($5,index($5,":")+1);if((lp>=42391&&lp<=43390)||lp==8000||(rp>=42391&&rp<=43390)||rp==8000)print}'
 

7. 위장 프로세스 점검

악성코드는 abrtd, udevd, atd 등으로 위장할 수 있습니다.

sudo ps -ef | grep -E '/usr/sbin/abrtd|/sbin/udevd|cmathreshd|/sbin/sgaSolAgent|/usr/sbin/atd|pickup' sudo ls -l /proc/<PID>/exe
 
 
 
 
 
 
의심 되는 파일에 대한 분석은 아래에 대한 점검을 활용할 수 있습니다.

8. 문자열 기반 점검

의심 파일에서 특정 문자열을 검색하세요:

sudo strings -a -n 5 <의심파일> | grep -E 'MYSQL_HISTFILE=/dev/null|:h:d:l:s:b:t:|:f:wiunomc|:f:x:wiuoc|ttcompat' sudo find <경로> -maxdepth 1 -type f -size +15k -size -4M -exec sh -c 'strings -a -n5 "$1" | sed "s|^|$1: |" | grep -E "MYSQL_HISTFILE=/dev/null|:h:d:l:s:b:t:|:f:wiunomc|:f:x:wiuoc|ttcompat"' _ {} \;

9. YARA 룰 기반 점검

YARA 룰(bpfdoor.yar)로 의심 파일을 분석하세요:

 
yara bpfdoor.yar <의심 파일 또는 디렉토리>

 

YARA 룰 예시:

plaintext

rule ELF_BPFDoor_Controller { meta: description = "BPFDoor Malware(ELF) Controller Detection rule" author = "KrCERT/CC Threat Hunting Analysis Team" date = "2025-05-06" ver = "1.1" strings: $pname = /usr\/sbin\/[a-z]{2,8}/ $str_1 = "[-] option requires an argument -- d" $str_2 = ":h:d:l:s:b:t:" $magic = {C7 05 ?? ?? ?? ?? 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*)) }

 

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*))
}
반응형