SecurityHeroblog

이름표를 갈아 달았다 — 목록은 이틀 만에 빗나갔다

어제 우리 허니팟에 이틀 만에 실행파일이 돌아왔습니다. 이틀 전 유포지와 주소 앞자리가 같은 옆 번지에서, 파일 이름 규칙만 통째로 바뀐 채로요. 미리 적어둔 악성 파일 이름 열두 개는 하나도 걸리지 않았고, 대신 하루에 세 번 반복된 5초짜리 행동이 남았습니다.

학교에서 사람을 알아보는 가장 빠른 방법은 이름표입니다. 가슴에 붙은 글자 몇 개만 보면 됩니다. 그래서 “이 이름들은 매점 출입 금지” 같은 걸 만들면 아주 잘 돌아갑니다 — 이름표를 갈아 달기 전까지는요.

이름표는 바꿀 수 있습니다. 그런데 바꾸기 어려운 것도 있습니다. 매점에 들어가서 늘 같은 것을 같은 순서로 집어 나오는 습관 같은 것. 삼각김밥 먼저, 우유, 그다음 젤리. 이름표를 떼고 새로 달아도 그 순서는 그대로입니다.

어제 우리 서버에 남은 기록이 정확히 그 장면이었습니다. 이름표는 갈렸고, 집어 나오는 순서는 그대로였습니다.

먼저, 우리가 적어 둔 이름표 목록

사실 우리는 악성 파일이 놓여 있는 주소 12개를 감시 목록에 올려 두고 있습니다. 전부 hxxp://31[.]77[.]227[.]121/bins/ 아래의 parm·parm5·parm6·parm64·parm7·pm68k·pmips·pmpsl·pppc·psh4·pspc·x86_64 입니다. 주소는 일부러 망가뜨려 적었습니다(hxxp://, [.]) — 그대로 복사해 붙여 넣어도 접속되지 않습니다.

사실 규칙이 보이시나요. /bins/ 라는 폴더 이름, 그리고 p 뒤에 CPU 종류를 붙인 파일 이름. 이게 우리가 갖고 있던 이름표 목록입니다.

사실 이 12개는 그냥 얻어진 게 아닙니다. UPX 라는 압축으로 싸여 있던 파일을 풀어야만 나온 주소들입니다. 압축된 겉면만 봐서는 주소가 하나도 보이지 않습니다. 손이 꽤 들어간 목록입니다.

사실 그리고 그저께(8/21) 처음 나타난 유포지 176[.]65[.]139[.]196 은 이 규칙과 글자까지 맞아떨어졌습니다. /bins/ 경로에 px86·pmips. 처음 보는 주소인데도 첫날에 바로 같은 계열로 알아볼 수 있었던 이유가 그것입니다.

사실 어제, 실제로 내려온 파일 이름은 이랬습니다. telnet.sh·daredevil.armv7l·daredevil.mips·daredevil.mipsel. 폴더 경로도 없습니다. 12개 목록의 어떤 이름과도 겹치지 않습니다.

추정 이름표를 갈아 단 겁니다. 이틀입니다. 이름만으로 만든 목록의 유통기한이 이만큼이었습니다.

그런데 학번 앞자리는 같았습니다

사실 어제 그 파일 네 개가 전부 내려온 곳은 hxxp://176[.]65[.]139[.]202 한 곳입니다. 이 주소는 8/16부터 8/22까지 일곱 날치 기록 어디에도 없습니다. 어제가 처음입니다.

사실 그런데 그저께 유포지는 176[.]65[.]139[.]196 이었습니다. 앞의 세 마디가 같습니다. IP 주소는 점으로 나뉜 네 마디인데, 앞 세 마디가 같다는 건 같은 주소 블록 안에 있다는 뜻입니다. 학번 앞자리가 같은 것과 비슷합니다.

사실 여기서 한 걸음 더 나가면 안 됩니다. 같은 반이라고 같은 사람은 아닙니다. 인터넷 주소를 빌려주는 회사들은 나란히 붙은 주소를 서로 아무 관계 없는 사람들에게 나눠 줍니다. 옆 번지에 산다는 것과 같은 집에 산다는 것은 다릅니다.

사실 게다가 우리에게는 그 두 주소가 같은 회사 소속인지 확인할 수단조차 없습니다. 어느 사업자의 주소인지 알려주는 데이터베이스를 갖고 있지 않습니다. 그래서 이 자리에서는 “모른다”가 정답입니다.

어제 하루를 시간 순서로

