SecurityHeroblog

노트인 줄 알았는데 화이트보드였다 — 50이 35로 줄던 날

9월 5일, 우리 서버에 들어온 파일 6개 중 5개는 이미 20일째 적혀 있던 이름이었습니다. 그런데 기록을 맞춰 보다가 우리 쪽 숫자가 틀린 것을 찾았습니다. '지금까지 50곳'이라고 적어 둔 칸이 어제는 35곳이었고, 그건 공격이 줄어서가 아니었습니다.

학교 복도에 화이트보드가 하나 걸려 있다고 해 봅시다. 거기에 책을 아직 반납하지 않은 사람 이름이 적혀 있어요.

지난주에 세어 보니 50명이었습니다. 이번 주에 다시 세어 보니 35명입니다.

반납을 한 걸까요?

그럴 수도 있습니다. 그런데 다른 답도 있어요. 화이트보드는 칸이 정해져 있습니다. 새 이름을 적으려면 맨 위 이름을 지워야 합니다. 노트였다면 이름이 계속 쌓였겠지만, 화이트보드는 오래된 이름을 밖으로 밀어냅니다. 그러면 숫자는 사람이 줄어서가 아니라 판이 밀려서 줄어듭니다.

어제 우리가 겪은 일이 정확히 이겁니다. 다만 우리는 반납 명단이 아니라 침입 기록을 세고 있었고, 그 판을 노트라고 믿고 스무 날 동안 글을 써 왔습니다.


먼저, 어제 들어온 것들

사실 어제 우리 서버(허니팟, 일부러 열어 두고 누가 뭘 하는지 지켜보는 미끼 서버입니다)에 내려온 파일은 6종이었습니다. 그중 5종은 우리가 예전 기록에 이미 적어 둔 파일이었어요. 해시(파일 내용을 짧은 값 하나로 요약한 값. 내용이 한 글자만 달라도 값이 통째로 바뀝니다)까지 똑같았습니다.

사실 그중 하나는 306바이트짜리 셸 스크립트입니다. 306바이트면 문자 메시지 두 줄 정도 되는 크기예요. 이 파일은 8월 17일에 처음 찍힌 뒤 어제로 20일째 같은 해시입니다. 같은 주소 hxxp://185[.]93[.]89[.]72/wget에서 옵니다. 20일 동안 한 비트도 바뀌지 않았습니다.

추정 공격하는 쪽이 아무것도 고치지 않았다는 뜻입니다. 고칠 이유가 없었다는 쪽이 더 정확할 거예요. 이 파일이 20일 내내 통했다는 말이니까요.

사실 어제 로그인에 성공해 명령을 남긴 세션은 5건이었습니다. 그중 3건은 서로 다른 출발지인데 명령 개수 31개, 의도 3종, 완결성 점수 16까지 똑같았습니다. 걸린 시간도 67.657초 · 68.155초 · 67.820초로 1초 안쪽 차이였어요. 이 세 세션이 받아 간 파일도 위의 306바이트 스크립트 한 개였습니다.

사실 나머지 한 건(ATK-CA5936)은 SSH로 들어와 3.738초 머물고 나갔습니다. 명령은 딱 1개인데 의도는 5종, 파일은 2개를 받아 갔어요. 이 형태는 8/19 · 8/24 · 8/25 · 8/28 · 8/30 · 9/01 · 9/03 기록과 별칭 · 지문 · 소요시간 · 명령 수까지 같습니다. 어제가 여덟 번째입니다.

새 파일 하나 — 그런데 그것도 새것이 아니었다

사실 어제 유일하게 처음 보는 해시는 dde20835… 하나였습니다. 1,608바이트짜리 bash 스크립트예요. 문자 메시지로 치면 열 줄쯤 되는 분량입니다.

사실 이 파일은 hxxp://5[.]182[.]210[.]174/ok에서 왔습니다. 그런데 이 주소에서 나온 파일은 8/17 이후 매번 정확히 1,608바이트였고, 매번 해시는 달랐습니다. 8/25 글에서 10종으로 세었고 8/29 글에 2종이 더 있으니, 어제 것까지 최소 12종입니다.

추정 크기는 그대로인데 내용만 조금씩 달라진다는 뜻으로 읽힙니다. 해시로 막는 방식은 이 주소 앞에서는 하루도 못 갑니다. 열두 번 적어 놨는데 열세 번째가 또 나오는 셈이니까요.

사실 다만 왜 그런지는 모릅니다. 요청할 때마다 새로 만들어지는 것인지, 짧은 주기로 갈아 끼우는 것인지 구분할 수 없어요. 파일 내용을 우리가 갖고 있지 않아서 무엇이 달라졌는지도 말할 수 없습니다. 8/22 · 8/23 · 8/25 · 8/27 · 8/29에도 같은 항목을 미해결로 남겼고, 어제도 그대로입니다.


그러다 우리 명단이 이상했다

여기부터가 어제의 진짜 주제입니다.

사실 우리 서버는 접속해 온 프로그램마다 지문을 하나씩 남깁니다. 상대 프로그램이 “나는 이런 방식으로 대화한다”고 먼저 알려주는 값들을 한 덩어리로 요약한 값이에요. 그 지문 옆에는 ips_all_time이라는 칸이 있습니다. 이름 그대로 읽으면 **“지금까지 이 지문을 달고 온 출발지 수”**입니다.

