접근을 얻는 것은 일의 절반이고, 나머지 절반은 그것을 잃지 않는 것입니다. 그래서 거의 모든 자동화된 악성 소프트웨어는 무엇보다 먼저 다시 시작될 방도를 마련합니다. 재부팅 뒤에도, 파일이 지워진 뒤에도, 비밀번호가 바뀐 뒤에도. 여기서 낯익은 이야기가 나옵니다 — 「정리했는데 이틀 뒤에 돌아왔다」.
그것이 마련되는 자리는 그리 많지 않고, 전부 몇 분이면 확인할 수 있습니다. 아래는 순서대로 도는 전체 코스입니다.
1. SSH 키
가장 단순한 귀환로. authorized_keys의 한 줄은 비밀번호 변경도, 시스템 업데이트도, 재부팅도 견딥니다.
sudo find /home /root -name authorized_keys -exec ls -l {} \; -exec cat {} \;
모든 줄은 누군가의 영구 접근입니다. 누구의 것인지 말할 수 없다면 남의 것으로 여기세요. 줄 끝의 주석도 눈여겨보세요. 그것은 임의의 텍스트이며, 당신 이름과 일치한다고 아무것도 증명되지 않습니다.
2. 모든 사용자의 cron 작업
확인해야 할 것은 당신 자신의 crontab만이 아닙니다.
for u in $(cut -f1 -d: /etc/passwd); do echo "== $u"; sudo crontab -u "$u" -l 2>/dev/null; done
sudo ls -la /etc/cron.d/ /etc/cron.hourly/ /etc/cron.daily/
sudo cat /etc/crontab
찾을 가치가 있는 표시들. @reboot 줄, 길게 인코딩된 명령, 셸로 파이프되는 curl이나 wget 호출, /tmp·/dev/shm·/var/tmp에서 시작되는 무엇이든. 그 디렉터리에서 실행되는 표준적인 것은 없습니다.
3. systemd 타이머와 서비스
cron의 현대적 등가물이며, 눈에 띄게 덜 확인됩니다.
systemctl list-timers --all
systemctl list-units --type=service --state=running
sudo ls -la /etc/systemd/system/ /run/systemd/system/
따로, root 권한 없이 돌며 전체 목록에 나타나지 않는 사용자 서비스:
systemctl --user list-units --type=service
sudo ls -la /home/*/.config/systemd/user/
세부 하나 더. 사용자에게 켜진 lingering(loginctl enable-linger)은 활성 세션 없이도 그 서비스가 돌게 해 줍니다. loginctl list-users로 확인하세요.
4. 셸 시작 파일
셸 시작 파일 끝에 덧붙여진 코드는 로그인할 때마다 실행됩니다.
sudo tail -5 /root/.bashrc /root/.profile /home/*/.bashrc /home/*/.profile
sudo ls -la /etc/profile.d/
특히 파일의 끝을 보세요 — 얼핏 볼 때 눈에 띄지 않도록 덧붙이는 자리가 거기입니다.
5. ld.so.preload
시작되는 모든 프로세스에 지정된 라이브러리를 시스템이 적재하게 만드는 파일입니다. 정상적인 상황에서는 결코 만들어지지 않습니다.
ls -l /etc/ld.so.preload
그 존재는 심각한 침해의 사실상 명백한 표시이며, 그런 라이브러리는 대개 파일도 프로세스도 네트워크 연결도 함께 숨깁니다. 그 뒤로 그 머신에서 보는 어떤 것도 신뢰할 가치가 없습니다.
6. 패키지 관리자 훅
좀처럼 떠올리지 않는 방법. apt는 모든 패키지 작업 전후에 명령을 실행할 수 있습니다.
sudo ls -la /etc/apt/apt.conf.d/
sudo grep -r 'DPkg::Pre-Invoke\|DPkg::Post-Invoke\|APT::Update' /etc/apt/apt.conf.d/
그런 훅은 업데이트를 설치할 때마다 걸립니다 — 즉 정기적으로, 그리고 root로.
7. Ubuntu의 오늘의 메시지
디렉터리 /etc/update-motd.d/에는 SSH로 로그인할 때마다 실행되어 인사 문구를 만드는 실행 스크립트가 있습니다. 이 자리가 편리한 이유는 바로 그것이 시스템의 일부처럼 보이기 때문입니다.
sudo ls -la /etc/update-motd.d/
8. 미뤄 둔 at 작업
sudo atq
sudo ls -la /var/spool/cron/atjobs/ 2>/dev/null
오래되고 좀처럼 쓰이지 않는 메커니즘이며, 그래서 가장 덜 확인됩니다.
무언가 찾았다면 무엇을 할 것인가
첫 충동은 발견물을 곧바로 지우는 것입니다. 그것은 실수입니다. 그것이 어떻게 거기 들어왔는지에 대한 정보가 함께 사라지고, 그 질문에 답하지 못하면 모든 일이 되풀이됩니다.
- 파일이나 작업의 사본과 그 수정 시각을 남기세요.
- 그 시각으로 웹 서버 로그와
auth.log에서 같은 분에 무슨 일이 있었는지 보세요. 대개 그곳에 진입점이 있습니다. - 무언가 나온 자리만이 아니라 목록의 여덟 군데 전부를 확인하세요. 백도어가 한 부만 남는 일은 거의 없습니다.
- 그 뒤에야 정리하고 취약점 자체를 닫으세요.
정상이 어떤 모습인지 알기
이 확인의 주된 어려움은 명령이 아니라, 작업 목록의 낯선 줄이 예전 목록을 기억하지 못하면 수상해 보이지 않는다는 사실입니다. 다른 사람이 설정했거나 1년 전에 설정한 서버에서 내 것과 남의 것을 가려내기란 거의 불가능합니다.
여기서 실용적 결론이 나옵니다. 「지금 있는 그대로」의 스냅숏을 뜨는 일은 서버가 멀쩡한 오늘 하는 것이 합리적입니다. 건강한 머신의 cron 작업, 타이머, 키, 서비스의 목록은 이후 모든 것이 비교되는 기준입니다. 이력과 함께 모아 두면 백도어 사냥은 몇 시간짜리 작업에서 두 목록의 비교로 바뀝니다. 그것이 어떤 모습인지는 아래 데모 페이지에서.