하루치를 순서대로 늘어놓으면 이렇게 됩니다. 맨 위 두 줄과 맨 아래 10:19 줄, 이 세 줄의 숫자가 서로 얼마나 똑같은지 눈여겨보세요. 초 단위까지 닮아 있습니다.

  1. 사실 어제의 주제 세션 ①. ATK-31C779(94.154.x.x), 텔넷 로그인 성공. 약 5.11초 동안 명령 3개, 다운로드 4건. 의도 4종 — 정찰(시스템) · 파일 다운로드 · 실행 권한 부여 · 다운로드 후 실행. completeness 25. TTY 녹화됨(내용 미포함). 텔넷이라 지문·클라이언트 값은 빈 문자열이다
  2. 사실 ATK-31C779 가 유일한 전달 출처인 검체는 정확히 4종이고 각 관측 3회다. ① hxxp://176[.]65[.]139[.]202:80/telnet.sh — 2,107바이트 POSIX 셸 스크립트(ad19b70c…) ② hxxp://176[.]65[.]139[.]202/daredevil.armv7l — 48,352바이트 ELF 32-bit LSB ARM EABI4, statically linked, no section header(c71d74ce…) ③ hxxp://176[.]65[.]139[.]202/daredevil.mips — 57,104바이트 ELF 32-bit MSB MIPS-I, statically linked, no section header(344bbdca…) ④ hxxp://176[.]65[.]139[.]202/daredevil.mipsel — 58,848바이트 ELF 32-bit LSB MIPS-I, statically linked, no section header(9f1897ce…). 네 건 합계 166,411바이트
  3. 사실 주제 세션 ②. 같은 별칭 ATK-31C779 가 첫 세션 종료 약 53.8초 뒤에 다시 들어왔다. 약 5.03초, 명령 3개, 다운로드 4건, 의도 4종, completeness 25 — 첫 세션과 모든 값이 같다
  4. 사실 ATK-F2B80A(121.161.x.x), 텔넷 로그인 성공. 약 32.6초 동안 명령 48개(어제 최다), 다운로드 12건(어제 최다), completeness 43(어제 최고값). 그런데 의도 배열이 비어 있다. 이 별칭이 유일한 전달 출처인 검체는 1바이트 빈 파일(01ba4719…, 11회)과 202바이트 POSIX 셸 스크립트(0c99433c…, 1회)이며 11+1=12 로 다운로드 수와 일치한다. 아카이브 대조상 8/21 의 ATK-792ADF 와 명령 48개·다운로드 12건·검체 해시 2종·의도 0개·completeness 43 이 전부 같고 지속 시간만 약 23.7초에서 약 32.6초로 늘었다
  5. 사실 ATK-ADE2BE(45.43.x.x), 텔넷 로그인 성공. 약 60.6초 동안 명령 17개. 의도 5종으로 어제 최다 — 정찰(시스템) · 파일 다운로드 · 실행 권한 부여 · 다운로드 후 실행 · 지속성(SSH 키 심기). 그런데 다운로드 수는 0이다. completeness 17. 8/18(ATK-C17F4E) · 8/19(ATK-103570) · 8/20(ATK-B4B2E2) · 8/21(ATK-4CA329) · 8/22(ATK-5A0689)에 이어 여섯 번째로 같은 형태이며, 명령 17개·의도 5종·다운로드 0건·completeness 17 까지 8/21 과 완전히 일치한다
  6. 사실 주제 세션 ③. ATK-31C779 의 세 번째 방문. 두 번째 세션 종료로부터 약 10시간 6분 40초 뒤다. 약 4.91초, 명령 3개, 다운로드 4건, 의도 4종, completeness 25 — 앞의 두 세션과 모든 값이 같다. 새벽에 두 번, 낮에 한 번, 세 번 다 제지되지 않았다
  7. 사실 유포지 176[.]65[.]139[.]202 는 8/16~8/22 일곱 개 기록 어디에도 없다. 8/21 에 첫 관측으로 기록한 176[.]65[.]139[.]196 과 앞 세 마디가 같지만 규칙은 다르다 — 8/21 은 /bins/ 경로·'p+아키텍처' 이름(px86·pmips)·statically linked stripped·133,452~244,420바이트였고, 어제는 경로 없는 루트·'daredevil.아키텍처' 이름·no section header·48,352~58,848바이트다. 8/22 는 ELF 가 0건이었으므로 이틀 만의 재등장이다
  8. 사실 hxxp://5[.]182[.]210[.]174/ok 에서 1,608바이트 Bourne-Again 셸 스크립트가 어제도 내려왔는데, 같은 URL·같은 크기로 서로 다른 해시 2종이 기록됐다 — d3e76949… 와 31283c34…, 둘 다 출처 ATK-10149C 한 곳·각 1회. 하루 안에 2종이 나온 것은 8/21 에 이어 두 번째이며, 이 URL 의 해시는 8/18~어제까지 누적 7종이다(6aa5054a · b7728639 · c850a285 · 7a5dcc03 · 6ff53177 · d3e76949 · 31283c34)
  9. 사실 389바이트 OpenSSH RSA 공개키(a8460f44…)를 서로 다른 출처 6곳이 남겼다. 이 해시는 8/16~8/22 에도 있었으므로 여드레 연속이다. 출처 수는 8/20 8곳 → 8/21 10곳 → 8/22 8곳 → 어제 6곳이다. 의도 분류의 '지속성 — SSH 키 심기'는 7회로, 8/21 11회 → 8/22 9회 → 어제 7회로 사흘째 줄고 있다
  10. 사실 명령 의도 분포 — 정찰(시스템) 980회로 전체 명령 1,863개의 약 52.6%(8/22 는 26.1%), 실행 권한 부여 212회, 파일 다운로드 55회, 다운로드 후 실행 50회, 흔적 삭제 7회, 지속성(SSH 키 심기) 7회, 정찰(네트워크) 1회. 8/22 에 1회 기록됐던 '방어 무력화'는 어제 항목 자체가 없다. 의도 분류 합계는 1,312회로 명령 총계와 551 차이가 난다

사실 표에서 눈에 걸리는 줄이 둘 있습니다. 하나는 02:13 의 ATK-F2B80A — 명령도 다운로드도 어제 최다인데 의도가 하나도 분류되지 않았습니다. 다른 하나는 06:52 의 ATK-ADE2BE — 의도는 5종으로 가장 넓은데 받아간 파일은 0건입니다. 둘 다 숫자는 큰데 무슨 일이 있었는지 설명할 근거가 없습니다. 그래서 어제의 주제로 삼지 않았습니다.

5초, 하루 세 번, 값이 하나도 안 틀림

사실 어제 주제로 삼은 것은 ATK-31C779(94.154.x.x)입니다. 텔넷으로 들어왔습니다. 텔넷은 아주 오래된 원격 접속 방식입니다. 쉽게 말해 인터넷 너머에서 그 기계의 명령창을 직접 두드릴 수 있게 열어 두는 통로인데, 비밀번호가 암호화되지 않고 그대로 흘러갑니다.

사실 머문 시간은 약 5.11초입니다. 그 사이 명령 3줄을 넣고 파일 4개를 받아갔습니다. 라면 봉지를 뜯는 데 걸리는 시간쯤입니다.

사실 그리고 53.8초 뒤에 다시 들어왔습니다. 약 5.03초, 명령 3개, 다운로드 4건. 값이 첫 번째와 하나도 다르지 않습니다.

사실 세 번째는 약 10시간 6분 뒤인 10:19:30 입니다. 약 4.91초, 명령 3개, 다운로드 4건. 역시 같습니다. 새벽에 두 번, 낮에 한 번. 세 번 다 로그인에 성공했고, 세 번 다 아무것도 막지 않았습니다.

사실 매점에 들어가서 늘 같은 것을 같은 순서로 집어 나오는 그 습관이 여기 있습니다. 정찰 → 파일 받기 → 실행 권한 주기 → 실행. 세 번 모두 의도 4종이 같고 completeness 값도 25로 같습니다.