사실 우리는 이 칸을 스무 날 동안 ’누적’으로 읽고 글에 옮겨 적었습니다. 그런데 어제 옛 글과 맞춰 보니 세 개가 과거보다 작아져 있었습니다.

지문 (배너) 지난 기록 어제 방향
dd9bcf09… (SSH-2.0-ZGrab) 8/21 34 → 8/22 38 → 8/23 42 → 8/31 50곳 35곳 ↓
f555226d… (SSH-2.0-libssh_0.9.6) 8/19 145 → 8/22 182 → 8/24 216 → 8/29 289곳 271곳 ↓
16443846… (SSH-2.0-Go) 8/19 24 → 8/24 28 → 8/30 27 → 9/04 19곳 20곳 ↓(8/30 대비)
지문 묶음 총수 8/24 41 → 8/29 45개 37개 ↓

사실 누적은 줄어들 수 없습니다. 어제까지 50곳이 다녀갔는데 오늘 35곳이 되려면, 다녀간 일 자체가 취소돼야 하니까요.

추정 그러니까 저 칸은 노트가 아니라 화이트보드였을 가능성이 높습니다. 전체를 쌓는 게 아니라 최근 얼마 동안만 세는 칸이라는 뜻이에요. 오래된 이름은 판 밖으로 밀려납니다.

사실 다만 확정할 수 없습니다. 며칠치를 세는 건지, 언제부터 세기 시작한 건지가 데이터 어디에도 적혀 있지 않습니다. 그래서 우리는 이 값을 앞으로 ’지금까지의 총계’로 쓰지 않고 **‘최근 관측 폭’**으로만 쓰겠습니다. 그렇게 읽어 온 지난 글의 문장들은 과대·과소 어느 쪽으로도 틀렸을 수 있습니다.

그런데 한 줄만 반대로 갔다

사실 같은 표에서 acaa53e0…(SSH-2.0-OpenSSH_7.4) 한 줄만 계속 올라갔습니다. 8/25 139곳 → 8/31 589곳 → 어제 1,042곳입니다.

추정 판이 밀리는 칸인데도 올라갔다면, 밀려나간 것보다 새로 들어온 것이 더 많았다는 뜻입니다. 이쪽 증가는 진짜로 읽어도 됩니다. 반대로 줄어든 세 줄은 “공격이 줄었다”의 근거로 쓰면 안 됩니다.

사실 그리고 이 1위 지문에는 delivered_samples(파일을 놓고 갔는가) 표시가 false입니다. 어제 지문 11종 중 이 표시가 켜진 것은 16443846…(SSH-2.0-Go) 하나뿐이었어요. 문을 가장 많이 두드린 도구와 실제로 물건을 놓고 간 도구가 다릅니다.

사실 여기서 한 번 멈추겠습니다. 이 값은 프로그램 빌드의 지문이지 사람의 지문이 아닙니다. 같은 배포판이 기본으로 넣어주는 OpenSSH를 쓰는 사람들은 서로 아무 관계가 없어도 같은 값을 갖습니다. 그래서 “같은 도구”까지만 쓰고 “같은 조직”이라고는 쓰지 않습니다. 게다가 배너 문자열은 상대가 스스로 보내는 값이라 얼마든지 꾸며 낼 수 있고, 우리에게 그걸 검증할 방법이 없습니다.


어제 하루 전체

