SecurityHeroblog

같은 보냉가방, 반찬 아홉 통은 전부 새로 담았다

9월 27일, 닷새 전에 적어 둔 악성코드 배포 주소가 다시 파일을 내보냈습니다. 맨 앞 설치 스크립트는 8월 21일부터 37일째 한 비트도 바뀌지 않았습니다. 뒤따라온 실행파일 아홉 개는 모두 처음 보는 파일이었고, 그중 셋은 크기가 바이트 단위까지 같은데 내용만 달랐습니다.

반찬 정기배달을 받아 본 적이 있나요? 일주일에 한 번, 현관 앞에 보냉가방이 놓입니다. 가방은 매주 같습니다. 색도 같고 지퍼 손잡이에 달린 가게 이름표도 같습니다. 달라지는 건 안에 든 반찬입니다. 지난주에는 멸치볶음이었고, 이번 주에는 장조림일 수 있습니다.

어제 우리 서버 앞에도 이런 가방이 하나 놓였습니다. 그런데 이 가방은 이미 두 번 본 가방이었습니다. 8월 21일에 처음 봤고, 닷새 전인 9월 22일에 또 봤습니다. 가방은 그때와 한 올도 다르지 않았습니다. 안에 든 반찬 통은 여섯 개에서 아홉 개로 늘었습니다. 그리고 아홉 통 모두 새로 담은 것이었습니다.

오늘은 이 가방을 하나씩 열어 봅니다.

먼저, 우리 서버는 일부러 문을 열어 둔 집입니다

사실 우리는 허니팟을 운영합니다. 허니팟은 일부러 허술하게 열어 두고, 누가 들어와 무엇을 하는지 지켜보는 미끼 서버입니다. 그래서 아래 이야기는 실제 피해가 아니라 관찰 기록입니다. 서버는 두 대입니다. 첫 번째(센서 01)는 문이 실제로 열립니다. 두 번째(센서 02)는 누가 문을 두드렸는지만 적습니다.

사실 어제 가방을 들고 온 쪽은 ATK-9D3922 입니다. 우리가 붙인 별칭입니다. 출발지 IP 는 108.59.x.x 로 가려서 적습니다. 이 별칭은 우리 기록에 처음 나왔습니다. 텔넷으로 들어왔습니다. 텔넷은 멀리 있는 기계에 글자로 명령을 보내는 오래된 원격 접속 방식입니다. 오가는 내용이 암호화되지 않습니다. 요즘은 주로 공유기나 CCTV 같은 작은 장비에 남아 있습니다. 포트는 2223번이었고 로그인에 성공했습니다. 텔넷이라서 접속 프로그램의 표식(지문)은 남지 않았습니다.

47초, 가방 하나를 푸는 데 걸린 시간

사실 오후 4시 11분 7초에 들어와서 47.12초 만에 나갔습니다. 그동안 명령을 11개 쳤습니다. 4.3초에 한 줄꼴입니다. 파일도 11개를 받았습니다. 역시 4.3초에 하나씩입니다. 우리 분류기는 이 세션의 행동에 세 가지 이름을 붙였습니다. 파일 다운로드 → 실행 권한 부여 → 다운로드 후 실행 순서입니다. ’실행 권한 부여’는 받은 파일을 프로그램으로 돌릴 수 있게 허락해 주는 단계입니다.

사실 기록이 얼마나 촘촘한지를 우리는 completeness(기록 촘촘함)라는 점수로 매깁니다. 이 세션은 46점으로 어제 1등이었습니다. 화면 녹화도 남았습니다. 다만 녹화 내용 자체는 우리 재료에 없습니다.

사실 받은 11개는 세 종류입니다.

  • 보냉가방 하나 — kla.sh. 셸 스크립트입니다. 셸 스크립트는 명령 여러 줄을 한 파일에 모아 둔 것입니다. 실행하면 적힌 명령이 차례로 돌아갑니다. 크기는 3,013바이트입니다. A4 한 장 남짓한 글자 수입니다.
  • 반찬 통 아홉 개 — 실행파일입니다. 리눅스에서 쓰는 ELF 라는 형식의 프로그램입니다. 아홉 개를 합치면 1,725,652바이트, 약 1.7메가바이트입니다. 휴대폰 사진 한 장 정도 크기입니다.
  • 쪽지 한 장 — 9바이트짜리 글자 파일입니다. 영어 글자 아홉 개 분량입니다.

추정 이런 공격에서 맨 앞 스크립트는 보통 가방 역할을 합니다. 뒤따르는 실행파일을 챙겨 와서 하나씩 열어 보게 만드는 겁니다. 다만 kla.sh 안에 무엇이 적혀 있었는지는 우리 재료에 없습니다. 이건 비슷한 구조에 비춰 본 해석입니다.

먹을 사람을 몰라서, 아홉 가지

사실 컴퓨터의 두뇌인 CPU 는 종류가 여러 가지입니다. CPU 가 다르면 프로그램도 그 CPU 에 맞춰 따로 만들어야 돌아갑니다. 반찬으로 치면 먹는 사람에 맞춘 식단입니다. 아기에게는 이유식을, 할머니에게는 부드러운 죽을 드려야 하는 것과 같습니다. 어제 내려온 아홉 통은 CPU 종류가 모두 달랐습니다. 가운데 칸을 보세요.

파일 이름 어떤 CPU 용인가 크기 집 숟가락이 필요한가
px86 Intel 80386 (x86) 133,292바이트 아니요 (정적 링크)
pmips MIPS-I · 빅 엔디언 244,836바이트 아니요 (정적 링크)
pmpsl MIPS-I · 리틀 엔디언 248,932바이트 아니요 (정적 링크)
parm ARM 183,488바이트 아니요 (정적 링크)
parm5 ARM 83,344바이트 예 (동적 링크)
parm6 ARM EABI4 199,324바이트 아니요 (정적 링크)
parm7 ARM EABI4 259,684바이트 아니요 (정적 링크)
pppc PowerPC · 빅 엔디언 179,536바이트 아니요 (정적 링크)
pm68k Motorola 68020 (m68k) · 빅 엔디언 193,216바이트 아니요 (정적 링크)

