직원 세 명인 회사에 하루 4,812번
이 편에서 다루는 접근 로그는 직원이 세 명인 회사의 것입니다. 어젯밤 하루 동안 관리자 페이지에 로그인 시도가 4,812번 들어왔습니다. 회사 규모가 작으니 공격 대상이 아닐 것이라고 생각하시는 경우가 많은데, 실제로는 규모와 관계가 없습니다.
관리자 주소를 /wp-login.php나 /admin처럼 기본값 그대로 두면 하루에 이 정도가 들어옵니다. 공격하는 쪽에서는 사람이 확인하는 것이 아니라 프로그램이 인터넷 전체를 훑으면서 기본 경로를 두드리기 때문입니다.
무작위가 아닙니다
로그에 남은 시도를 계정과 비밀번호 조합으로 정리해 보면 성격이 분명하게 드러납니다. 아무 문자열이나 넣어 보는 것이 아니라, 흔한 계정 이름에 다른 사이트에서 유출된 비밀번호 목록을 순서대로 붙여 넣는 방식입니다.
- 계정은
admin,administrator, 회사 도메인 앞부분, 대표자 이름의 영문 표기처럼 추측하기 쉬운 값이 반복됩니다. - 비밀번호는 이미 유출되어 공개된 목록에서 순서대로 꺼내 씁니다.
- 시도가 몰린 구간의 간격은 0.4초였습니다. 사람이 손으로 입력하는 속도가 아닙니다.
그래서 다른 서비스에서 쓰던 비밀번호를 관리자 계정에 그대로 쓰고 계시다면, 그 조합은 이미 목록 안에 들어 있을 가능성이 있습니다.
4,812번 중 한 번만 맞으면 끝납니다
로그에는 401 응답이 길게 이어지다가 302 응답이 한 줄 찍힙니다. 인증에 성공했다는 뜻입니다. 그리고 그 바로 다음 줄부터 파일 업로드 요청이 나타납니다.
이 시점부터는 로그인 시도의 횟수가 의미를 잃습니다. 관리자 권한을 얻은 쪽은 웹셸을 올리고, 그 웹셸로 스팸 페이지를 계속 만들어 냅니다. 검색 결과에 낯선 페이지가 쏟아지는 상태가 어떻게 시작되는지는 홈페이지가 해킹됐는지 10초 만에 확인하는 방법에서 다뤘습니다.
확인은 한 줄입니다
접근 로그에서 관리자 주소가 몇 번 호출됐는지 세어 보시면 됩니다.
grep -c "wp-login.php" /var/log/nginx/access.log
awk '/wp-login/{print $1}' access.log | sort | uniq -c | sort -rn
첫 줄은 전체 호출 횟수를 세고, 둘째 줄은 어느 IP 가 얼마나 두드렸는지 많은 순서로 보여 줍니다. 워드프레스를 쓰지 않는 사이트라면 wp-login.php 자리에 /admin, /manager처럼 실제로 사용하는 관리자 경로를 넣어서 세셔야 합니다.
하루 호출이 수백 건을 넘는다면 아직 뚫리지 않았을 뿐, 이미 목표가 된 상태입니다.
즉시 적용할 조치 네 가지
- 관리자 주소를 기본값에서 바꿉니다.
/wp-login.php와/admin을 회사만 아는 경로로 옮기면 자동화된 시도의 대부분이 그 자리에 닿지 못합니다. - 2단계 인증을 켭니다. 비밀번호가 맞아떨어져도 그 앞에서 한 번 더 막힙니다.
- 접속 가능한 IP 를 제한합니다. 사무실과 VPN 대역만 관리자 페이지에 닿게 두면 나머지 요청은 서버에서 바로 끊깁니다.
- 실패 횟수로 자동 차단합니다. 5회 실패한 IP 를 일정 시간 동안 서버가 직접 거부하도록 설정합니다.
네 가지를 함께 적용하셔야 효과가 있습니다. 비밀번호만 길게 바꾸는 조치로는 시도 횟수가 줄어들지 않습니다. 이미 유출된 목록을 대입하는 방식이기 때문에, 길이를 늘리는 것은 성공 확률만 낮출 뿐 두드리는 행위 자체를 막지 못합니다.