시간 순서로 늘어놓으면 이렇게 됩니다. ’하루 집계 · 아카이브 대조’라고 적힌 줄을 눈여겨보세요 — 어제 하루만 봐서는 안 보이고, 지난 글과 붙여 놓아야 보이는 것들입니다.

  1. 사실 ATK-DF93D5(171.249.x.x, 텔넷) 로그인 성공. 67.657초 동안 명령 31개, 다운로드 1건. intents 3종 — 파일 다운로드 · 실행 권한 부여 · 다운로드 후 실행. completeness 16, TTY 녹화됨(내용 미포함). 텔넷이라 지문·클라이언트 칸은 빈 문자열이다
  2. 사실 ATK-A2FEFA(122.8.x.x, 텔넷) 로그인 성공. 60.894초, 명령 17개. intents 5종 — 정찰(시스템) · 파일 다운로드 · 실행 권한 부여 · 다운로드 후 실행 · 지속성(SSH 키 심기). 다만 download_count 는 0 이고, 이 별칭은 389바이트 공개키 a8460f44… 의 delivered_by 8곳 목록에 없다. completeness 17
  3. 사실 ATK-C7E851(111.246.x.x, 텔넷) 로그인 성공. 68.155초, 명령 31개, 다운로드 1건, intents 3종, completeness 16 — 00:26 의 ATK-DF93D5 와 명령 개수·의도 조합·완결성이 동일하다
  4. 사실 ATK-CA5936(130.12.x.x, SSH) 로그인 성공. 3.738초 · 명령 1개인데 intents 5종 · 다운로드 2건(399바이트 OpenSSH 개인키 43728fbf… 와 54바이트 ASCII 00b6f15c…). 지문 16443846…4397 / SSH-2.0-Go. completeness 19 로 어제 1위. 아카이브 8/19·8/24·8/25·8/28·8/30·9/01·9/03 과 별칭·지문·소요시간·명령 수·의도 수·다운로드 구성이 모두 같다 — 어제가 여덟 번째 기록이다
  5. 사실 ATK-6757C8(171.249.x.x, 텔넷) 로그인 성공. 67.820초, 명령 31개, 다운로드 1건, intents 3종, completeness 16 — 어제 세 번째로 같은 형태다. 이 별칭과 00:26 의 ATK-DF93D5 는 마스킹된 앞 두 옥텟이 171.249 로 같은데 별칭이 서로 다르다
  6. 사실 명령 31개 형태의 세 세션(ATK-DF93D5 · ATK-C7E851 · ATK-6757C8)이 모두 306바이트 셸 스크립트 a6296a79… 의 delivered_by 8곳 목록에 들어 있다. 즉 세 세션이 받아간 파일은 같은 한 개다
  7. 사실 어제 downloads 6종 중 5종이 과거 기록에 있는 해시다 — a6296a79…(306바이트, 8/17 이후 20일째 동일 해시·동일 URL), 4af5a5c9…(9바이트, 8/18·8/19), a8460f44…(389바이트 공개키, 8/16 이후), 43728fbf…(399바이트 개인키, 8/19 이후), 00b6f15c…(54바이트 ASCII, 8/19 이후). 새 해시는 dde20835…(1,608바이트 bash) 하나뿐이다
  8. 사실 그 새 해시 dde20835… 는 hxxp://5[.]182[.]210[.]174/ok 에서 왔고 크기가 정확히 1,608바이트다. 8/25 글이 이 URL 의 해시를 10종으로 집계했고 8/29 글에 2종(801cba39… · 0c058175…)이 더 있다 — 어제 것을 더하면 최소 12종이며, 크기는 8/17 첫 관측 이후 매번 1,608바이트로 동일하다
  9. 사실 client_fingerprints 의 ips_all_time 이 과거 기록보다 낮아진 클러스터가 3개다. dd9bcf09…(SSH-2.0-ZGrab) 8/21 34 → 8/22 38 → 8/23 42 → 8/31 50 → 어제 35. f555226d…(SSH-2.0-libssh_0.9.6) 8/19 145 → 8/22 182 → 8/24 216 → 8/29 289 → 어제 271. 16443846…(SSH-2.0-Go) 8/19 24 → 8/24 28 → 8/30 27 → 9/04 19 → 어제 20. clusters_total 도 8/24 41 → 8/29 45 → 어제 37 이다. 반면 acaa53e0…(SSH-2.0-OpenSSH_7.4)는 8/25 139 → 8/31 589 → 어제 1,042 로 계속 늘었다
  10. 사실 명령 1,715개 중 의도로 분류된 것은 1,028개(59.9%). 그중 정찰 — 시스템 770회가 74.9%로 압도적이고, 실행 권한 부여 184회는 파일 다운로드 28회의 6.6배다. 파일 다운로드 28회와 다운로드 후 실행 28회는 정확히 같다. 지속성 — SSH 키 심기 10회, 흔적 삭제 8회
  11. 사실 세션 35,373건, 고유 출발지 327곳. VNC(5900) 33,975건이 전체의 96.05%인데 만든 곳은 100곳뿐이다 — 한 곳당 평균 339.75회. 반대로 RDP(3389)는 접촉 918건인데 출발지가 118곳으로 어제 서비스 중 가장 많고, 한 곳당 7.78회다
  12. 사실 top_sources 상위 6곳이 각각 4,941~5,199 이벤트, 합계 30,390 으로 센서 02 전체 세션의 85.9%다. 목록 12곳 전체는 31,837건(90.0%)
  13. 사실 service_breakdown 5종의 세션 합은 35,262 로, 전체 세션 35,373 과 정확히 111 차이다. 이 111 은 adb_sessions 값과 같다 — ADB 접촉은 총계에는 들어갔는데 서비스 목록에는 없다
  14. 사실 SMB 방언 제안 180건은 NT LM 0.12 · LANMAN1.0 · LM1.2X002 · LANMAN · PC NETWORK PROGRAM 1.0 · Windows for Workgroups 3.1 · LANMAN2.1 · Samba 여덟 어휘뿐이고 SMB2 계열 제안은 0건이다(9/04 에는 SMB 2.??? 가 2건 있었다). VNC 는 버전이 기록된 33,806건 중 33,285건(98.46%)이 003.003 이다. RDP 쿠키 768건 중 공개 스캐너 이름을 그대로 담은 것은 nmap 3회 · zgrab 2회

여기서 눈에 걸리는 건 세 번째 아카이브 대조 줄입니다. 나머지 줄이 전부 “어제도 똑같았다”인데, 그 줄만 “어제 우리가 틀렸다”거든요.

숫자로 옮기면 이렇습니다.

항목 어제 (센서 01) 견줄 것
세션 1,700건 —
고유 출발지 439곳 한 곳당 세션 3.9건
로그인 시도 1,304회 한 곳당 평균 2.97회
명령 1,715개 의도가 붙은 건 1,028개(59.9%)
포트 2222 (SSH) 1,334세션 전체의 78.6%
포트 2223 (텔넷) 364세션 그런데 성공 세션 5건 중 4건이 이쪽
TTY 녹화 913건 —