사실 x86, MIPS, ARM, PowerPC, m68k 까지 다섯 계열입니다. ARM 은 네 벌, MIPS 는 두 벌입니다. 엔디언은 CPU 가 숫자를 앞에서부터 읽느냐 뒤에서부터 읽느냐의 차이입니다. 같은 MIPS 라도 읽는 방향이 다르면 다른 반찬이 필요합니다.

사실 오른쪽 칸의 정적 링크는 필요한 부품을 파일 안에 다 넣어 둔 상태입니다. 반찬 통 안에 숟가락까지 같이 넣어 보낸 것과 같습니다. 받는 집에 숟가락이 없어도 먹을 수 있습니다. 아홉 중 여덟이 이렇습니다. parm5 하나만 동적 링크입니다. 받는 장비에 /lib/ld-uClibc.so.0 이라는 부품이 미리 있어야 돌아갑니다. 집에 있는 숟가락을 꺼내야 먹을 수 있는 반찬인 셈입니다.

추정 가방을 보낸 쪽은 우리 서버에 어떤 CPU 가 들어 있는지 몰랐을 겁니다. 받는 집에 누가 사는지 모르니 식단을 아홉 가지 다 넣은 것입니다. 그리고 이 구성은 일반 컴퓨터보다 공유기·CCTV 같은 작은 장비에 맞는 쪽입니다. 그런 장비를 봇넷에 끌어들이려는 구성과 맞아떨어집니다. 봇넷은 주인 모르게 원격으로 조종당하는 기계들의 무리입니다.

가방은 37일째 그대로, 반찬은 전부 새로

사실 파일 11개 중 10개는 모두 같은 주소에서 받았습니다. hxxp://176[.]65[.]139[.]196/bins/ 입니다. 닷새 전 9월 22일 글에서 적어 둔 바로 그 주소입니다. 즉 같은 반찬가게입니다.

사실 파일마다 해시라는 값이 있습니다. 파일 내용 전체로 계산한 고유 번호입니다. 한 글자만 달라져도 전혀 다른 값이 나옵니다. 반찬으로 치면 통 속을 찍은 정밀 사진입니다. 깨 한 알만 옮겨도 다른 사진이 됩니다. 닷새 전과 어제의 사진을 나란히 놓아 봤습니다. 맨 오른쪽 칸을 보세요.

파일 9월 22일 9월 27일 (어제) 달라진 것
kla.sh (가방) 3,013바이트 · bb36568c… 3,013바이트 · bb36568c… 없음 (8/21 과도 같음)
px86 133,292바이트 · 2461a317… 133,292바이트 · 98c6780a… 크기 같음 · 사진만 다름
parm5 83,344바이트 · 13e3e131… 83,344바이트 · a273cd0b… 크기 같음 · 사진만 다름
parm6 199,324바이트 · 7aa4efe5… 199,324바이트 · 62a434f7… 크기 같음 · 사진만 다름
pmips 244,740바이트 244,836바이트 96바이트 커짐 · 사진 다름
pmpsl 248,836바이트 248,932바이트 96바이트 커짐 · 사진 다름
parm 182,976바이트 183,488바이트 512바이트 커짐 · 사진 다름
parm7 · pppc · pm68k (없었음) 새로 등장 이 주소에서 처음 보는 이름

사실 가방 kla.sh 는 8월 21일부터 어제까지 37일 동안 한 비트도 바뀌지 않았습니다. 반대로 반찬 아홉 통의 사진은 전부 처음 보는 값입니다. 아카이브 30일치(8/16~9/22)를 다 뒤져도 없습니다. 이름이 같은 여섯 통도 하나같이 다시 담겨 있었습니다. 96바이트는 문자 메시지 한 통 남짓한 크기입니다. 그만큼만 늘어난 통도 사진은 완전히 달라졌습니다.

무게까지 같은 반찬 세 통

사실 위 표에서 가장 이상한 줄은 둘째부터 넷째 줄입니다. px86, parm5, parm6 세 개는 크기가 바이트 단위까지 닷새 전과 같습니다. 그런데 사진(해시)은 다릅니다. 저울에 올리면 그램까지 똑같은데, 뚜껑을 열어 찍은 사진은 다른 반찬 통 세 개인 셈입니다.

추정 같은 이름에 같은 크기인데 해시가 다르다면 가능성이 하나 떠오릅니다. 파일 길이는 그대로 둔 채 안쪽 내용 일부만 바꿔서 다시 만들었을 수 있습니다. 통 크기는 그대로 두고 반찬만 조금 바꿔 담은 것처럼요. 하지만 파일 내용이 우리 재료에 없습니다. 그래서 무엇이 바뀌었는지는 말할 수 없습니다.

레시피 메모가 붙은 채 온 한 통

사실 새로 추가된 세 통 중 parm7 은 아홉 개 중 가장 큽니다(259,684바이트). 그리고 아홉 개 중 유일하게 디버그 정보를 지우지 않은 채 왔습니다. 디버그 정보는 프로그램을 만든 사람이 오류를 고칠 때 보려고 남겨 두는 설명 메모입니다. 보통 내보내기 전에 떼어 냅니다(stripped). pppc, pm68k 는 떼어 낸 상태였습니다. parm7 은 레시피 메모를 통에 붙인 채 배달된 셈입니다.

사실 같은 이름의 반찬이 다른 가게에서도 왔습니다. ATK-60335A 라는 다른 방문자가 hxxp://64[.]89[.]160[.]48:80/bins/parm7 에서 60,088바이트짜리 ARM 실행파일을 받아 갔습니다. 우리 기록에 없던 주소이고, 없던 해시(40b497bc…)입니다. 크기는 어제 주인공의 parm7 의 4분의 1이 안 됩니다. 이 파일에는 ‘no section header’(목차 없음)라는 표시가 붙어 있었습니다.