추정 사람이 손으로 하면 이렇게 안 됩니다. 5초짜리를 세 번 반복하면서 명령 개수와 파일 개수가 한 번도 안 틀리는 건, 정해진 순서가 그대로 재생됐다는 뜻에 가깝습니다.

사실 다만 여기서도 선을 그어야 합니다. 우리는 출발지 IP 를 그대로 두지 않고 ATK- 로 시작하는 별칭으로 바꿔서 기록합니다. 이때 소금(salt)이라는 값을 섞기 때문에 날짜가 다르면 같은 IP 라도 다른 별칭이 됩니다. 그리고 마스킹으로 남는 것은 앞 두 마디뿐입니다 — 94.154.x.x 대역에만 주소가 65,536개나 있습니다. 8/21에 실행파일을 받아간 세션도 표기가 94.154.x.x 였지만, 같은 곳이라고 말할 수 없습니다.

받아간 네 개가 무엇이었나

사실 네 개의 정체는 이렇습니다.

파일 크기 정체
telnet.sh 2,107바이트 POSIX 셸 스크립트
daredevil.armv7l 48,352바이트 ELF 32-bit LSB ARM EABI4 · statically linked · no section header
daredevil.mips 57,104바이트 ELF 32-bit MSB MIPS-I(빅엔디안) · 위와 동일
daredevil.mipsel 58,848바이트 ELF 32-bit LSB MIPS-I(리틀엔디안) · 위와 동일

낯선 말이 넷 있으니 그 자리에서 풀겠습니다.

  • 셸 스크립트 — 명령을 순서대로 적어 둔 메모지입니다. 사람이 한 줄씩 치는 대신 파일 하나를 실행하면 적힌 순서대로 돌아갑니다. 2,107바이트면 A4 한 장에 못 미치는 글자 분량입니다.
  • ELF — 리눅스에서 쓰는 실행파일 형식입니다. 윈도우의 .exe 에 해당한다고 보면 됩니다.
  • statically linked(정적 링크) — 필요한 부품을 전부 안에 넣고 다닌다는 뜻입니다. 밖에서 뭘 빌리지 않으니, 그 CPU 를 쓰는 리눅스라면 종류·버전과 상관없이 돌아갑니다.
  • no section header(섹션 헤더 없음) — 파일 안의 구역을 나눠 적어 둔 안내판을 떼어냈다는 뜻입니다. 뜯어보는 쪽을 어렵게 만듭니다.

사실 armv7l·mips·mipsel 은 전부 CPU 종류입니다. 서로 호환되지 않습니다. 그래서 세 개를 다 받아간 겁니다 — 어느 것이 맞는지 모르니 셋 다 챙기는 방식입니다.

사실 여기서 어제 데이터의 특징이 하나 나옵니다. 일반 PC·서버에서 도는 x86 계열 실행파일은 한 건도 없습니다. ARM·MIPS·MIPSEL 은 공유기·IP 카메라·NAS 같은 장비 쪽에서 흔한 규격입니다. 8/21에는 x86 과 MIPS 가 함께 왔었는데, 어제는 장비 쪽만 왔습니다.

사실 네 개를 합치면 166,411바이트입니다. 사진 한 장이 보통 이보다 훨씬 큽니다. 그게 약 5초 만에 들어왔고, 세 번 합치면 약 487KB 가 통과했습니다.

추정 어제 이 호스트를 이어서 볼 수 있게 해 준 것은 이름이 아닙니다. ① 주소 앞 세 마디가 이틀 전 호스트와 같다는 점, 그리고 ② ‘텔넷으로 로그인 → 작은 셸 스크립트 하나 → CPU 종류별 정적 링크 실행파일’ 이라는 행동의 모양이었습니다. 이름표가 아니라 집어 나오는 순서 쪽입니다.

지문이 잡히는 층과, 실제로 뚫리는 층

사실 SSH 로 들어오는 접속에는 클라이언트 지문이 남습니다. 접속 프로그램이 처음 건네는 인사말의 구성이 도구마다 조금씩 달라서, 그 값을 묶으면 “출발지는 달라도 같은 프로그램”이라는 걸 알 수 있습니다. 어제 이 지문 묶음은 40개로 8/22 와 같고 기록상 최다 타이입니다(8/17 33 → 8/18 36 → 8/19 37 → 8/20 37 → 8/21 38 → 8/22 40).

사실 가장 큰 묶음은 f555226df1963d1d3c09daf865abdc9a(SSH-2.0-libssh_0.9.6)로, 어제 IP 7곳·누적 201곳입니다. 8/22 에는 8곳·누적 182곳이었으니 누적이 하루에 19곳 늘었습니다.

사실 그런데 목록에 오른 9개 묶음은 하나도 검체를 내려보내지 않았습니다. 사흘 연속 0개입니다.

사실 반대로 어제 실행파일 세 개를 실제로 받아간 세션은 텔넷이라 지문·클라이언트 값이 빈 문자열입니다. 완결성 상위 5개 세션이 전부 그렇습니다. 텔넷에는 그 인사말 절차가 애초에 없습니다.

추정 정리하면 지문이 잡히는 층(SSH · 1,246세션)과 실제로 물건이 내려오는 층(텔넷 · 277세션)이 사흘째 갈라져 있습니다. 지문 묶음을 40개나 세어 봐도, 어제 실행 바이너리가 어디로 들어왔는지는 그 40개가 알려 주지 않습니다.

사실 그래서 어제 세 세션을 하나로 묶은 근거는 지문이 아닙니다. 별칭(ATK-31C779)과 세션의 모양(명령 3개·다운로드 4건·의도 4종·completeness 25), 그리고 네 검체의 전달 출처가 이 별칭 한 곳뿐이라는 점입니다. 이건 같은 도구·같은 자동 실행 순서를 썼다는 뜻이지 같은 조직·같은 사람이라는 뜻이 아닙니다. 지문 값 역시 빌드의 지문이지 사람의 지문이 아닙니다 — 같은 배포판의 기본 접속 프로그램을 쓰는, 서로 모르는 사람들도 같은 값을 갖습니다.

어떻게 들어왔나 — 어제도 비밀번호입니다