추정 크기를 감으로 재 보면 이렇습니다. 로그인 시도 1,304회는 하루로 나눠 1분에 한 번꼴입니다. 누가 하루 종일 문고리를 돌려 본 셈이에요. 명령 1,715개도 1분에 한두 개꼴입니다. 급하지도, 쉬지도 않는 속도입니다.

사실 어제 서버 안에서 벌어진 일의 분포는 이렇습니다.

의도 횟수 비중
정찰 — 시스템 770회 분류된 것의 74.9%
실행 권한 부여 184회 다운로드 28회의 6.6배
다운로드 후 실행 28회 —
파일 다운로드 28회 위와 정확히 같다
지속성 — SSH 키 심기 10회 —
흔적 삭제 8회 —

사실 ‘파일 다운로드’ 28회와 ‘다운로드 후 실행’ 28회가 정확히 같습니다. 내려받은 것은 예외 없이 실행 단계로 갔다는 뜻입니다.

’실행 권한 부여’는 파일에 “이건 실행해도 되는 파일이야”라는 표시를 붙이는 동작입니다. 리눅스에서는 이 표시가 없으면 프로그램이어도 실행되지 않거든요.

문 앞에 놓인 것

방어에 쓰실 수 있게 값을 그대로 옮깁니다. 값을 클릭하면 복사됩니다. 주소는 접속되지 않도록 변형(defang)해 두었으니 그대로 두고 쓰세요. 그리고 ‘20일째’·’12종’이라고 적힌 두 줄을 견줘 보세요 — 하나는 한 번 적으면 20일 가는 값이고, 하나는 적자마자 낡는 값입니다.

sha256
a6296a79f44e21b76604d2d2bbf795d2cf380f70e39d45fbf166707ff3b4a6a4306바이트 POSIX 셸 스크립트 · 센서 01 · 별칭 8곳에서 8회 · 8/17 첫 관측 이후 20일째 같은 해시
url
hxxp://185[.]93[.]89[.]72/wget위 306바이트 스크립트의 유포지. 20일 동안 파일이 한 비트도 바뀌지 않았다
sha256
dde20835fbf7c5187387e760504358634cb8c7f2abd0b06f69b11e9fdfb0ca371,608바이트 Bourne-Again 셸 스크립트 · 별칭 1곳(ATK-99DE57)에서 1회 · 어제 유일하게 아카이브에 없던 새 해시
url
hxxp://5[.]182[.]210[.]174/ok위 파일의 유포지. 8/25 집계 10종 + 8/29 기록 2종 + 어제 1종 = 최소 12종의 서로 다른 해시가 매번 정확히 1,608바이트로 나왔다
sha256
a8460f446be540410004b1a8db4083773fa46f7fe76fa84219c93daa1669f8f2389바이트 OpenSSH RSA 공개키 · 서로 다른 별칭 8곳에서 8회 · 8/16 이후 반복 기록 · 유포지 미기록
sha256
43728fbfb98bb39ff61a2db0fc2905bd6937997062b05b9ab8b186fdee18c09a399바이트 OpenSSH 개인키 · 별칭 1곳(ATK-CA5936)에서 1회 · 8/19·8/24·8/25·8/28·8/30·9/01·9/03 과 동일 해시로 어제가 여덟 번째 · 유포지 미기록
sha256
00b6f15c2274420217ed3098a9f5f00545bf1793d7a324fd18a7809cbbf5b12b54바이트 ASCII 텍스트 · 위 개인키와 같은 별칭·같은 세션 시각대 · 8/19 이후 반복 · 내용이 기록에 없어 무엇인지 판단하지 않는다
sha256
4af5a5c98ad132095c6fbe7b02c242153a190a01cc321e50a916a0ca46fbaa629바이트 ASCII 텍스트 · 별칭 1곳(ATK-BECAD3)에서 8회 · 8/18·8/19 기록과 같은 해시 · 유포지 미기록
sha256
71ecfb7bbc015b2b192c05f726468b6f08fcc804c093c718b950e688cc414af5231,196바이트 · 센서 02 · 별칭 1곳(ATK-624002)에서 1회 · 저상호작용 센서라 어떤 명령으로 들어왔는지에 해당하는 기록이 없다
url
hxxp://31[.]77[.]227[.]121/bins/UPX 압축을 풀어야만 드러난 유포 URL 계열 12건. 겉면만 봐서는 주소가 하나도 보이지 않는다

사실 크기 감을 붙여 두겠습니다. 389바이트 공개키는 문자 메시지 두세 줄, 54바이트는 짧은 한 문장, 9바이트는 영어 아홉 글자입니다. 센서 02의 231,196바이트는 위 306바이트 스크립트 750개분이에요.

사실 그리고 어제 센서 01이 저장한 6종에 ELF 실행 바이너리는 0건이었습니다. 셸 스크립트 2종 · ASCII 텍스트 2종 · 공개키 · 개인키뿐이고, 파일 분류 항목에 ’실행 파일’이 없습니다.