추정 ’목차 없음’은 압축으로 꽁꽁 싸맨 실행파일에서 흔히 보이는 모습입니다. 그렇다면 크기가 작은 것도 설명이 됩니다. 하지만 오늘 재료에는 압축 여부를 알려 주는 칸이 없습니다. 그래서 확정하지 않습니다. 두 parm7 이 서로 어떤 관계인지도 모릅니다.

반찬 이름은 이미 알던 이름이었다

사실 우리는 전에 UPX 로 압축된 악성코드를 풀어 본 적이 있습니다. UPX 는 실행파일을 싸매서 부피를 줄이는 도구입니다. 싸맨 상태에서는 겉에 주소가 하나도 안 보입니다. 풀어야만 나온 파일 이름이 12개 있습니다. 모두 31[.]77[.]227[.]121/bins/ 아래 이름입니다.

parm · parm5 · parm6 · parm64 · parm7 · pm68k · pmips · pmpsl · pppc · psh4 · pspc · x86_64

사실 어제 아홉 통 중 여덟 통의 이름이 이 목록과 글자까지 같습니다. 겹치지 않는 건 px86 하나입니다. 닷새 전에는 여섯 중 다섯이 같았습니다. 목록에만 있고 아직 안 나온 이름은 parm64 · psh4 · pspc · x86_64 넷입니다.

추정 미리 풀어서 이름표 규칙을 알아 두었기 때문에 알아볼 수 있었습니다. 가게 주소가 다른데도 같은 이름 짓는 방식이라는 것을요. 겉만 봤다면 “처음 보는 파일 아홉 개”로만 적혔을 겁니다.

사실 여기서 선을 두 개 긋습니다. 첫째, 어제 주소들은 세션에서 그대로 보였습니다. 압축을 풀어서 얻은 게 아닙니다. 풀어 본 경험이 준 건 주소가 아니라 이름 규칙입니다. 둘째, 이름 규칙이 같다는 건 같은 계열의 공개된 제작 도구를 썼다는 뜻일 뿐입니다. 같은 사람이나 같은 조직이라는 뜻이 아닙니다. 같은 밀키트를 쓴다고 같은 식당은 아니니까요.

사진 목록으로 막을 수 있었을까

추정 이렇게 생각해 봅시다. 닷새 전에 “이 사진과 똑같은 반찬은 받지 않는다”는 사진 목록을 만들어 두었습니다. 해시로 만든 차단 목록이 바로 이런 방식입니다. 어제 들어온 11개 중 이 목록에 걸리는 건 몇 개일까요? 가방(kla.sh)과 9바이트 쪽지, 두 개뿐입니다. 반찬 아홉 통은 하나도 안 걸립니다. 전부 새로 담았으니까요.

추정 반대로 **“이 가게에서 오는 가방은 받지 않는다”**는 규칙이었다면 어떨까요? 주소가 기록된 10개가 모두 걸립니다. 사진은 닷새 만에 아홉 장이 다 바뀌었습니다. 가게 주소는 37일째 그대로였습니다.

시간 순서로 늘어놓으면

