보안

리눅스 인증 로그 읽기 - auth.log로 무차별 대입 흔적 찾기

jmineekim 2026. 10. 1. 18:31

공인 IP로 SSH 포트를 열어 둔 서버에 들어가 인증 로그를 열어 보면, 처음 보는 계정 이름으로 로그인 실패가 수백 줄씩 쌓여 있는 경우가 흔합니다. admin, test, oracle 같은 이름들이죠. 대부분은 인터넷 전체를 훑는 자동화 스캐너가 남긴 흔적이라 그냥 넘기기 쉽습니다. 문제는 그 수백 줄 사이에 진짜로 성공한 한 줄이 섞여 있을 때입니다. 그 한 줄을 골라내는 눈이 있는지가 서버 담당자와 보안담당자를 가르는 차이예요. 로그 한 줄 한 줄이 무슨 뜻인지부터 시작해서, 공격 패턴을 집계하고 자동으로 막는 데까지 가 보겠습니다.

인증 로그는 어디에, 어떻게 쌓이나 (개념)

리눅스에서 SSH 로그인, sudo, su, 계정 생성 같은 인증 관련 이벤트는 syslog의 auth·authpriv 분류(facility)로 기록됩니다. 이걸 받아서 파일로 쓰는 게 rsyslog이고, 어느 파일에 쓰는지는 배포판마다 다릅니다.

배포판 계열 인증 로그 파일 rsyslog 설정
Ubuntu·Debian /var/log/auth.log auth,authpriv.* /var/log/auth.log
RHEL·Rocky·CentOS /var/log/secure authpriv.* /var/log/secure

인증 로그가 쌓이는 경로


systemd를 쓰는 배포판은 같은 내용이 journald에도 들어갑니다. rsyslog가 설치되지 않은 배포판이나 최소 설치 이미지라면 파일이 아예 없을 수 있어서, 그때는 journalctl로 봐야 합니다.

로그 파일과 별개로, 로그인 기록을 담는 바이너리 파일도 있습니다.

파일 내용 확인 명령
/var/log/wtmp 로그인·로그아웃 기록 last
/var/log/btmp 로그인 실패 기록 sudo lastb

텍스트 로그는 "무슨 일이 있었나"를, wtmp·btmp는 "누가 언제 들어왔다 나갔나"를 보는 도구라고 생각하면 편합니다.

실습 서버에 공격 흔적 만들어 보기 (실습)

실행 환경: Ubuntu 24.04 / OpenSSH 9.6p1 / rsyslog — 외부와 분리된 실습 서버에서 진행했습니다.

존재하지 않는 계정 4개로 한 번씩, 실제 계정 alice로 두 번 틀린 뒤 성공하고, 로그인한 다음 sudo를 실행했습니다. 이때 auth.log에 남은 줄을 유형별로 추리면 이렇습니다.

sshd[1219]: Invalid user admin from 127.0.0.1 port 38828
sshd[1219]: Failed password for invalid user admin from 127.0.0.1 port 38828 ssh2
sshd[1223]: Failed password for root from 127.0.0.1 port 38844 ssh2
sshd[1236]: Failed password for alice from 127.0.0.1 port 44584 ssh2
sshd[1244]: Accepted password for alice from 127.0.0.1 port 45838 ssh2
sshd[1244]: pam_unix(sshd:session): session opened for user alice(uid=1001) by alice(uid=0)
sudo:    alice : PWD=/home/alice ; USER=root ; COMMAND=/usr/bin/cat /etc/shadow
sudo:    alice : 1 incorrect password attempt ; PWD=/home/alice ; USER=root ; COMMAND=/usr/bin/id

읽는 법은 단순합니다.

메시지 의미
Invalid user X 서버에 없는 계정으로 시도
Failed password for invalid user X 없는 계정 + 비밀번호 실패
Failed password for X 실제 있는 계정의 비밀번호 실패
Accepted password / Accepted publickey 로그인 성공 (인증 방식 포함)
sudo: 사용자 : ... COMMAND= 누가 어떤 명령을 root로 실행했나

invalid user가 붙지 않은 실패는 공격자가 계정 이름을 이미 맞혔다는 뜻이라 더 주의해서 봐야 합니다. 참고로 이 환경의 rsyslog는 2026-10-01T17:42:29.457758+09:00 같은 ISO 8601 형식으로 시간을 찍었습니다. 구버전은 Oct 1 17:42:29 형식이라 스크립트를 짤 때 이 차이를 고려해야 합니다.

공격 패턴을 집계로 읽기 (탐지)

한 줄씩 읽는 건 한계가 있으니 집계합니다. 먼저 IP별, 계정별 실패 횟수입니다.

# IP별 로그인 실패 횟수
sudo grep "Failed password" /var/log/auth.log \
  | grep -oE "from [0-9a-fA-F:.]+" | awk '{print $2}' \
  | sort | uniq -c | sort -rn | head