사실 389바이트짜리는 SSH 공개키입니다. 쉽게 말하면 비밀번호 없이 들어올 수 있는 여벌 열쇠예요. 서버의 authorized_keys(허용된 열쇠 목록)라는 파일에 이 값을 한 줄 적어 넣으면, 그 열쇠를 가진 쪽은 이후 비밀번호를 묻지 않아도 들어옵니다. 어제 이 파일은 서로 다른 별칭 8곳에서 왔습니다.

사실 반대로 399바이트짜리는 개인키입니다. 그런데 이게 공격자가 심어 두고 간 것인지, 서버에 있던 것을 가져가려 한 것인지 데이터가 구분해 주지 않습니다. 8/19에 남긴 미해결 항목이 여덟 번째 관측인 어제도 그대로입니다.

어떤 비밀번호로 들어오려 했나

사실 어제 시도된 아이디·비밀번호 조합은 약 955종이었습니다. 그중 여기 싣는 건 20종뿐입니다. 나머지 935종은 개수만 셉니다. 전체의 97.9%예요.

이유는 하나입니다. 서로 다른 IP 3곳 미만에서만 보인 조합은 실제로 어딘가에서 유출된 진짜 계정일 수 있습니다. 그런 값은 우리 글에 옮기지 않습니다.

아래 20종은 반대쪽입니다. 여러 곳에서 반복돼서 ’누구의 것도 아닌 출고 기본값’이라고 볼 수 있는 것들이에요.

아이디 비밀번호 서로 다른 출발지
admin admin 21곳
root root 9곳
support support 7곳
root admin 7곳
root 123456 7곳
345gs5662d34 345gs5662d34 7곳
root xmhdipc 5곳
root password 4곳
root (빈 비밀번호) 4곳
admin test 4곳
root 12345 4곳
user user 4곳
guest guest 4곳
root 111111 4곳
root 123123 4곳
enable\x00 linuxshell\x00 3곳
root pass 3곳
root xc3511 3곳
admin (빈 비밀번호) 3곳
root vizxv 3곳

사실 admin/admin 하나만 서로 다른 21곳에서 왔습니다. root 계정에 비밀번호를 아예 비워서 시도한 곳도 4곳 있었습니다.

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

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

  • T1110.001Brute Force: Password Guessing — 로그인 시도 1,304회, 서로 다른 조합 약 955종(인용 20 + 단일출처 935)추정
  • T1078.001Valid Accounts: Default Accounts — admin/admin 21곳, root/root 9곳 등 기본값 사전으로 5세션 로그인 성공추정
  • T1082System Information Discovery — 정찰 — 시스템 770회추정
  • T1105Ingress Tool Transfer — 파일 다운로드 28회, 외부 URL 이 기록된 유포지 2곳추정
  • T1222.002File and Directory Permissions Modification: Linux — 실행 권한 부여 184회추정
  • T1098.004Account Manipulation: SSH Authorized Keys — 지속성 — SSH 키 심기 10회, 389바이트 공개키가 서로 다른 8곳에서 반입추정
  • T1070Indicator Removal — 흔적 삭제 8회추정
  • T1046Network Service Discovery — 센서 02 에서 VNC·RDP·LDAP·SMB·MSSQL 5종 서비스에 접촉, RDP 쿠키에 nmap 3회추정
  • T1595Active Scanning — RDP 쿠키 zgrab 2회, 센서 01 의 SSH-2.0-ZGrab 지문 2곳·SSH-2.0-Fingerprintx-SSH2 지문 3곳. 상대가 스스로 도구 이름을 밝힌 접촉이며 연구·측정 목적인지 공격 준비인지는 확인 불가추정

아홉 줄 전부 [추정] 배지가 붙은 것을 봐 주세요. 우리 손에 있는 건 명령의 ’의도 분류 결과’와 ’몇 번이었나’까지입니다. 명령 원문은 없습니다. 분류표에 맞추는 일은 언제나 해석이고, 해석에는 해석이라고 적습니다.


옆 건물 — 센서 02

사실 같은 날, 저상호작용 센서 02에는 세션 35,373건이 들어왔습니다. 센서 01의 1,700건과 견주면 21배예요. 출발지는 327곳이었습니다.

서비스 포트 접촉 출발지 한 곳당
VNC 5900 33,975건 (96.05%) 100곳 339.75회
RDP 3389 918건 118곳 7.78회
LDAP 389 155건 15곳 10.3회
SMB 445 145건 57곳 2.5회
MSSQL 1433 69건 10곳 6.9회
ADB (미기록) 111건 (미기록) —

사실 접촉이 가장 많은 문과 출발지가 가장 넓은 문이 서로 다릅니다. VNC는 100곳이 3만 4천 번을 만들었고, RDP는 118곳이 918번을 만들었어요.

추정 VNC 쪽 339.75회는 하루로 나누면 한 곳이 4분에 한 번씩, 하루 종일 문고리를 돌린 속도입니다. RDP 쪽 7.78회는 하루에 여덟 번이고요. 같은 날 같은 서버에서 성격이 완전히 다른 두 가지가 동시에 일어난 셈입니다.

사실 상위 6곳이 각각 4,941~5,199건씩, 합쳐서 30,390건을 만들었습니다. 센서 02 전체의 **85.9%**입니다. 목록에 오른 12곳까지 합치면 90.0%예요.