사실 어제 로그인 시도는 1,187회입니다. 관측 구간을 하루로 놓고 보면 약 73초에 한 번꼴로 누군가 문고리를 돌려 본 셈입니다. 세션 1,523건은 약 57초에 한 번꼴로 새 접속이 들어온 것입니다. (다만 이 기록에 관측 구간이 명시돼 있지 않아, 하루 전체를 가정한 계산입니다.)

사실 출발지는 222곳입니다. 8/18(249곳) 이후 가장 많습니다. 한 곳당 평균 약 6.9세션, 약 5.3회 시도입니다.

사실 서로 다른 IP 3곳 이상에서 관측된 조합만 추리면 이렇습니다.

아이디 비밀번호 관측된 IP 수
admin admin 17곳
345gs5662d34 345gs5662d34 7곳
root admin 6곳
root root 6곳
root 12345 5곳
root 1234 5곳
root admin123 4곳
root (빈 비밀번호) 3곳
root passw0rd 3곳
root 123 3곳
admin admin123 3곳
admin 1234 3곳
root 123456 3곳
ftp ftp 3곳
root vizxv 3곳

사실 여덟 번째 줄을 보세요. 비밀번호 칸이 비어 있습니다. 서로 다른 세 곳이 각각 “그냥 빈칸”으로 로그인을 시도했습니다. 그게 통하는 기계가 있다는 걸 알고 있다는 뜻입니다.

사실 그리고 1,007개 조합은 싣지 않았습니다. 서로 다른 IP 3곳 미만에서만 나온 것들입니다(8/16 934 → 8/17 830 → 8/18 1,388 → 8/19 848 → 8/20 440 → 8/21 806 → 8/22 703 → 어제 1,007). 한 곳에서만 나온 조합은 어딘가에서 실제로 유출된 누군가의 계정일 수 있어서, 값은 쓰지 않고 개수만 셉니다.

사실 여기 이상한 점이 하나 있습니다. 로그인 시도 총량은 8/22의 약 3분의 1로 줄었는데, ’한두 곳에서만 나온 조합’은 오히려 1.43배가 됐습니다. 봇들이 서로 겹치지 않는 목록을 돌렸다는 뜻일 수 있지만, 데이터가 확인해 주지 않습니다.

사실 그리고 위 표에 실린 15개 조합의 시도를 다 합쳐도 97회입니다. 전체 1,187회의 약 8.2%. 우리가 공개할 수 있는 건 어제 관측의 일부라는 뜻입니다.

사실 어제도 CVE 나 익스플로잇을 참조한 침투 경로는 없었습니다. 전부 자격증명이었습니다.

남기고 간 것

어제 관측된 검체와 주소 전부입니다. 값을 누르면 복사됩니다 — 해시는 읽으라고 있는 게 아니라 차단 목록에 넣으라고 있습니다. hxxp:// 와 [.] 는 그대로 두었습니다.

sha256
ad19b70c4e523ef24baf5e062d2200e139b619b56049219d41cd0397faff2c402,107바이트 POSIX 셸 스크립트 · 출처 1곳(ATK-31C779) · 3회 · 8/16~8/22 에 없던 신규 해시이자 신규 호스트
url
hxxp://176[.]65[.]139[.]202:80/telnet.sh위 스크립트의 주소. 이 호스트는 어제가 첫 관측이다
sha256
c71d74ce79b23052d26619ccc3c967fa46d2fd97328369b22565ac84f902888248,352바이트 ELF 32-bit LSB ARM EABI4 · statically linked · no section header · 출처 1곳(ATK-31C779) · 3회 · 신규 해시
url
hxxp://176[.]65[.]139[.]202/daredevil.armv7l위 실행파일의 주소. 경로가 없고 이름 규칙이 감시 목록 12개와 겹치지 않는다
sha256
344bbdca6cc3f80f2d996398fa443c3dd7c98575b85cebc26df684ba04aa936957,104바이트 ELF 32-bit MSB MIPS-I(빅엔디안) · statically linked · no section header · 출처 1곳(ATK-31C779) · 3회 · 신규 해시
url
hxxp://176[.]65[.]139[.]202/daredevil.mips위 실행파일의 주소
sha256
9f1897ced87b33877e10b8185c97ba0ec386e53b04a82b5e942f05f56db18bd958,848바이트 ELF 32-bit LSB MIPS-I(리틀엔디안) · statically linked · no section header · 출처 1곳(ATK-31C779) · 3회 · 신규 해시
url
hxxp://176[.]65[.]139[.]202/daredevil.mipsel위 실행파일의 주소. 위 세 건과 합쳐 한 세션당 166,411바이트다
sha256
a6296a79f44e21b76604d2d2bbf795d2cf380f70e39d45fbf166707ff3b4a6a4306바이트 POSIX 셸 스크립트 · 출처 6곳(ATK-4DB3DE · ATK-862D72 · ATK-C1543C · ATK-F0EFFC · ATK-A840CC · ATK-34F42D) · 6회 · 8/17~8/22 와 같은 해시로 이레 연속이며, 출처 수는 8/22 15곳에서 6곳으로 줄었다
url
hxxp://185[.]93[.]89[.]72/wget위 스크립트의 주소. 이레 연속 같은 주소·같은 해시
sha256
a8460f446be540410004b1a8db4083773fa46f7fe76fa84219c93daa1669f8f2389바이트 OpenSSH RSA 공개키 · 출처 6곳(ATK-2AE2F2 · ATK-86A608 · ATK-77F398 · ATK-C26F79 · ATK-38BDE5 · ATK-B69AB0) · 6회 · URL 미기록 · 8/16~8/22 와 같은 해시로 여드레 연속. 8/17 기록은 이 파일을 '외부 다운로드가 아니라 세션 안에서 만들어진 것'으로 적었다
sha256
01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b1바이트, 종류를 알아볼 표식이 없는 빈 파일 · 출처 1곳(ATK-F2B80A) · 11회 · URL 미기록 · 8/17 121회·출처 2곳, 8/18·8/21·8/22 각 11회·출처 1곳, 어제 11회·출처 1곳으로 네 번째 같은 값이다
sha256
0c99433c7d433d65ab890dcee20b330f262379d532bc76f91e18f09ecfa5fb54202바이트 POSIX 셸 스크립트 · 출처 1곳(ATK-F2B80A) · 1회 · URL 미기록 · 8/21 에도 같은 해시가 1바이트 파일 11건과 함께 한 세션에서 나왔다
sha256
d3e769491e805b832c07c947c928b8ac419d2a9e2bc94ba2dc2dc75637ee4f361,608바이트 Bourne-Again 셸 스크립트 · 출처 1곳(ATK-10149C) · 1회 · 신규 해시
sha256
31283c34d08e608bfa2d2f785c6cd4b018635c8c6d5ca01cc8469089b23f1aa41,608바이트 Bourne-Again 셸 스크립트 · 출처 1곳(ATK-10149C) · 1회 · 위 d3e76949… 와 같은 URL·같은 크기·같은 출처인데 해시가 다르다 · 신규 해시
url
hxxp://5[.]182[.]210[.]174/ok위 두 스크립트의 주소. 주소도 크기도 그대로인데 내용만 바뀐다 — 8/18 이래 누적 7종
sha256
4af5a5c98ad132095c6fbe7b02c242153a190a01cc321e50a916a0ca46fbaa629바이트 ASCII 텍스트 · 출처 1곳(ATK-BECAD3) · 6회 · URL 미기록 · 8/18~8/22 에도 같은 해시가 있었다. 내용이 기록에 없어 무엇인지 판단하지 않는다
sha256
a9b1c85a7bd78dd1112ecc75c9070ea8c53078831a17aa09ebeb287fe6e21b729바이트 ASCII 텍스트 · 출처 1곳(ATK-0C24D1) · 1회 · URL 미기록 · 8/21 에도 아래 1193dde1… 과 짝으로 나왔으나 그때는 다른 별칭이다
sha256
1193dde1c831808bf6f2db6f5b850b846b8a7f870873ec3b8a347f21cc5d96e39바이트 ASCII 텍스트 · 출처 1곳(ATK-0C24D1) · 1회 · URL 미기록 · 위 a9b1c85a… 와 함께 이 별칭의 다운로드 2건을 이룬다
url
hxxp://31[.]77[.]227[.]121/bins/ 계열 12건 (parm · parm5 · parm6 · parm64 · parm7 · pm68k · pmips · pmpsl · pppc · psh4 · pspc · x86_64)압축을 풀어야만 나왔던 감시 목록. 어제도 다운로드 0건으로 나흘 연속이며, 계속 목록에 올려 둔다

