서론
최근 지인의 자취방에서 침해 사고 대응에 관한 교육 자료를 가져온 적이 있다. 책꽂이 한 켠에 꽂혀 있던 케케묵은 2016년 자료였으나, 그 안에 적힌 내용의 상당 부분이 오늘날에도 거의 그대로 적용된다는 사실이 웃프게 다가왔다. 그러던 차에 공개된 것이 2017년 이후 출시된 거의 모든 주요 배포판에 영향을 미친 리눅스 커널 로컬 권한 상승(LPE) 취약점, Copy Fail(CVE-2026-31431)이다. 구조적으로 내 환경에서 이 취약점이 악용될 가능성은 대단히 낮지만, 10년이 지나도록 책자의 내용이 거의 달라지지 않았다는 사실과 맞물리자, 평소 정리 우선순위가 낮다는 이유로 방치해 두었던 EC2 인스턴스를 더 이상 두고 볼 수 없게 만드는 자극으로는 충분했다. 그리하여 오랜만에 접속하게 되었고, 기왕 접속한 김에 휴면 기간 동안 외부로부터 어떠한 영향을 받지 않았는지 간단히 확인해 보았다. 본 글은 그 과정을 간략히 기록한 것이다.
점검
AI에게 내 서버에서 일어난 일들을 살펴보려면 어떤 작업들을 하면 되는지 물어보았다. 그러자 다음과 같은 명령어들을 잔뜩 내뱉었다.
w; who; last -20 # 현재 세션, 최근 로그인 lastb -20 # 실패한 로그인 (sudo 필요) ps auxf # 프로세스 트리 ss -tulpnH # 열린 포트 + 어떤 프로세스 ss -tnp # 현재 외부 연결
sudo grep -E "Accepted|Failed" /var/log/auth.log | tail -50 cat ~/.ssh/authorized_keys # 모든 사용자에 대해 sudo find /home /root -name "authorized_keys" -exec ls -la {} \; -exec cat {} \; sudo cat /etc/passwd | grep -v nologin # 셸 가진 계정 sudo cat /etc/shadow | awk -F: '$2!="*"&&$2!="!"&&$2!~/^!/ {print $1}' # 패스워드 설정된 계정 sudo cat /etc/sudoers /etc/sudoers.d/*
sudo systemctl list-unit-files --state=enabled sudo ls -la /etc/systemd/system/ /etc/systemd/user/ sudo crontab -l; for u in $(cut -f1 -d: /etc/passwd); do sudo crontab -u $u -l 2>/dev/null; done sudo ls -la /etc/cron.* /var/spool/cron/ cat /etc/rc.local 2>/dev/null ls -la ~/.bashrc ~/.profile /etc/profile.d/
sudo find / -xdev -mtime -7 -type f -not -path "/proc/*" -not -path "/sys/*" 2>/dev/null | head -100 sudo find /tmp /var/tmp /dev/shm -type f -ls 2>/dev/null # 흔한 드롭 위치 sudo debsums -c 2>/dev/null | head # 변조된 패키지 파일
sudo iptables -L -n -v; sudo iptables -t nat -L -n -v ip route; cat /etc/resolv.conf sudo journalctl -u ssh --since "7 days ago" | grep -i "accept\|fail" | tail
나는 결코 나의 아름다운 새벽의 밤을 저 명령어들의 복붙에 쓰고 싶지 않았다. 분명 나만 귀찮은 것은 아닐 것이다. 수십, 수백 개의 인스턴스를 관리하는 실무에서 이를 자동화하는 솔루션은 누군가 이미 만들어 두었을 것이다. 그리하여 나는 AI에게 다시 한번 질문했다.
이런걸 자동으로 해주는 오픈소스 솔루션 있어?
그렇게 약간의 발품을 판 끝에 찾은 것이 Velociraptor (Rapid7, 오픈소스) 이다.
velociraptor
Velocidex • Updated Aug 14, 2026
Rapid7과 스타 4k 개의 오픈소스를 불신하기엔 나의 시간이 충분하지 않았기에, 곧바로 나의 인스턴스에 Velociraptor를 설치했다.
mkdir ~/ir && cd ~/ir
curl -LO $(curl -s https://api.github.com/repos/velocidex/velociraptor/releases/latest \ | jq -r '[.assets[] | .browser_download_url | select(test("linux-amd64$"))][0]') chmod +x velociraptor-*-linux-amd64 ln -sf velociraptor-*-linux-amd64 vr
그 이후 아래 명령어를 실행했다.
sudo ./vr -v artifacts collect \ Linux.Sys.Pslist \ Linux.Sys.SUID \ Linux.Sys.Services \ Linux.Sys.Crontab \ Linux.Sys.BashHistory \ Linux.Sys.LastUserLogin \ Linux.Network.Netstat \ Linux.Ssh.AuthorizedKeys \ Linux.Ssh.KnownHosts \ Linux.Mounts \ Linux.Debian.Packages \ --output triage.zip
triage.zip 에 결과가 떨어지는데, VSCode를 통해 빠르게 훑어볼 수 있었다. AuthorizedKeys나 LastUserLogin, BashHistory 같은 정보는 수동으로 확인했고, 나머지는 챗봇의 도움을 받아 분석을 수행했다. 추후 도메인별로 분석을 해주는 솔루션이 있다면 한번 사용해 보면 좋을 듯하다.- 패키지 관리자에 의해 설치된 표준 항목 외의 추가 구성 요소는 확인되지 않음
- 권한 상승 후보가 될 수 있는 SUID 바이너리는 배포판 표준 목록과 일치.
- 자동 실행 항목은 운영체제 패키지가 설치하는 표준 작업(로그 회전, 패키지 캐시 갱신, 인증서 갱신 등)에 한정되어 있음.
결론
위 결과를 두고 "침해는 없었다"라고 결론짓는 것은 적절하지 않다. 이것은 단발성 호스트 점검의 기록이다. 결과는 양호하였으나, 단발 점검이 가지는 한계는 명확하다. 점검의 진정한 가치는 한 차례의 수행이 아니라 결과의 축적, 즉 베이스라인 확보와 차후 점검과의 비교 가능성에서 발생한다.
Copy Fail과 같은 메모리 상주형 위협에 대한 대응은 사후 분석이 아닌 사전telemetry의 도입을 통해서만 의미 있게 가능하다. 단발 점검에서 흔적이 발견되지 않았다는 사실 자체가 안심의 근거가 되어서는 안 되며, 다음 점검과 비교할 수 있도록 결과를 보존하는 절차가 더 본질적이다.
본 포스팅은 단발성 점검의 절차를 정리한 것일 뿐, 이를 권장하거나 충분한 보안 활동이라 주장하지 않는다. 다만 미뤄왔던 정리 작업의 동기가 되어 준 한 건의 취약점 공개가, 평소 외면해 왔던 인프라의 현재 상태를 들여다보는 계기가 되었다는 점은 기록할 만한 가치가 있다고 본다. 사람 일은 모르는 법이니, 한번 나의 VPC도 확인을 해보자. 어떤 나쁜 친구가 1코어 2기가의 컴퓨터로 채굴을 하고 있을지도 모르는 일이니까.

