Linux의 권한은 「누가 이 파일을 읽어도 되는가」라는 질문에 답합니다. AppArmor는 다른 질문에 답합니다. 「이 프로그램은 애초에 무엇을 해도 되는가」. 그 차이는 침해 때 드러납니다. 웹셸은 웹 서버의 사용자로 실행되며 그 권한을 전부 물려받습니다 — 그것은 시스템의 절반쯤에 대한 읽기 접근입니다. AppArmor 프로파일은 프로세스를 그 일에 필요한 목록으로 제한하며, /etc/shadow를 읽으려는 시도나 /bin/bash를 실행하려는 시도는 사용자의 권한과 무관하게 거부로 끝납니다.
이미 켜져 있는 것
sudo aa-status
출력은 세 가지 질문에 답합니다. 프로파일이 몇 개 적재됐는가, 그중 몇 개가 enforce와 complain 모드인가, 그리고 어떤 프로세스가 프로파일 없이 도는가. 전형적인 Ubuntu에는 프로파일이 수십 개 있지만 거의 전부가 man이나 tcpdump 같은 보조 프로그램을 위한 것입니다. 핵심 서비스 — nginx, Apache, PHP-FPM — 는 대개 제한 목록에 없습니다.
구별할 가치가 있는 세 가지 모드:
- enforce — 규칙이 적용되고 그 밖의 것은 거부됩니다;
- complain — 위반이 저널에 기록될 뿐 아무것도 차단되지 않습니다. 조율을 위한 모드입니다;
- unconfined — 프로파일이 없고 프로그램은 제한 없이 돕니다.
aa-status 출력에서 가장 쓸모 있는 부분은 마지막입니다. 네트워크에서 대기하면서 아무것에도 제한되지 않는 프로세스들. 거기서 시작할 목록입니다.
도구
sudo apt install apparmor-utils
그 패키지가 없으면 AppArmor 자체는 돌고 있어도 aa-complain, aa-enforce, aa-logprof 명령이 시스템에 없습니다.
서비스를 멈추지 않고 프로파일을 켜는 법
순서가 근본적입니다. 곧바로 enforce로 넘긴 프로파일은 높은 확률로 서비스에 필요한 무언가를 거부하고, 서비스는 작동을 멈춥니다 — 대개 즉시가 아니라 파일 업로드나 메일 발송 같은 드문 작업에서.
올바른 순서:
sudo aa-complain /etc/apparmor.d/usr.sbin.nginx
그 모드로 일주일의 작업, 드문 시나리오를 모두 겪으면서: 백업 뜨기, 업데이트, 큰 파일 업로드. 그다음 쌓인 것을 훑습니다.
sudo aa-logprof
이 명령은 기록된 위반을 하나씩 지나며 각각에 대해 허용할지 묻습니다. 여기서는 주의가 필요합니다. 눈에 보이는 것을 다 허용하지 말고 정말로 서비스의 일에 속하는 것을 허용하세요 — 그러지 않으면 모든 것을 허용하는 프로파일이 남고 의미가 사라집니다.
그리고 그 뒤에야:
sudo aa-enforce /etc/apparmor.d/usr.sbin.nginx
거부는 어디서 보는가
모든 위반은 커널 저널로 갑니다.
sudo journalctl -k | grep -i apparmor
sudo grep 'apparmor="DENIED"' /var/log/audit/audit.log
두 번째 파일은 auditd가 설치돼 있으면 존재하며, 그 경우 기록이 눈에 띄게 상세합니다. 거부 기록은 프로파일 이름, 요청된 작업, 접근하려던 경로를 보여 줍니다. 프로파일을 고칠지 아니면 그것이 작동한 것을 기뻐할지 판단하기에 충분합니다.
외워 둘 만한 증상이 하나 있습니다. 서비스가 이상하게 굽니다 — 설정을 읽지 못하고, 디렉터리에 쓰지 못하며, 소켓을 열지 못합니다 — 그러면서 자기 로그에는 권한이 분명히 올바른데도 「permission denied」 오류가 뜹니다. 그것은 거의 언제나 AppArmor이며, 가장 먼저 할 일은 커널 저널을 보는 것입니다.
이론이 아니라 실용적인 조치
PHP-FPM이나 nginx를 위한 프로파일은 구체적인 방식으로 값을 합니다. 프로세스가 제한돼 있으면, 사이트에 이른 웹셸은 시스템 파일을 읽지도, 셸을 실행하지도, 허용된 디렉터리 밖에 무언가를 쓰지도 못합니다. 해킹당한 사이트는 머신 전체에 대한 접근으로 바뀌는 대신 해킹당한 사이트로 남습니다 — 그리고 피해의 대부분을 차지하는 것이 바로 그 전환입니다.
합리적인 도입 순서: 먼저 인터넷을 향한 것(웹 서버, PHP-FPM)을 위한 프로파일, 그다음 데이터베이스, 그다음은 필요에 따라. 한꺼번에 전부 켤 필요는 없고, 보편적으로 준비된 모음 같은 것도 없습니다. 프로파일은 당신의 파일이 어디에 있는지에 달렸으니까요.
정기적으로 확인할 것
프로파일은 생각보다 자주 unconfined로 되돌아갑니다. 패키지 업데이트가 프로파일 파일을 바꿔 놓을 수 있고, 손으로 문제를 살피다 서비스가 complain에 남으며, 새 서비스는 아예 프로파일 없이 옵니다. 유용한 수치가 둘입니다. enforce인 프로파일이 몇 개인가, 그리고 네트워크를 향한 프로세스 중 unconfined가 몇 개인가. 둘 중 어느 것의 변화든 알아 둘 가치가 있습니다. 그것이 한 페이지에 모인 모습은 아래 데모에서.