# 계정별 로그인 실패 횟수 (invalid user 포함)
sudo grep "Failed password" /var/log/auth.log \
  | sed -E 's/.*Failed password for (invalid user )?([^ ]+) from.*/\2/' \
  | sort | uniq -c | sort -rn | head

실습 로그에서 계정별 집계는 이렇게 나왔습니다.

      2 alice
      1 test
      1 root
      1 oracle
      1 admin

계정별 실패 집계 (실습 서버 실제 출력)


집계 결과는 패턴으로 해석합니다. MITRE ATT&CK은 이런 공격을 무차별 대입(T1110)으로 묶고 세부 기법을 나눕니다.

보이는 패턴 의심할 기법
IP 하나, 계정 하나, 실패 다수 비밀번호 추측 (T1110.001)
IP 하나, 계정 여러 개, 계정당 실패 1~2회 패스워드 스프레이 (T1110.003)
여러 IP에서 같은 계정으로 실패 분산 공격 — IP 차단만으로는 못 막음

가장 중요한 건 실패 뒤의 성공입니다. 아래 명령은 alice의 실패 횟수를 세다가 성공한 줄을 만나면 함께 출력합니다.

sudo awk '/Failed password for alice / {f++}
          /Accepted .* for alice / {print "실패 " f "회 후 성공: " $0}' /var/log/auth.log
실패 2회 후 성공: 2026-10-01T17:42:48.220197+09:00 vm sshd[1244]: Accepted password for alice from 127.0.0.1 port 45838 ssh2

실패가 몰린 IP에서 성공이 나왔다면 침해를 전제로 그 세션이 무엇을 했는지(sudo 기록, 셸 히스토리, 새로 생긴 계정·키)를 바로 확인해야 합니다.

journald만 있는 환경이라면 같은 내용을 이렇게 봅니다.

journalctl _COMM=sshd --since today | grep -E "Failed|Accepted"
journalctl _COMM=sudo --since "1 hour ago"

하나 더 알아 둘 점이 있습니다. 실습에서 ssh 서버 명령어처럼 터미널 없이 명령만 실행한 접속은 last에 나오지 않았습니다. wtmp는 터미널(pty)이 할당된 세션 위주로 기록되기 때문입니다. last에 없다고 접속이 없었던 게 아니니, 판단은 텍스트 로그 기준으로 해야 합니다.

막고, 남기고, 보관하기 (대응)

1) fail2ban으로 반복 실패 IP 자동 차단. fail2ban은 로그에서 실패 패턴을 찾아 일정 횟수를 넘긴 IP를 방화벽으로 막습니다. 실습 환경(Ubuntu 24.04, fail2ban 1.0.2)은 설치만 해도 sshd 감시가 켜져 있었고, 기본 설정이 auth.log가 아니라 journald를 읽도록(backend = systemd) 되어 있었습니다. 기준을 조정하려면 jail.local에 덮어씁니다.

# /etc/fail2ban/jail.local
[sshd]
enabled  = true
maxretry = 5
findtime = 10m
bantime  = 1h
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd                                   # 차단 현황
sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf  # 필터가 로그를 잡는지 확인

실습 로그(45줄)에 fail2ban-regex를 돌려 보니 9줄이 sshd 필터에 걸렸습니다.

fail2ban이 IP를 차단하는 흐름


단, 앞의 표처럼 여러 IP에서 분산해 들어오는 공격은 IP 차단으로 못 막습니다. 근본 대책은 비밀번호 로그인을 끄고 키 인증만 허용하는 것입니다. 키 로그인이 되는지 먼저 확인한 다음 sshd_config에서 PasswordAuthentication no로 바꾸세요.

2) 로그를 서버 밖으로 보내기. 침입자가 root를 얻으면 가장 먼저 지우는 게 로그입니다. 인증 로그만이라도 별도 로그 서버로 보내 두면 지워도 원본이 남습니다.

# /etc/rsyslog.d/60-forward-auth.conf  (@@는 TCP, @는 UDP)
auth,authpriv.*  @@logserver.example.internal:514

3) 보관 기간 확인. 실습 환경의 기본 logrotate 설정은 auth.log를 주 단위로 4개까지만 보관했습니다(weekly, rotate 4). 사고는 보통 한참 뒤에 발견되는데, 이 기본값이면 한 달 남짓 전 기록은 이미 사라져 있습니다. 조직의 보관 정책에 맞게 /etc/logrotate.d/rsyslog의 값을 늘리거나 중앙 로그 서버에서 장기 보관하세요.

인증 로그, 이 세 가지만 챙기세요 (마무리)

  • invalid user가 없는 실패, 그리고 실패 뒤에 나온 Accepted 한 줄이 진짜 경보다.
  • IP별·계정별로 집계하면 비밀번호 추측인지 스프레이인지 분산 공격인지 구분된다.
  • fail2ban은 응급처치, 근본 대책은 키 인증 전환과 로그 외부 전송·충분한 보관이다.

원문과 표준 문서 (참고 자료)

반응형