사실 목록에서 hxxp://5[.]182[.]210[.]174/ok 두 줄이 눈에 걸립니다. 주소도 같고 크기도 1,608바이트로 같은데 해시만 다릅니다. 하루 안에 두 종류입니다. 8/18 이래 이 주소 하나에서만 누적 일곱 종류가 나왔습니다. 같은 자리에 놓인 파일이 조용히 바뀌었다는 뜻입니다. “이 파일은 위험함”이라고 해시에 이름표를 붙여 막는 방식이 왜 자꾸 늦는지, 이 두 줄이 답입니다.

사실 그리고 389바이트 OpenSSH RSA 공개키가 여드레째 같은 해시로 나옵니다. 389바이트면 문자 메시지 두어 줄 분량입니다. 이 작은 파일이 authorized_keys(허용된 열쇠 목록)에 한 줄로 들어가면, 비밀번호 없이 들어올 수 있는 열쇠가 현관에 하나 걸립니다. 비밀번호를 전부 바꿔도 그 열쇠는 남습니다.

공격 단계로 옮기면

관측된 행동을 MITRE ATT&CK 라는 국제 분류표에 대응시키면 이렇습니다. ID 를 누르면 원문 설명을 직접 볼 수 있습니다 — 우리 말을 믿지 않고 확인하셔도 됩니다. 전부 [추정]입니다. 우리가 본 것은 명령이지 공격자의 의도가 아닙니다.

  • T1110Brute Force추정
  • T1078.001Valid Accounts: Default Accounts추정
  • T1059.004Command and Scripting Interpreter: Unix Shell추정
  • T1082System Information Discovery추정
  • T1016System Network Configuration Discovery추정
  • T1105Ingress Tool Transfer추정
  • T1222.002File and Directory Permissions Modification: Linux and Mac추정
  • T1098.004Account Manipulation: SSH Authorized Keys추정
  • T1070Indicator Removal추정
  • T1608.001Stage Capabilities: Upload Malware추정

사실 두 줄에 단서를 붙여야 합니다. T1016(네트워크 정찰)은 어제 단 1회로 분류된 의도 하나에만 근거합니다. T1070(흔적 지우기)도 7회뿐이고, 명령 원문이 없어 무엇을 지웠는지 말할 수 없어서 더 세부적인 하위 기법은 붙이지 않았습니다. 마지막 T1608.001은 한 호스트가 로더 스크립트 1종과 CPU 별 실행파일 3종을 함께 내보냈다는 사실에 근거한 것이며, 그 호스트를 누가 운영하는지는 확인할 수 없습니다.

어디서 본 것 같다면

추정 2016년부터 이어진 Mirai 봇넷 계열 및 그 파생과 진입 구조가 같습니다. 텔넷 기본 비밀번호로 들어간 뒤 웹 서버에서 작은 셸 스크립트 로더를 내려받고, CPU 종류별로 따로 만든 정적 링크 실행파일을 순서대로 시도하는 방식입니다. 어제 ATK-31C779 가 받아간 조합 — 2,107바이트 로더 하나 + ARM·MIPS·MIPSEL 정적 링크 ELF 세 개가 한 호스트에서 한 세션에 함께 내려온 것 — 이 이 구조와 맞고, 인용한 자격증명 15개가 전부 기본값·단순 조합이며 완결 세션 5건이 전부 텔넷·비밀번호 경로라는 점도 맞습니다. 미국 법무부 기소·유죄인정 기록이 남아 있고 여러 벤더의 공개 분석 보고서가 있는 사건입니다.

추정 Gafgyt(Bashlite/Lizkebab) 계열과도 맞물립니다. 텔넷·약한 비밀번호로 리눅스 장비에 들어간 뒤 셸 스크립트가 CPU 별 정적 링크 실행파일을 내려받아 실행시키는 구조입니다. 어제 관측된 세 규격이 서버용 x86 없이 장비 계열로만 구성된 점, 검체 크기가 48~59KB 로 작은 점이 이 구조와 맞습니다.