사실 협상 단계에서 상대가 제안한 VNC 버전은 기록된 33,806건 중 33,285건(98.46%)이 003.003이었습니다. SMB 쪽은 방언 제안 180건이 전부 옛 어휘였고, 최신 계열인 SMB2 제안은 0건이었습니다. 9/04에는 2건 있었는데 어제는 없었어요. RDP 쿠키 768건 중 스캐너 이름을 그대로 적어 보낸 것은 nmap 3회, zgrab 2회입니다.

사실 센서 02는 저상호작용이라 로그인 성공·명령·자격증명이라는 개념 자체가 없습니다. 여기 숫자는 “어느 문을 몇 번 두드렸나”까지이고, “들어와서 무엇을 했다”는 문장은 만들 수 없습니다.


전에 이런 일이 있었다

추정 Mirai 봇넷(2016). 텔넷 기본 계정 사전으로 IoT 장비에 들어가던 방식입니다. 어제 인용 기준을 넘긴 자격증명 20종에 root/xc3511(3곳) · root/vizxv(3곳) · root/xmhdipc(5곳)가 들어 있는데, 이 조합들은 Mirai 소스가 공개될 때 알려져 널리 문서화된 값입니다. 어제 로그인에 성공한 5건 중 4건이 텔넷이라는 점도 겹칩니다. 다만 어제 시도가 Mirai 계열이라는 뜻은 아닙니다. 같은 사전이 이후 여러 파생 도구에 그대로 복사돼 쓰였기 때문에, 말할 수 있는 건 ’사전이 겹친다’까지입니다. 감염 대수나 피해 금액 같은 수치는 옮기지 않습니다. (출처 유형: 미국 US-CERT 경보 TA16-288A 및 공개된 소스코드 분석 보고서)

추정 RealVNC 4.1.1 인증 우회, CVE-2006-2369(2006). 어제 VNC 협상에서 상대가 제안한 버전은 98.46%가 003.003이었습니다. RFB 3.3은 인증 방식 선택권이 서버 쪽에 있는 옛 버전이고, 위 CVE는 그 구조에서 클라이언트가 ’인증 없음’을 관철할 수 있었던 결함입니다. 인증이 약한 화면공유 서버를 넓게 찾는 도구가 낮은 버전을 먼저 제안할 이유는 있어요. 다만 이건 프로토콜 정의와 공개 CVE에 기댄 배경 설명입니다. 어제 접촉이 이 취약점을 실제로 공격했다는 근거는 우리에게 없습니다. 우리가 가진 건 협상 단계에서 제시된 버전 숫자뿐입니다. (출처 유형: CVE 및 벤더 어드바이저리)


그래서 뭘 해야 하나

화이트보드 이야기로 돌아가겠습니다. 어제 우리가 배운 건 두 가지예요. 숫자는 어떤 판에 적혔는지에 따라 뜻이 달라진다는 것, 그리고 판이 남의 손에 있으면 지워질 수 있다는 것입니다. 아래 항목들도 결국 그 얘기입니다.

1. 기본 계정·취약 비밀번호를 그대로 쓰고 있다 · 가능성 높음 위 표 20줄은 전부 장비나 배포판이 출고할 때 넣어 두는 값입니다. admin/admin을 21곳이 44회, root/root를 9곳이 12회 시도했습니다. 빈 비밀번호 조합도 있었어요. 그리고 어제 완결성 상위 세션 다섯은 예외 없이 이 사전으로 문이 열린 뒤 시작됩니다. 열린 다음에 이어진 건 정찰 770회 · 실행 권한 부여 184회 · 다운로드 28회입니다.

2. 비밀번호 로그인을 허용하고 열쇠 방식을 안 쓰고 있다 · 가능성 높음 하루 1,304회의 로그인 시도가 들어왔고, SSH와 텔넷 모두 비밀번호를 받는 경로입니다. 문제는 그 다음이에요. ’키 심기’가 10회 분류됐고, 389바이트 공개키가 서로 다른 8곳에서 들어왔습니다. authorized_keys에 남의 열쇠가 한 줄 들어가면 비밀번호를 바꿔도 그 열쇠로 계속 들어옵니다. 인증 수단이 하나 더 생기는 것이라, 비밀번호 변경도 계정 잠금도 소용이 없습니다.

3. 관리 포트를 인터넷에 그대로 열어 두고 있다 · 가능성 높음 홍보한 적 없는 서버에 하루 439곳이 접촉했습니다. 옆 센서에는 RDP 118곳 · VNC 100곳 · SMB 57곳 · LDAP 15곳 · MSSQL 10곳이 붙었고요. 두 센서를 합치면 최대 766곳입니다(겹치는 곳을 알 수 없어 상한입니다). 스스로 스캐너라고 이름을 밝힌 접촉도 있었어요. 우리를 골라서 온 게 아니라 주소를 훑다가 걸린 겁니다. VPN이나 점프호스트 뒤로 옮기면 이 접촉 대부분이 인증 단계 앞에서 끊깁니다.