어제 첫 번째 서버에서 벌어진 일을 시간 순서로 놓으면 이렇습니다. 16:11 의 세 줄을 눈여겨보세요. 들어와서 나갈 때까지 1분이 안 걸렸습니다.

  1. 사실 ATK-BDB53E(160.119.x.x) 텔넷 로그인 성공. 15.66초 동안 명령 7개 · 다운로드 2건. 검체는 hxxp://160[.]119[.]66[.]206/bins/kla.sh(3,241B · 39be6853…)와 net.x86_64(192,328B · 2cebccdc…)이고 9/20 · 9/22 와 같은 해시. 새로운 것은 없다
  2. 사실 주제 세션 시작. ATK-9D3922(108.59.x.x) 텔넷 로그인 성공. 아카이브에 없던 별칭. 텔넷이라 접속 프로그램 표식이 빈 문자열이다
  3. 사실 47.12초 동안 명령 11개 · 다운로드 11건. 의도 3개(파일 다운로드 · 실행 권한 부여 · 다운로드 후 실행). 기록 촘촘함 46 으로 오늘 최고. 화면 녹화됨(내용 미포함). 이 별칭이 배달자로 적힌 검체는 kla.sh 1 + ELF 9 + 9바이트 텍스트 1 = 11 로 다운로드 수와 맞는다
  4. 사실 hxxp://176[.]65[.]139[.]196/bins/kla.sh · 3,013B Bourne-Again 셸 스크립트 · bb36568c…. 8/21 · 9/22 와 URL · 크기 · 해시가 모두 같다. 8/21 부터 37일째 변하지 않았다
  5. 사실 px86 133,292B(2461a317… → 98c6780a…) · parm5 83,344B(13e3e131… → a273cd0b…) · parm6 199,324B(7aa4efe5… → 62a434f7…)는 크기가 같고 해시만 다르다. pmips 244,836B(+96B) · pmpsl 248,932B(+96B) · parm 183,488B(+512B)는 크기도 해시도 달라졌다
  6. 사실 parm7 259,684B(ELF32 LSB ARM EABI4 · 정적 · with debug_info, not stripped) · pppc 179,536B(ELF32 MSB PowerPC · 정적 · stripped) · pm68k 193,216B(ELF32 MSB m68k 68020 · 정적 · stripped). ELF 9개 합계 1,725,652B. 동적 링크는 parm5(/lib/ld-uClibc.so.0) 하나, 디버그 정보가 남은 것은 parm7 하나
  7. 사실 9바이트 ASCII 텍스트(0dc95fb4… · URL 미기록). 오늘 5회 · 출발지 3곳(ATK-9D3922 · ATK-EA3D92 · ATK-377ED5). 9/17 · 9/20 · 9/22 에도 다른 별칭들이 남긴 같은 해시
  8. 추정 파일 길이를 바꾸지 않는 범위 안에서 내부 내용 일부만 교체해 다시 빌드했을 가능성이 있다. 검체 내용이 없어 무엇이 바뀌었는지는 말할 수 없다
  9. 추정 9/22 해시로 만든 차단 목록은 이 세션 파일 11개 중 kla.sh 와 9바이트 텍스트 2개만 잡고 실행파일 9개는 하나도 잡지 못한다. 호스트 · 경로 기준 규칙이었다면 URL 이 기록된 10개를 모두 잡는다
  10. 사실 ATK-EC7309(160.250.x.x) 텔넷. 40.68초 · 명령 17개 · 의도 5개(정찰—시스템 · 파일 다운로드 · 실행 권한 부여 · 다운로드 후 실행 · SSH 키 심기). 다운로드 0 · 기록 촘촘함 17
  11. 사실 ATK-CA5936(130.12.x.x) SSH. 4.11초 · 명령 1개 · 의도 5개 · 다운로드 2건(54B 텍스트 00b6f15c… · 399B OpenSSH 개인키 43728fbf…). 지문 16443846… · 접속 프로그램 'SSH-2.0-Go'. 별칭 · 지문 · 검체 해시가 8/19 이후 반복 기록된 것과 같다
  12. 사실 ATK-015624(2.29.x.x) 텔넷. 61.79초 · 명령 17개. 의도 5개가 ATK-EC7309 와 같은 조합이고 다운로드 0 · 기록 촘촘함 17 도 같다. 두 별칭 모두 아카이브에 없다
  13. 사실 ATK-60335A 가 hxxp://64[.]89[.]160[.]48:80/bins/parm7 에서 60,088B ELF(ARM EABI4 · no section header)를 받았다. 호스트 · 해시(40b497bc…) · 별칭 모두 아카이브에 없다. 이 별칭은 주요 세션 목록에 없다
  14. 사실 세션 5,617 · 고유 출발지 203 · 로그인 시도 5,233 · 명령 9,747 · 화면 녹화 5,079. SSH 4,989(포트 2222) · 텔넷 628(포트 2223). 9/22(세션 829 · 명령 790) 대비 세션 약 6.8배 · 명령 약 12.3배. 의도 분류 합 6,682 로 명령 수와 3,065 차이
  15. 사실 389바이트 공개키(a8460f44…) 출발지 21곳 21회. 345gs5662d34 조합 22곳. libssh_0.9.6 지문(f555226d…) 오늘 22곳 · 누적 520곳. 9/22 의 24 · 23 · 24 와 비슷한 수준
  16. 사실 세션 54,243 · 고유 출발지 433. VNC 53,038(97.8% · 출발지 211) · RDP 567(113) · SMB 181(74) · MSSQL 30(10) · LDAP 19(10) · ADB 408. 02 검체 0건. 9/22 에 11,698건이던 RDP 가 567건으로 약 95% 줄었다

사실 주제 세션 말고도 어제 로그인에 성공한 주요 세션이 넷 더 있었습니다. 주제로 고르지 않은 이유를 적어 둡니다. ATK-BDB53E 는 파일 두 개가 9월 20일·22일과 같았습니다. ATK-CA5936 은 8월 19일부터 반복된 3~4초짜리 세션이고 파일도 그때와 같습니다. ATK-EC7309 와 ATK-015624 는 행동 이름이 다섯 개로 가장 많았습니다. 하지만 받아 간 파일이 0개라 들여다볼 물건이 없습니다.

어제 나온 값 — 받아 적을 것

방어에 쓰실 수 있게 값을 그대로 옮깁니다. 값을 누르면 복사됩니다. 주소는 실수로 접속되지 않게 변형(디팽)해 두었습니다. http 대신 hxxp, 점 대신 [.] 를 쓴 형태입니다. 그대로 두고 쓰세요. **둘째 줄부터 열째 줄까지가 어제 처음 본 사진(해시)**입니다.