사실 두 사례가 딱 하나 짚어 주는 게 있습니다. 둘 다 소스가 공개된 계열이라, 서로 아무 관계 없는 운영자들이 각자 유포지를 세우고 같은 순서를 돌리는 것이 흔합니다. 어제 “이틀 전과 다른 이름 규칙을 쓰는 새 호스트”가 나온 것도 이 방향과 어긋나지 않습니다.

사실 다만 이 사례들이 어제의 개별 판단까지 확인해 주지는 않습니다. 두 호스트의 관계도, daredevil 이라는 이름이 어느 계열인지도 마찬가지입니다. 파일 이름은 이름일 뿐이며 계열 명칭이 아닙니다.

그래서 뭘 해야 하나

추정 어제 데이터가 가리키는 순서입니다.

  1. 기본 계정·초기 비밀번호를 바꿉니다. 로그인 시도 1,187회, 완결 세션 5건은 전부 로그인 성공입니다. 어제 실행된 명령 1,863개는 전부 로그인에 성공한 뒤에 실행된 것입니다. 주제 세션은 로그인 성공에서 실행파일 세 개 확보까지 약 5.1초가 걸렸고, 같은 일을 하루에 세 번 반복했습니다. 위 표의 조합을 쓰고 계시다면 그게 전부입니다.
  2. 장비가 밖에서 파일을 받아오지 못하게 막습니다. 어제 파일 다운로드 55회, 실행 권한 부여 212회, 다운로드 후 실행 50회입니다. 밖으로 나가는 연결이 막혀 있었다면 ATK-31C779 의 세 세션과 ATK-F2B80A 는 다운로드 단계에서 전부 끊깁니다. 로그인은 이미 뚫린 뒤이므로 여기가 실제 피해를 막는 마지막 지점이었습니다. 게다가 어제 내려온 세 실행파일은 정적 링크라 리눅스 종류·버전과 무관하게 돌아가고, 섹션 헤더가 없어 뜯어보기도 어렵습니다.
  3. 텔넷 같은 원격 접속을 끕니다. 어제 텔넷은 전체 세션의 18.2% 입니다. 8/22 의 33.9%에서 돌아왔습니다. 그런데 실제로 뚫려서 명령이 실행된 세션의 비중은 8/22 도 어제도 100%입니다. 트래픽 비중으로 방어 순서를 정하면 매일 틀립니다. 공유기·홈캠 설정에서 “원격 접속”, “Telnet”, “원격 관리”를 찾아 꺼 두시면 됩니다. 텔넷은 비밀번호가 그대로 흘러가고, 키 인증이라는 선택지 자체가 없습니다 — 끄는 것 말고 방법이 없습니다.
  4. 로그인 실패 횟수를 제한합니다. admin/admin 한 조합이 17곳에서 37회 두드려졌는데 아무것도 걸리지 않았습니다. 같은 출발지가 1분 안에 두 번, 그리고 열 시간 뒤에 세 번째로 들어와도 막히지 않았습니다. 동시에 세션 하나가 5초면 끝나므로, “오래 붙어 있는 연결”이나 “천천히 쌓이는 시도”를 기준으로 잡은 임계값에는 애초에 걸리지 않습니다. 차단 판단이 5초보다 느리면 그 차단은 사후 조치입니다.
  5. ~/.ssh/authorized_keys 파일이 바뀌면 알림을 받습니다. 어제 키 심기 의도 7회, 같은 해시 공개키를 남긴 출처 6곳입니다. ATK-ADE2BE 는 검체를 한 건도 저장하지 못한 세션인데도 키 심기 단계까지 분류됐습니다. 파일을 하나도 안 받은 세션에는 백신이 검사할 실행파일 자체가 없습니다. 키 파일을 직접 들여다보지 않으면 뚫렸다는 사실 자체를 모릅니다.
  6. 로그를 장비 밖에 저장합니다. 흔적 삭제가 7회 관측됐습니다(8/18 19 → 8/19 13 → 8/20 8 → 8/21 12 → 8/22 8 → 어제 7). 그리고 어제 이 글이 성립한 이유가 로그입니다. TTY 녹화 덕에 5초짜리 세션 안에서 명령 3개와 다운로드 4건이 어떻게 흘렀는지 되짚을 수 있었고(내용은 이 글에 포함하지 않습니다), 이레치 기록을 지우지 않았기에 “새 유포지가 이틀 전 호스트와 앞 세 마디가 같으면서 이름 규칙만 다르다”는 것과 “ATK-F2B80A 세션이 8/21 세션과 다섯 값이 같다”는 것을 알 수 있었습니다. 하루치만 보면 둘 다 ’처음 보는 것’으로 기록됩니다.
  7. 파일 이름·해시 목록만으로 만든 차단 규칙에는 유통기한이 있다고 전제하고 운영합니다. 어제가 그 증거입니다. 12개 목록에 걸린 것은 0개였습니다.

사실 “비밀번호 대신 키 인증을 쓰세요”는 어제 데이터로는 중간 정도의 권고입니다. 어제 로그인이 성공한 완결 세션은 전부 텔넷이고, 텔넷에는 키 인증이 없습니다. 그리고 1,187회 중 SSH 몫이 얼마인지 데이터가 나눠 주지 않아, “키 인증을 켰다면 어제 침투가 막혔다”고 말할 근거가 없습니다.

어제 하루 전체

세션 1,523건
고유 IP 222곳
로그인 시도 1,187회
실행된 명령 1,863개
SSH (2222) 1,246건
텔넷 (2223) 277건

출발지 한 곳당 평균 약 6.9세션, 약 5.3회 시도입니다.

사실 8/22 와 나란히 놓으면 세션은 3,553→1,523, 명령은 7,574→1,863, 로그인 시도는 3,324→1,187 로 전부 되돌아왔습니다. 텔넷도 1,203→277 로 약 4.3분의 1이 되어 8/19·8/20·8/21 의 299·297·281 과 같은 띠로 복귀했습니다. 줄어든 날에 실행파일이 돌아왔습니다. 트래픽 총량과 실제 피해는 같은 방향으로 움직이지 않습니다.