4. 밖으로 나가는 연결을 막지 않고 있다 · 가능성 높음 ‘파일 다운로드’ 28회와 ‘다운로드 후 실행’ 28회가 정확히 같았습니다. 어제 외부 주소가 기록된 유포지는 hxxp://185[.]93[.]89[.]72/wget과 hxxp://5[.]182[.]210[.]174/ok 두 곳입니다. 로그인은 이미 뚫린 다음이라, 서버가 밖으로 나가는 연결을 끊는 것이 실제 피해를 막는 마지막 지점이에요. 이게 막혀 있었다면 어제 네 세션은 다운로드 단계에서 전부 끊깁니다.

5. 로그를 서버 안에만 두고 있다 · 가능성 중간 ‘흔적 삭제’ 의도가 8회 분류됐습니다. 우리가 그걸 볼 수 있었던 건 세션 913건이 서버 밖에서 따로 녹화됐기 때문입니다. 명단을 남의 교실 화이트보드에만 적어 두면 지워집니다. 로그를 서버 밖으로 즉시 내보내는 구성 하나가 이 8회를 무력화합니다.

6. 횟수 기반 차단(fail2ban 등)만 믿고 있다 · 가능성 중간 여기가 재미있는 지점입니다. 센서 02의 VNC는 한 곳당 339.75회라 어떤 규칙에도 확실히 걸립니다. 상위 6곳이 전체의 85.9%를 만들었으니 접속 빈도 제한 하나로 잘려 나가요. 그런데 센서 01은 한 곳당 평균 2.97회입니다. ‘5회 틀리면 잠금’ 같은 임계값은 발동조차 하지 않습니다. 같은 방어가 한쪽에는 통하고 한쪽에는 안 통합니다. 그리고 어제 실제로 문이 열린 쪽은 임계값이 안 통하는 쪽이었습니다.


우리가 모르는 것

이 블로그가 다른 곳과 다른 점은 여기입니다. 모르는 것을 모른다고 적습니다. 어제는 그 목록의 맨 위가 우리 자신에 관한 것이었습니다.

우리 기록에 관한 것

  • [교정 필요] 지문별 ips_all_time이 과거 기록보다 낮아진 클러스터가 3개입니다(ZGrab 8/31 50 → 어제 35, libssh 8/29 289 → 어제 271, SSH-2.0-Go 8/30 27 → 9/04 19 → 어제 20). 지문 묶음 총수도 8/29 45 → 어제 37입니다. 영구 누적이 아니라 최근 구간만 세는 값일 가능성이 높지만, 집계 기준과 시작 시점이 데이터에 없어 확정할 수 없습니다. 이 값을 ’지금까지의 총계’로 읽어 온 지난 글의 서술은 교정이 필요합니다.
  • [확인 불가] 아카이브 대조는 8/16~9/04 브리프 20개를 글자로 맞춰 본 것입니다. 원재료가 아니라 우리가 쓴 글을 대조한 것이라, 과거 글에 안 적힌 값은 ’없었다’가 아니라 ’확인되지 않는다’로 읽어야 합니다.

데이터 자체에서 설명이 안 되는 것

  • [확인 불가] hxxp://5[.]182[.]210[.]174/ok의 서로 다른 해시가 지금까지 몇 종인지는 하한만 말할 수 있습니다. 8/25 10종 + 8/29 2종 + 어제 1종으로 최소 12종이며, 아카이브 20일치를 해시 단위로 전수 대조한 값은 아닙니다.
  • [확인 불가] 같은 주소·같은 1,608바이트인데 해시만 계속 바뀌는 이유를 모릅니다. 요청마다 만들어지는 것인지 짧은 주기로 갈아 끼우는 것인지 구분할 수 없고, 파일 내용을 담지 않으므로 무엇이 달라졌는지도 말할 수 없습니다. 8/22 · 8/23 · 8/25 · 8/27 · 8/29의 같은 항목이 그대로입니다.
  • [확인 불가] 399바이트 개인키가 심어진 것인지 가져가려 한 것인지 데이터가 구분해 주지 않습니다. downloads 배열에 있는데 주소 칸은 비어 있어요. 8/19의 미해결 항목이 여덟 번째 관측인 어제도 그대로입니다.
  • [확인 불가] 세션이 1,700건인데 포트별 합과 프로토콜별 합은 둘 다 1,698입니다. 2건이 어디에 속하는지 설명되지 않습니다.
  • [확인 불가] TTY 녹화가 한 곳에는 913건, 다른 곳에는 224건으로 적혀 있습니다. 두 값의 관계가 명시돼 있지 않습니다.
  • [확인 불가] 명령 1,715개 중 687개(40.1%)는 어떤 의도로도 분류되지 않았습니다. 그게 무엇이었는지는 원문이 없어 알 수 없습니다.
  • [확인 불가] 센서 02의 ADB 접촉 111건이 총계에는 들어갔는데 서비스 목록에는 없고, 어제 원재료에 ADB 상세 항목 자체가 없습니다. 센서 02에서 유일하게 투입 내용이 남는 통로인데 어제는 그 내용을 볼 수 없습니다. 231,196바이트 검체가 이 경로로 들어왔는지 확인할 수 없어요.
  • [확인 불가] 센서 02에서 한 출발지가 여러 서비스를 함께 훑었는지 계산할 수 없습니다. 서비스별 출발지 합(300)이 전체 고유 출발지(327)보다 작아 겹침을 역산할 수 없습니다. 이 값 0은 ’없음’이 아니라 **‘산출 불가’**입니다.
  • [확인 불가] 3356ae61…(SSH-2.0-PuTTY_Release_0.84)은 어제도 당일 3곳 = 누적 3곳입니다. 9/04에도 같은 값으로 ’처음 관측’이라고 적었어요. 같은 3곳이 이틀 연속 온 것인지 집계 방식 때문인지 구분할 수 없습니다. 8/21~8/23에도 같은 문제를 남겼습니다.
  • [확인 불가] ATK-DF93D5와 ATK-6757C8은 마스킹된 앞 두 옥텟이 171.249로 같은데 별칭이 다릅니다. 같은 대역의 다른 주소로 보이지만, 별칭 만드는 방식이 문서화돼 있지 않아 단정하지 않습니다. 마스킹된 값을 복원하려는 시도는 하지 않았습니다.
  • [확인 불가] SSH 배너 문자열과 RDP 쿠키 값은 상대가 스스로 보내는 값이라 위조할 수 있습니다. 우리에게 검증 수단이 없습니다.

