이 질문이 아무 이유 없이 떠오르는 경우는 드뭅니다. 서버가 느려졌거나, 호스팅 업체에서 나가는 트래픽에 관해 메일이 왔거나, 하지도 않은 로그인 알림이 메일함에 들어와 있습니다. 그다음부터 불쾌한 부분이 시작됩니다. 무엇을 어떤 순서로 봐야 할지 분명하지 않고, 첫 충동인 「다 지우고 새로 설치」는 거의 언제나 성급합니다.
아래는 스무 분쯤 걸리며 대부분의 경우 분명한 답을 주는 확인 순서입니다. 가장 값싼 것에서 가장 값비싼 것으로 나아갑니다. 먼저 바로 보이는 것, 그다음 어떤 기준과 맞춰 봐야 하는 것.
첫 단계: 누가 로그인했는가
로그인부터 시작합니다. 다른 사람이 들어왔다면 거의 확실히 SSH를 통해서였고, 흔적은 남아 있습니다.
last -20
lastb | head -20
who
last는 최근의 성공한 로그인을, lastb는 실패한 것을, who는 지금 접속해 있는 사람을 보여 줍니다. 중요한 것은 개수가 아니라 형태입니다. 다시는 돌아오지 않는 주소에서 온 수천 번의 실패한 시도는 평범한 배경 소음입니다. 그것은 모든 공개 주소를 상대로 쉬지 않고 돌아가며 아무 의미도 없습니다.
걱정해야 할 것은 다른 쪽입니다.
- 당신 쪽 사람이 아무도 없는 주소에서 성공한 로그인;
- 만든 적 없는 사용자 이름으로의 로그인;
- 이 서버에 실제로 존재하는 이름을 상대로 한 실패한 시도 — 이는 누군가 사전을 돌린 것이 아니라 당신의 사용자 목록을 알아냈다는 뜻입니다;
- 지금 열려 있는, 당신이 열지 않은 세션.
낯선 키가 생기지 않았는지도 따로 확인하세요. 파일 ~/.ssh/authorized_keys는 가장 흔한 잔류 수단입니다. 비밀번호는 몇 번이든 바꿔도 되지만 키는 남습니다.
cat ~/.ssh/authorized_keys
sudo cat /root/.ssh/authorized_keys
거기 있는 각 줄은 누군가의 접근 권한입니다. 누구의 것인지 말할 수 없다면 남의 것으로 여기세요.
두 번째 단계: 시스템에서 무엇이 바뀌었는가
침입은 거의 언제나 디스크에 흔적을 남깁니다. 바꿔치기된 바이너리, 설정에 늘어난 한 줄, 웹 서버 디렉터리의 새 파일. 이를 눈으로 확인하는 것은 가망이 없습니다 — 맞춰 볼 기준이 필요합니다.
Debian과 Ubuntu에서는 그 기준이 이미 있습니다. 모든 패키지가 자기 파일의 체크섬을 알고 있기 때문입니다.
sudo apt install debsums
sudo debsums -c
이 명령은 배포판이 설치한 것과 다른 파일들을 나열합니다. 결과 중 일부는 정당합니다 — /etc의 설정 파일은 수정하라고 있는 것이니까요. 하지만 손댄 적 없는 서버에서 /usr/bin, /usr/sbin, /bin의 실행 파일이 바뀌어 있다면 완전히 다른 이야기입니다.
두 번째 단서는 새것이 있을 리 없는 곳에 나타난 새 파일입니다. web shell은 대개 업로드 디렉터리에 앉아 있고 무해해 보이는 .php의 모습을 하고 있습니다.
find /var/www -type f -name '*.php' -mtime -14 -ls
14일은 출발점일 뿐입니다. 아무것도 게시하지 않았다고 확신하는 기간을 쓰세요.
세 번째 단계: 밖으로 무엇이 나가는가
장악된 서버가 그 서버 자체를 위해 뚫리는 일은 드뭅니다. 그것은 이용됩니다. 스팸을 보내려고, 채굴하려고, 다른 네트워크에 손을 뻗으려고, 남의 파일을 두려고. 그 모든 것이 이전에는 없던 나가는 연결을 만듭니다.
ss -tulpn
ss -tp state established
첫 번째 명령은 무엇이 대기 중인지, 두 번째는 지금 무엇이 연결돼 있는지 보여 줍니다. 프로세스 열을 읽으세요. 의문을 일으키는 것들: 0.0.0.0에서 대기하는 낯선 프로세스, 당신의 애플리케이션과 아무 상관없는 주소의 높은 포트로 나가는 연결, 그리고 무엇보다 /tmp나 /dev/shm에서 실행된 프로세스 — 그 디렉터리들에서 정당한 것이 도는 일은 없습니다.
겸사겸사 부하도 보세요. 채굴 프로그램은 인기라고는 전혀 없는 사이트에서 프로세서를 계속 바쁘게 만들어 스스로를 드러냅니다.
징후가 나타났다면
첫 충동은 빨리 치우는 것입니다. 남의 키를 지우고, 프로세스를 죽이고, 파일을 삭제하고. 그러지 마세요 — 그와 함께, 나중에 그들이 어떻게 들어왔는지 설명해 줄 수 있었던 바로 그것이 파괴됩니다. 그리고 그것이 밝혀지지 않은 채로 남으면 그들은 돌아옵니다. 어쩌면 내일이라도.
데이터와 전체 그림을 모두 지키는 순서:
- 제공된다면 서비스 업체에서 디스크 스냅샷을 뜨세요. 나중에 되풀이할 수 없는 유일한 단계입니다.
- 서버를 네트워크에서 끊거나, 자신의 IP를 제외한 모든 것을 닫으세요 — 다만 전원을 끄지는 마세요. 종료하면 프로세스 목록과 열린 연결이 사라지고, 그것이 증거의 절반입니다.
- 로그를 서버 밖으로 복사하세요:
/var/log/auth.log, 웹 서버 로그, 위 세 명령의 출력. - 그러고 나서야 그들이 어떻게 들어왔는지 밝혀냅니다.
접근 권한이 root 권한으로 얻어진 것이라면 깨끗한 재설치가 옳은 마무리입니다. 어떤 청소도 뒤에 아무것도 남지 않았다고 보장해 주지 않습니다. 다만 원인을 이해하지 못한 채 다시 설치하는 것은 무의미합니다. 같은 구멍을 새 시스템에 그대로 옮겨 놓게 됩니다.
이 질문이 불시에 오지 않게 하려면
위의 모든 것은 한 번뿐인 수동 확인이며, 그것이 답하는 것은 「지금 무슨 일이 일어나고 있는가」입니다. 문제는 그 질문이 대개 늦게 던져진다는 점입니다. 업체가 이미 연락을 했거나 사이트가 이미 내려간 뒤에요.
이 확인들은 각각 계속 지켜볼 수 있는 별도의 도구로 존재합니다. 실패한 로그인은 fail2ban, 파일 변경은 AIDE, 패키지 무결성은 debsums, 열린 포트는 ss의 정기 스냅샷. 하나씩 설치하는 것 자체는 어렵지 않습니다. 어려운 것은 매일 접속해 여섯 가지 출력을 읽는 습관을 들이는 일이고, 그래서 실제로는 아무도 읽지 않습니다.
그것들을 한데 모은 패널의 의미는 바로 거기에 있습니다. 같은 데이터를, 다만 한 페이지에 이력과 함께. 그러면 「어제는 이렇지 않았다」가 따로 찾아보지 않아도 눈에 들어옵니다. 조립된 모습이 어떤지는 아래 데모 페이지가 보여 줍니다.