어제 관측된 유포지·C2(176[.]65[.]139[.]202, 185[.]93[.]89[.]72, 5[.]182[.]210[.]174)와 감시 목록의 31[.]77[.]227[.]121 은 C-TAS 로 신고했습니다. 어제 신고분의 핵심은 신규 호스트 176[.]65[.]139[.]202 와 그 호스트가 내보낸 검체 4종의 해시입니다. 전송 계층 성공만 확인되며, KISA 측 적재 여부는 별도 확인이 필요합니다.

60초로 보기

같은 관측분을 짧은 영상으로도 만들었습니다. 영상은 미리 적어둔 이름 열두 개가 하나도 걸리지 않았다는 쪽에 초점을 맞췄습니다.

우리가 모르는 것

이 블로그는 아는 것과 모르는 것을 나눠서 씁니다. 어제 관측분에서 확인할 수 없었던 것들입니다.

  • 176[.]65[.]139[.]202(어제)와 176[.]65[.]139[.]196(8/21)이 같은 운영자인지. 앞 세 마디가 같지만, 같은 주소 블록의 무관한 이웃일 수 있습니다. 인터넷 주소를 빌려주는 회사들은 나란히 붙은 주소를 서로 무관한 이용자들에게 배정합니다. 게다가 우리에겐 사업자 정보가 없어 두 주소가 같은 회사 안에 있는지조차 확인할 수 없습니다.
  • 8/21 호스트(.196)가 어제도 기록에 없는 이유. 이틀 연속 0건입니다. 사라진 것인지, 살아 있는데 우리 허니팟으로 요청이 오지 않은 것인지 구분할 수 없습니다. 8/22 에 남긴 같은 항목이 어제도 풀리지 않았습니다.
  • 감시 목록 12개가 나흘 연속 0건인 이유. 마찬가지로 유포지가 멈춘 것인지 우리 쪽으로 오지 않은 것인지 구분할 수 없습니다.
  • daredevil 이 무엇인지. 관측된 파일 이름일 뿐입니다. 악성코드 계열명이나 캠페인 이름으로 해석하지 않았고, 데이터가 그 근거를 주지 않습니다.
  • ATK-31C779 의 세 세션이 명령은 3개인데 다운로드가 4건인 이유. 명령 하나가 여러 파일을 받은 것인지 다른 이유인지, 명령 원문이 없어 말할 수 없습니다. 네 검체의 전달 출처가 이 별칭 한 곳뿐이고 각 관측이 3회라 세 세션과 딱 맞아떨어지지만, 데이터가 세션과 검체를 직접 이어 주는 항목은 없습니다 — 개수가 맞는다는 것에 근거한 추론입니다.
  • 왜 하루에 세 번, 그중 두 번은 1분 안에 반복됐는지. 앞 세션이 실패해서 다시 시도한 것인지 원래 그렇게 도는 것인지 구분할 근거가 없습니다. 세 번 다 로그인에 성공했고 다운로드 수도 같습니다.
  • ATK-F2B80A 의 의도가 왜 하나도 분류되지 않았는지. 명령 48개인데 의도 배열이 비어 있고 completeness 는 43 으로 어제 최고값입니다. 계산식이 데이터에 없어 설명할 수 없습니다. 8/18·8/21·8/22 에도 같은 항목이 남아 있습니다.
  • 1바이트 빈 파일이 11회 반복 저장된 이유. 다운로드 실패의 결과인지 의도된 동작인지 알 수 없습니다. 8/17·8/18·8/21·8/22 에도 같은 항목이 남아 있습니다.
  • ATK-ADE2BE 가 다운로드에 실패한 것인지, 받았는데 저장이 안 된 것인지. 의도에는 ‘파일 다운로드’·’다운로드 후 실행’이 있는데 다운로드 수는 0 입니다. 8/18 이래 여섯 번째입니다.
  • 어제 ATK-F2B80A 세션과 8/21 의 ATK-792ADF 세션이 같은 출발지인지. 다섯 값이 일치하지만 별칭은 소금을 섞어 만들므로 맞춰 볼 수 없습니다. 확인되는 것은 세션의 모양과 검체 해시가 같다는 것까지이며, 이는 같은 도구·같은 자동 실행 순서를 썼다는 뜻이지 같은 조직·같은 사람이라는 뜻이 아닙니다. 지속 시간이 약 23.7초에서 약 32.6초로 늘어난 이유도 알 수 없습니다.
  • 8/21 의 실행파일을 받아간 세션과 어제 주제 세션이 같은 곳인지. 둘 다 마스킹 표기가 94.154.x.x 입니다. 그러나 마스킹으로 남는 것은 앞 두 마디뿐이라 이 대역에만 주소가 65,536개 있고, 별칭은 날짜 간 비교가 불가능합니다. 같은 출발지라고 말할 수 없습니다.
  • hxxp://5[.]182[.]210[.]174/ok 가 하루에 두 종류를 내보낸 이유. 요청마다 새로 만들어지는 것인지 짧은 주기로 교체되는 것인지 알 수 없고, 내용을 담지 않으므로 무엇이 달라졌는지도 말할 수 없습니다. 8/18 이래 이 주소의 해시는 누적 7종입니다.
  • 같은 해시 공개키를 6곳이 남긴 이유. 같은 도구를 쓴 결과인지 키를 공유한 결과인지 알 수 없습니다. 별칭 때문에 날짜 간 출처 수를 합산하거나 같은 출발지로 추적할 수도 없습니다.
  • 9바이트 ASCII 텍스트 3종(4af5a5c9…·a9b1c85a…·1193dde1…)이 무엇인지. 내용이 기록에 없습니다. a9b1c85a·1193dde1 은 8/21 에도 한 별칭에서 짝으로 나왔지만 어제는 다른 별칭이고, 별칭은 날짜 간 대조가 불가능합니다.
  • 명령 총계 1,863개와 의도 분류 합계 1,312회의 차이 551 이 왜 생기는지. 한 명령이 여러 의도로 분류되는지, 분류되지 않는 명령이 있는지 설명이 없습니다. 정찰(시스템) 비중이 8/22 26.1%에서 어제 52.6%로 돌아온 것도 같은 원인일 수 있으나 확인할 수 없습니다.
  • 인용하지 않은 1,007개 조합의 시도 횟수. 인용한 15개의 시도 합계는 97회로 전체의 약 8.2%입니다. 1,007개는 ’조합 수’이지 ’시도 수’가 아니므로, 나머지 1,090회가 어떻게 분포하는지 계산할 수 없습니다.
  • 텔넷이 1,203건에서 277건으로 줄었는데 고유 출발지는 205곳에서 222곳으로 늘어난 이유. 8/22 의 급증이 무엇이었는지, 어제의 감소가 무엇 때문인지 설명이 없습니다.
  • 지문 목록이 상위 몇 개인지 전수인지. 클러스터 총계는 40인데 목록은 9개입니다. 따라서 “어제 검체를 전달한 클러스터가 없다”는 것은 그 9개 범위 안에서의 사실입니다.
  • 0425c279…(SSH-2.0-PuTTY_Release_0.70)의 누적 집계. 어제는 당일 2곳·누적 3곳인데, 8/21·8/22 기록은 당일 3곳 = 누적 3곳이었습니다. 누적 집계의 시작 시점과 갱신 방식이 명시돼 있지 않아 날짜 간 해석이 불가능합니다.
  • SSH-2.0-ZGrab ZGrab SSH Survey(지문 dd9bcf09…, 어제 IP 2곳·누적 42곳)의 성격. 공개된 인터넷 스캐너 도구의 이름이지만, 연구·측정 목적인지 공격 준비인지 이 데이터로는 구분할 수 없습니다.
  • Discord 웹훅 URL 1건. 어느 세션·어느 검체와 연결되는지 명시돼 있지 않아 어제 사실 관계에 넣지 않았습니다. 8/20·8/21·8/22 도 같은 이유로 제외했습니다. 웹훅의 토큰 문자열은 그 자체가 악용될 수 있는 값이라 본문에 옮기지 않습니다.
  • 집계 수치가 하루 전체를 덮는지. 주요 세션이 UTC 00:11~10:19 에 걸쳐 있고 생성 시각은 15:05Z 입니다. 관측 구간이 명시돼 있지 않습니다. 위에서 “약 73초에 한 번꼴”이라고 쓴 것도 하루 전체를 가정한 계산입니다.
  • tty_recordings_available(148)·samples_on_honeypot(52)과 집계 TTY 녹화(1,063건)·검체 13종의 관계. 설명이 없습니다.
  • 배경 취약점 통계가 하루 만에 늘어난 이유. 추적 CVE 가 4,556건에서 6,548건으로 1,992건 늘었고 CISA KEV 등재도 345→385, 랜섬웨어 연계도 95→98 로 늘었습니다. 수집 범위가 바뀐 것인지 실제 증가인지 설명이 없습니다. 이건 KISA 보안공지 기반 배경 통계이며 어제 관측과 직접 연결되지 않습니다 — 어제 관측된 침투 경로는 전부 자격증명이었습니다.
  • C-TAS 신고의 적재·활용 여부. 전송 계층 성공만 확인됐습니다.
  • 의도 목록이 실행 순서를 뜻하는지. 명시돼 있지 않아, 이 글은 의도 배열의 순서를 단계 진행 순서로 읽지 않았습니다.