sha256
bb36568c1f0a4f4d604cc67f8692506291eb1ffd217a451ffc846c94daa09440kla.sh · 3,013바이트 Bash 스크립트 · 출처 ATK-9D3922 · 8/21 · 9/22 와 같은 해시로 37일째 그대로
sha256
98c6780a3a6d276994b02ab89f80671f5c347f029ca76472e7095a9407761b08px86 · 133,292바이트 ELF32 i386 정적 · 9/22 와 크기 같고 해시 다름
sha256
6d91ecbff02877062add12ff8647a1c85dad1e2429aad08095e0421bceff0edepmips · 244,836바이트 ELF32 MSB MIPS-I 정적 · 9/22 대비 +96바이트
sha256
5be047ede1d06e807c9d52aa65fe899eda0720c784d51e3715395146e25b843cpmpsl · 248,932바이트 ELF32 LSB MIPS-I 정적 · 9/22 대비 +96바이트
sha256
32ad236fe419a677de7d6cc56a7d774641bc5174aff5d198af0bced92b8fc488parm · 183,488바이트 ELF32 LSB ARM 정적 · 9/22 대비 +512바이트
sha256
a273cd0b39df9ce7debccf814615357e33af32ae42231fb9bf9db2921b3346e6parm5 · 83,344바이트 ELF32 ARM 동적 링크(uClibc) · 아홉 중 유일한 동적 링크 · 9/22 와 크기 같고 해시 다름
sha256
62a434f7061eb5b4ec075be4794dc268968f7e6c7eff530583a30ed9809bdd7dparm6 · 199,324바이트 ELF32 ARM EABI4 정적 · 9/22 와 크기 같고 해시 다름
sha256
2114dad45995ce2208cdd57701bcc4489daa093b35072ca52e08ff2f73fd160dparm7 · 259,684바이트 ELF32 ARM EABI4 정적 · 디버그 정보 남음(not stripped) · 이 호스트에서 처음 보는 이름
sha256
b8a95987f0fa415d5091b60589c0d3cea9f9b99f408c60bde7a2ace9454550a5pppc · 179,536바이트 ELF32 MSB PowerPC 정적 · 이 호스트에서 처음 보는 이름
sha256
49b0bc6e09ab3f485f3a45fba571a19e83b5071a22124e8050d9fdabff10ad79pm68k · 193,216바이트 ELF32 MSB m68k 정적 · 이 호스트에서 처음 보는 이름
sha256
0dc95fb4077cce0bff19aa1a77109d059dff6503bbf6c1b0dd2f41fc0a4c88e79바이트 ASCII 텍스트 · URL 미기록 · ATK-9D3922 · ATK-EA3D92 · ATK-377ED5 가 남김 · 9/17 · 9/20 · 9/22 에도 나온 해시
sha256
40b497bc232886341613fdcfd84adaf326aba1336bf42b2ad2cab26f8fc00d9dparm7(다른 유포지) · 60,088바이트 ELF32 ARM EABI4 · no section header · 출처 ATK-60335A · 주제 세션과 별개
url
hxxp://176[.]65[.]139[.]196/bins/kla.sh위 셸 스크립트의 유포지 · 8/21 · 9/22 와 같은 URL
url
hxxp://176[.]65[.]139[.]196/bins/px86위 px86 의 유포지
url
hxxp://176[.]65[.]139[.]196/bins/pmips위 pmips 의 유포지
url
hxxp://176[.]65[.]139[.]196/bins/pmpsl위 pmpsl 의 유포지
url
hxxp://176[.]65[.]139[.]196/bins/parm위 parm 의 유포지
url
hxxp://176[.]65[.]139[.]196/bins/parm5위 parm5 의 유포지
url
hxxp://176[.]65[.]139[.]196/bins/parm6위 parm6 의 유포지
url
hxxp://176[.]65[.]139[.]196/bins/parm7위 parm7 의 유포지 · 이 호스트에서 처음 보는 이름
url
hxxp://176[.]65[.]139[.]196/bins/pppc위 pppc 의 유포지 · 이 호스트에서 처음 보는 이름
url
hxxp://176[.]65[.]139[.]196/bins/pm68k위 pm68k 의 유포지 · 이 호스트에서 처음 보는 이름
url
hxxp://64[.]89[.]160[.]48:80/bins/parm7다른 유포지의 parm7 · 아카이브에 없던 호스트

사실 스물세 줄을 다시 보세요. 해시 줄 열두 개 중 열 개가 어제 처음 본 값입니다. 반면 주소 줄 열한 개 중 열 개는 앞부분 hxxp://176[.]65[.]139[.]196/bins/ 이 같습니다. 사진은 매번 새로 찍어 둬야 합니다. 가게 주소는 한 줄이면 됩니다.

이 비밀번호 쓰고 계십니까

사실 어제 첫 번째 서버의 로그인 시도는 5,233회였습니다. 하루로 나누면 16.5초에 한 번꼴로 누군가 문고리를 돌려 본 셈입니다. 노래 한 곡을 듣는 동안 열 번 넘게 돌린 겁니다.

사실 시도된 아이디·비밀번호 조합 중 이 글에 옮기는 건 20종뿐입니다. 서로 다른 IP 세 곳 이상에서 반복된 조합만 원문을 적는 게 우리 규칙입니다. 이 기준에 못 미친 356종은 개수만 세고 값은 적지 않습니다. 한 곳에서만 나온 조합은 어디선가 새어 나간 누군가의 진짜 계정일 수 있어서입니다. 아래 20종은 여러 곳이 똑같이 넣어 본, 누구의 것도 아닌 흔한 값입니다. 첫 줄의 숫자를 보세요.

아이디 비밀번호 서로 다른 출발지
admin admin 32곳 (368회 · 곳당 약 11.5회)
345gs5662d34 345gs5662d34 22곳 (곳당 1회)
root 3245gs5662d34 10곳
root password 8곳
root root 7곳
root 12345 7곳
root (빈칸) 6곳
root P@ssw0rd 6곳
user user 6곳
root admin 6곳
root 000000 6곳
daniel daniel 5곳
root 123456789 5곳
oracle oracle 5곳
ftpuser 123456 5곳
admin admin123 5곳
admin P@ssw0rd 5곳
root 123456 5곳
root 12345678 5곳
root 1112 5곳

사실 admin/admin 은 32곳에서 368번 들어왔습니다. 한 곳이 11번 넘게 같은 조합을 넣어 본 셈입니다. 둘째 줄의 이상한 문자열은 정반대입니다. 22곳이 딱 한 번씩만 넣었습니다. 비밀번호 칸이 아예 빈 root 도 6곳에서 들어왔습니다.

어제 하루 전체

사실 문이 실제로 열리는 첫 번째 서버의 하루 집계입니다. 오른쪽 칸을 함께 보세요. 숫자 하나만으로는 크기가 잘 안 잡힙니다.

항목 9월 27일 견줄 것
세션 5,617건 15.4초에 한 번 · 9/22(829건)의 약 6.8배
고유 출발지 203곳 한 곳당 평균 27.7세션
로그인 시도 5,233회 16.5초에 한 번
명령 9,747개 8.9초에 하나 · 9/22(790개)의 약 12.3배
포트 2222 (SSH) 4,989세션 전체의 88.8%
포트 2223 (텔넷) 628세션 11.2% — 그런데 파일을 받아 간 두 세션은 모두 텔넷

사실 세션은 닷새 전의 7배 가까이, 명령은 12배 넘게 늘었습니다. 왜 이렇게 늘었는지는 뒤의 ’우리가 모르는 것’에 적었습니다. 서버 안에서 친 명령을 종류별로 나누면 이렇습니다.