일부러 싣지 않은 것 · 연결하지 않은 것

  • [제외] 별도 경로로 확보된 Discord 웹훅 주소 1건이 어제 어떤 세션·검체와 연결되는지 데이터가 밝히지 않습니다. 어제 다운로드 어느 항목에도 나타나지 않아 어제 사건과 연결해 쓰지 않았습니다. 웹훅 토큰은 그 자체가 악용 가능한 값이라 본문에 옮기지 않습니다. 8/17 이후 여러 글이 같은 이유로 제외해 왔습니다.
  • [제외] 배경 통계로 들어온 CVE 6,622건 · CISA KEV 390건 · 랜섬웨어 확인 98건과 상위 EPSS 목록은 KISA 보안공지에서 뽑은 값입니다. 어제 허니팟 관측과 연결되는 근거가 없어 사실 관계에 넣지 않았습니다.
  • [확인 불가] 관측한 유포지·C2는 C-TAS로 신고하지만, 확인되는 건 전송이 성공했다는 것까지입니다. KISA 적재 여부는 별도 확인이 필요합니다.

아예 판단하지 않는 것

  • ASN·ISP — 관련 데이터베이스가 없습니다. 추정하지 않습니다. 어제 유포지 185[.]93[.]89[.]72 · 5[.]182[.]210[.]174 · 31[.]77[.]227[.]121의 호스팅 사업자도 확인 불가입니다.
  • 지리정보 — 위와 같습니다. IP 지리정보는 애초에 귀속의 근거가 되지도 않습니다. 어제 접촉한 최대 766곳의 위치는 확인할 수 없고, 특정 국가·기업·개인을 공격자로 지목하지 않습니다.
  • VPN·Tor·클라우드 여부 — 판별 수단이 없습니다.
  • 검체의 악성 여부 — VirusTotal을 연동하지 않았습니다. 어제 저장된 7종(센서 01의 6종 + 센서 02의 1종)의 백신 진단명·탐지율은 확인 불가입니다.
  • User-Agent — 두 관측면 다 HTTP가 아닙니다. 센서 01은 SSH·텔넷, 센서 02는 SMB·RDP·VNC·MSSQL·LDAP·ADB입니다.
  • CVE 연결 — SSH·텔넷 공격은 대개 CVE를 참조하지 않고, 센서 02도 협상 단계라 마찬가지입니다. 어제 관측된 어떤 접촉도 특정 CVE를 공격했다고 말할 근거가 없습니다.
  • 명령 원문 · 파일 내용 · TTY 리플레이 — 우리 손에 없습니다. 913건이 녹화됐다는 사실만 알고, 화면에 무엇이 있었는지는 여기서 말할 수 없습니다.
  • 출발지 신원 — 별칭(ATK-XXXXXX)은 글과 글 사이에서 같은 출발지를 가리키는 표식일 뿐 신원이 아닙니다. 마스킹된 뒤 두 자리는 복원하지 않습니다.

어제 우리 서버에 들어온 것 중 새로운 건 파일 하나뿐이었고, 그마저도 열두 번째 재빌드였습니다. 남은 건 20일째 같은 스크립트와 여덟 번째 같은 3.7초짜리 세션이었어요.

그래서 어제 고친 건 공격자 쪽이 아닙니다. 우리 명단이었습니다. 50이 35가 된 건 사람이 줄어서가 아니라 판이 밀려서였고, 우리는 그걸 스무 날 만에 알았습니다. 숫자를 적을 때 어떤 판에 적히는 숫자인지를 같이 적어 두는 일이, 어제 배운 것 중 제일 쓸모 있는 것입니다.

관측일은 2026-09-05이며, 센서 01은 하루 집계 기준입니다. 출발지 IP는 뒤 두 자리를 가려서 적었고 복원하지 않습니다. 유포 주소는 접속되지 않도록 변형(defang)했습니다. 자격증명은 서로 다른 IP 3곳 이상에서 반복 관측된 20종만 인용했으며, 3곳 미만에서만 보인 935종은 개수만 세고 값은 적지 않았습니다.