그리고 애초에 확인할 수단이 없는 것들입니다. 이건 모르는 것과 다릅니다 — 추정하지 않는 쪽이 정답입니다.

  • ASN·ISP — GeoIP·ASN 데이터베이스를 갖고 있지 않습니다. 추정하지 않습니다. 새 유포지 176[.]65[.]139[.]202 와 8/21 의 176[.]65[.]139[.]196 이 같은 사업자·같은 네트워크에 있는지도 말할 수 없습니다.
  • 지리 위치 — 동일합니다. IP 지리정보는 애초에 귀속 근거가 되지도 않습니다. 어제 세 번 들어온 출발지가 어디인지 말할 수 없고, 특정 국가·기업·개인을 공격자로 지목하지 않습니다.
  • VPN·Tor·클라우드 여부 — 판별 수단이 없습니다. 같은 출발지가 하루에 세 번 들어온 것이 고정 회선인지 임시로 빌린 것인지 구분할 수 없습니다.
  • VirusTotal 탐지 결과 — 미연동입니다. 어제 저장된 검체 13종, 특히 ELF 3종이 어떤 계열로 탐지되는지 이 데이터로는 말할 수 없습니다. 검체 분류는 MalwareBazaar 태그를 씁니다.
  • User-Agent — SSH·텔넷에는 User-Agent 자체가 존재하지 않습니다. 유포지로 나간 요청이 어떤 도구였는지도 이 소스로는 알 수 없습니다. HTTP 공격은 별도 소스입니다.
  • CVE 연결 — SSH·텔넷 공격은 취약점을 참조하지 않는 경우가 대부분이고, 어제 관측분도 전부 비밀번호를 노린 것이었습니다.

이름표 이야기로 시작했습니다.

어제 알아낸 것은 딱 그 정도입니다. 이름표는 이틀 만에 갈렸습니다. 우리가 손으로 압축을 풀어가며 적어 둔 열두 개는 하나도 걸리지 않았습니다. 학번 앞자리가 같다는 건 알았지만, 같은 반이라고 같은 사람은 아닙니다.

남은 건 순서였습니다. 텔넷으로 들어와서, 메모지 한 장을 받고, CPU 종류별로 실행파일 세 개를 챙겨서, 5초 만에 나갑니다. 그걸 하루에 세 번 했습니다. 이름은 바꿀 수 있는데 순서는 바꾸기 어렵습니다 — 바꾸면 안 돌아가니까요.

그리고 그 세 개는 전부 PC 용이 아니라 장비용이었습니다. 지금 이 글을 보고 계신 화면 뒤에서 인터넷을 물려 주고 있는 공유기, 거실 구석의 홈캠, 책상 밑의 NAS. 어제 5초 동안 세 번 챙겨간 것이 그 기계들에서 도는 물건입니다.


이 글은 2026-08-23 허니팟 관측분을 바탕으로 작성됐습니다. 출발지 IP 는 브리프의 마스킹 형태 그대로 표기했고, 유포 주소는 접속되지 않도록 변형(defang)했습니다. 인용한 자격증명은 서로 다른 IP 3곳 이상에서 관측된 15개 조합만 포함했으며, 그 미만에서만 관측된 1,007개 조합은 개수만 밝히고 값은 싣지 않았습니다.