무엇을 하려 했나 횟수
정찰 — 시스템 살펴보기 4,481회
실행 권한 부여 2,099회
지속성 — SSH 키 심기 25회
흔적 삭제 23회
파일 다운로드 22회
정찰 — 네트워크 18회
다운로드 후 실행 14회

사실 일곱 줄을 더하면 6,682입니다. 명령 9,747개와 3,065개 차이가 납니다. 그 3,065개가 무엇인지는 재료에 설명이 없습니다. ’SSH 키 심기’는 서버에 비밀번호 없이 다시 들어올 수 있는 열쇠를 몰래 등록해 두는 일입니다. 그 열쇠 파일(389바이트 공개키 a8460f44…)은 21곳에서 한 번씩, 모두 21번 들어왔습니다. 389바이트는 문자 메시지 서너 통 분량입니다. libssh_0.9.6 이라는 접속 프로그램 지문(f555226d…)은 어제 22곳에서 보였습니다. 지금까지 모두 520곳입니다. 닷새 전과 비슷한 수준입니다.

사실 두 번째 서버(센서 02)는 문을 열어 주지 않고 누가 두드렸는지만 적습니다. 그래서 로그인 성공도, 명령도, 자격증명도 여기엔 없습니다. 어제는 54,243건이 433곳에서 왔습니다. 1.6초에 한 번입니다. 그중 97.8%인 53,038건이 VNC 였습니다. VNC 는 멀리서 다른 컴퓨터의 화면을 보고 조작하는 기능입니다. 원격 데스크톱(RDP)은 닷새 전 11,698건에서 어제 567건으로 약 95% 줄었습니다. 받아 간 파일은 0건입니다.

같은 날 두 번째 서버 이야기는 영상으로 따로 만들었습니다. 서로 다른 두 곳이 두드린 횟수가 한 자리까지 같았던 일입니다.

공격자가 쓴 수법을 국제 분류표에 대응시키면

MITRE ATT&CK 은 공격 수법마다 번호를 붙여 둔 국제 목록입니다. 어제 본 행동을 그 번호에 맞추면 이렇습니다. ID 를 누르면 원문 설명으로 갑니다. 우리 말을 그대로 믿지 말고 직접 확인해 보시라고 링크를 겁니다.

  • T1110.001Brute Force: Password Guessing — 로그인 시도 5,233회, admin/admin 32곳 368회추정
  • T1078.001Valid Accounts: Default Accounts — 주요 세션 5건 모두 로그인 성공, 인용 조합이 기본값 계열추정
  • T1059.004Command and Scripting Interpreter: Unix Shell — 텔넷 셸에서 명령 11개, 셸 스크립트 kla.sh추정
  • T1105Ingress Tool Transfer — '파일 다운로드' 의도, 검체 11건추정
  • T1222.002File and Directory Permissions Modification: Linux and Mac — '실행 권한 부여' 의도추정
  • T1082System Information Discovery — 하루 전체 '정찰 — 시스템' 4,481회. 주제 세션 의도에는 없다추정
  • T1098.004Account Manipulation: SSH Authorized Keys — ATK-CA5936 · EC7309 · 015624 의도, 공개키 21곳. 주제 세션과는 관계없다추정
  • T1070Indicator Removal — 하루 전체 흔적 삭제 23회. 주제 세션과는 관계없다추정

사실 여덟 줄 모두 **[추정]**입니다. 우리 손에 있는 건 명령의 ’의도 분류 결과’와 횟수, 그리고 파일의 이름·크기·종류까지입니다. 명령 원문도 파일 내용도 없습니다. 분류표에 맞추는 건 늘 해석입니다. 그리고 아래 세 줄(T1082 · T1098.004 · T1070)은 어제의 보냉가방과 상관없는 하루 전체 이야기입니다.

전에 이런 모양이 있었다

추정 Mirai 봇넷과 그 파생 계열 (2016~). 텔넷 기본 계정으로 들어갑니다. 그다음 /bins/ 같은 웹 경로에서 CPU 종류별 실행파일을 여러 벌 받습니다. 그중 맞는 것이 실행되게 하는 구조입니다. 다만 소스코드가 공개된 계열이라, 서로 관계없는 운영자들도 같은 이름 규칙을 씁니다. (출처 유형: 미국 법무부 유죄인정 기록, 다수 보안업체 공개 분석 보고서)

Gafgyt(Bashlite) 계열 (2014~). 셸 스크립트 하나가 CPU 종류별 정적 실행파일을 차례로 받아 실행하는 구조입니다. ’가방 하나 + 반찬 통 여러 개’가 한 세션에 내려온 어제 모습과 생김새가 같습니다. (출처 유형: 다수 보안업체 공개 분석 보고서)

사실 여기서 멈춥니다. 검체 분류 서비스(VirusTotal)가 연동돼 있지 않습니다. MalwareBazaar 태그도 오늘 재료에 없습니다. 그래서 어제 파일이 Mirai 계열이라는 판정은 하지 않습니다. 닮은 건 구조와 이름 짓는 방식까지입니다.

그래서 뭘 해야 하나

가방을 보내는 쪽은 우리가 막을 수 없습니다. 바꿀 수 있는 건 현관문이 열려 있느냐, 가게에서 오는 배달을 받아 주느냐입니다.

사실 1. 기본 계정·쉬운 비밀번호를 그대로 쓰고 있다 · 가능성 높음 어제 주요 세션 다섯 건은 모두 로그인에 성공했습니다. 위 표의 admin/admin 은 32곳이 368번 넣어 봤습니다. 빈 비밀번호 root 도 6곳에서 들어왔습니다. 어제 확인되는 진입 경로는 자격증명뿐이었습니다. 주제 세션은 로그인 후 47.12초 만에 CPU 종류별 실행파일 아홉 개를 손에 넣었습니다.

사실 2. 관리 포트, 특히 텔넷을 인터넷에 직접 열어 두고 있다 · 가능성 높음 어제 텔넷은 전체 세션의 11.2%뿐이었습니다. 그런데 주요 세션 다섯 건 중 넷이 텔넷이었습니다. 실행파일을 받아 간 두 세션(ATK-9D3922 · ATK-BDB53E)도 모두 텔넷이었습니다. 집에 있는 공유기나 카메라 설정 화면에서 텔넷이 켜져 있는지 확인해 보세요.

추정 어제 내려온 ARM·MIPS·PowerPC·m68k 실행파일은 텔넷이 열린 공유기·CCTV 같은 장비를 겨냥한 구성입니다. 뚫리면 장비 하나가 통째로 넘어갑니다.

사실 3. 밖으로 나가는 연결을 막지 않고 있다 · 가능성 높음 어제 ‘파일 다운로드’ 의도가 22회, ’다운로드 후 실행’이 14회였습니다. 주제 세션은 176[.]65[.]139[.]196/bins/ 에서 10건을 받아 갔습니다. 아홉 통 중 여덟이 정적 링크입니다. 숟가락까지 들어 있어서 CPU 만 맞으면 어느 리눅스에서든 돌아갑니다. 서버가 밖으로 나가는 길이 막혀 있었다면 어땠을까요? 이 세션은 가방을 받아 오는 단계에서 끝났을 겁니다. 이 글의 비유로 말하면 “이 가게 배달은 받지 않는다”입니다. 반찬이 몇 번 바뀌든 상관없습니다.

추정 4. 접속 빈도 제한(fail2ban 등)이 없다 · 가능성 중간 fail2ban 은 “몇 번 틀리면 한동안 문을 잠그는” 도구입니다. admin/admin 쪽은 곳당 11.5회꼴이라 “5번 틀리면 잠금” 같은 규칙에 걸렸을 겁니다. 반면 345gs5662d34 조합(22곳 22회)과 공개키(21곳 21회)는 곳당 딱 한 번입니다. 이런 쪽은 빈도 제한으로 막을 수 없습니다. 두 종류가 섞여 있어서 ’중간’으로 둡니다. 기본 계정 없애기와 함께 써야 효과가 있습니다.

사실 5. 비밀번호 로그인을 허용하고 열쇠 방식을 쓰지 않는다 · 가능성 낮음 주제 세션은 텔넷이었습니다. 텔넷에는 열쇠 방식이라는 선택지가 없습니다. SSH 쪽 ATK-CA5936 은 로그인에 성공했습니다. 하지만 재료에 인증 방식 칸이 없어서 비밀번호로 들어왔다고 확정할 수 없습니다. 어제의 주제 경로인 텔넷은 끄는 것 말고는 답이 없습니다.

추정 6. 로그를 모으지 않거나 이상 행동 감시가 없다 · 가능성 중간 하루 전체에서 흔적 삭제가 23회 있었습니다. 주제 세션에는 없었습니다. 우리는 화면 녹화가 5,079건 있어서 세션 흐름을 다시 맞출 수 있었습니다. 기록이 없었다면 같은 가게가 닷새 만에 반찬을 전부 갈아 담았다는 사실 자체를 몰랐을 겁니다.

사실 어제 관측한 유포지 176[.]65[.]139[.]196 · 160[.]119[.]66[.]206 · 64[.]89[.]160[.]48 은 C-TAS(한국인터넷진흥원의 사이버 위협정보 공유 체계) 신고 대상입니다. 다만 우리가 확인할 수 있는 건 전송이 성공했다는 것까지입니다. KISA 쪽에 실제로 올라갔는지는 따로 확인해야 합니다.

우리가 모르는 것

이 블로그가 다른 곳과 다른 지점입니다. 아는 것만큼 모르는 것도 적습니다.

가방과 반찬에 대해

  • [확인 불가] 아카이브에 9/9 · 9/11 · 9/12 · 9/14 · 9/16 · 9/18 · 9/19 · 9/21 · 9/23~9/26 브리프가 없습니다. ’닷새 만에’는 9/22 브리프와 비교한 말입니다. 그 사이 이 가게가 반찬을 몇 번 바꿨는지는 모릅니다.
  • [확인 불가] px86 · parm5 · parm6 은 9/22 와 크기가 같고 해시만 다릅니다. 무엇이 바뀌었는지(설정값인지, 만든 시각인지, 다른 무엇인지) 파일 내용이 재료에 없어 판단할 수 없습니다.
  • [확인 불가] parm7 만 디버그 정보가 남아 있는 이유를 모릅니다. 실수인지 의도인지 이 재료로는 가릴 수 없습니다.
  • [확인 불가] 64[.]89[.]160[.]48 의 parm7(60,088바이트, 목차 없음)이 176[.]65[.]139[.]196 의 parm7(259,684바이트)과 어떤 관계인지 모릅니다. ’목차 없음’은 압축된 실행파일에서 흔히 보이지만, 압축 여부를 알려 주는 칸이 없어 확정하지 않습니다.
  • [확인 불가] 아홉 통 중 어느 것이 실제로 실행됐는지 기록이 구분하지 않습니다. ‘다운로드 후 실행’ 의도는 있지만 명령 원문과 화면 녹화 내용이 없습니다.
  • [확인 불가] ATK-9D3922 와 파일 11건을 잇는 근거는 배달자 칸과 개수 합(11 = 다운로드 수)이 맞는다는 것입니다. 세션과 파일을 1:1 로 잇는 칸은 없습니다.

다른 세션과 집계에 대해

  • [확인 불가] ATK-EC7309 와 ATK-015624 는 ‘파일 다운로드’ 의도가 있는데 다운로드 수가 0 입니다. 두 세션은 명령 17개 · 의도 5개 · 기록 촘촘함 17 이 모두 같습니다. 받으려다 실패했는지, 같은 스크립트를 썼는지 알 수 없습니다.
  • [확인 불가] ATK-CA5936 의 지문 16443846… 이 어제 접속 프로그램 지문 목록(12개)에 없습니다. 그 목록이 전체 45개 묶음 중 상위 일부만 보여 주는 것인지 명시돼 있지 않습니다. 주제 세션은 텔넷이라 지문 자체가 없어서 묶음 분석을 적용하지 않았습니다. 지문은 프로그램의 지문이지 사람의 지문이 아닙니다.
  • [확인 불가] 명령 9,747개와 의도 분류 합 6,682의 차이 3,065개가 무엇인지 재료가 설명하지 않습니다.
  • [확인 불가] 첫 번째 서버 세션이 9/22 대비 약 6.8배로 뛴 원인을 모릅니다. 첫 번째 서버에는 상위 출발지 목록이 없어서, 한두 곳이 만든 숫자인지도 확인할 수 없습니다.
  • [확인 불가] 기록 촘촘함(completeness)의 계산식이 재료에 없습니다.
  • [확인 불가] 두 번째 서버 상위 출발지에 176.65.x.x(ATK-D4B7A8, 200건)가 있습니다. 가려진 주소라 유포지 176[.]65[.]139[.]196 과 같은 기계인지 알 수 없습니다. 복원하지 않습니다. 별칭이 두 서버 사이에서 같은 출발지를 가리킨다는 보장도 문서화돼 있지 않습니다.
  • [확인 불가] VNC 53,038건이 우리 기록의 최대치인지는 확인하지 않았습니다. 비교한 날은 9/22(33,287건)와 9/6(48,605건)뿐입니다.
  • [확인 불가] RDP 이름표 Administr 가 9/22 5,159회에서 어제 2회로 줄어든 원인을 모릅니다.
  • [확인 불가] 두 번째 서버의 adb 상세 기록이 어제 재료에 없습니다. ADB(안드로이드 기기를 연결해 조작하는 통로) 408세션에 무엇이 들어왔는지, 몇 곳에서 왔는지 모릅니다.

일부러 빼거나 연결하지 않은 것

  • [제외] 평문 지표로 남은 Discord 웹훅 1건(9/22 에도 있었음)은 어느 세션·파일과 연결되는지 재료에 없어서 사실 관계에서 뺐습니다. 웹훅 토큰은 남이 악용할 수 있어 옮기지 않습니다.
  • [확인 불가] C-TAS 신고는 전송 성공까지만 확인됩니다. KISA 쪽 적재·활용 여부는 따로 확인해야 합니다.
  • [제외] 배경 통계(KISA 보안공지 CVE 7,642건 · CISA KEV 408건 · 랜섬웨어 연계 확인 101건, EPSS 상위 CVE-2018-13379 · CVE-2022-26134 · CVE-2021-44228 · CVE-2023-4966 · CVE-2024-3400)는 어제 관측과 직접 연결되지 않습니다. 어제 침입 경로는 전부 자격증명이었습니다.

아예 판단하지 않는 것

  • 통신사·조직(ASN·ISP) — 관련 데이터베이스가 없습니다. 추정하지 않습니다.
  • 지리 위치 — 같은 이유로 모릅니다. IP 지리정보는 애초에 누가 했는지를 가리는 근거가 되지 못합니다. 이 글은 어떤 국가·기업·개인도 공격자로 지목하지 않습니다.
  • VPN·Tor·클라우드 여부 — 판별할 수단이 없습니다.
  • 검체 분류(VirusTotal) — 연동돼 있지 않습니다. 검체 분류는 MalwareBazaar 태그를 씁니다. 어제 새 실행파일 아홉 개가 어떤 계열로 탐지되는지 이 글로는 말할 수 없습니다.
  • 접속 프로그램 문자열(User-Agent) — 두 서버 모두 웹(HTTP)이 아닙니다. 첫 번째는 SSH·텔넷, 두 번째는 SMB·RDP·VNC·MSSQL·LDAP·ADB 입니다. 웹 공격은 별도 소스에서 다룹니다.
  • 취약점 번호(CVE) 연결 — SSH·텔넷 공격은 대부분 특정 취약점을 참조하지 않습니다. 두 번째 서버도 접속 규격을 맞추는 단계라 마찬가지입니다.

같은 보냉가방이 세 번째로 왔습니다. 가방은 37일 동안 한 올도 달라지지 않았습니다. 안에 든 반찬 통은 여섯 개에서 아홉 개로 늘었고, 아홉 통 모두 새로 담겨 있었습니다. 세 통은 무게까지 똑같았는데 속만 달랐습니다. 한 통에는 레시피 메모가 붙어 있었습니다. 닷새 전에 찍어 둔 사진 목록으로는 아홉 통 중 하나도 알아보지 못합니다.

무엇을 바꿔 담았는지, 누가 보냈는지는 모릅니다. 모르는 건 모른다고 둡니다. 그래도 할 수 있는 일은 분명합니다. 현관문(텔넷)을 닫고, 가게에서 오는 배달(밖으로 나가는 연결)을 받지 않고, 가게 주소를 오래 기억해 두는 것. 사진은 닷새 만에 아홉 장이 다 바뀌었습니다. 가게 주소는 37일째 그대로였습니다.


관측일은 2026년 9월 27일이고, 이 글은 다음 날 정리했습니다. 출발지 IP 는 브리프에 가림 처리된 형태(108.59.x.x, 160.119.x.x, 160.250.x.x, 130.12.x.x, 2.29.x.x, 176.65.x.x) 그대로 옮겼고 복원하지 않았습니다. 유포지 주소는 실수로 접속되지 않도록 디팽(hxxp://, [.]) 상태를 본문과 IOC 블록 모두에서 유지했습니다. 자격증명은 서로 다른 IP 3곳 이상에서 반복 관측된 조합 20개만 원문 인용했고, 나머지 356개는 개수만 밝히고 값은 적지 않았습니다. 통신사·국적·VPN 여부처럼 우리에게 계측 수단이 없는 항목은 추정하지 않고 “모른다”로 남겨 뒀습니다.