전권 sudo 가 남긴 문
한 줄 요약
NOPASSWD: ALL 은 그 계정이 곧 root 라는 뜻입니다. sudo 는 각 계정이 꼭 필요한 명령만, 가능하면 비밀번호와 함께 쓰게 좁히는 도구입니다. 좁힐 때는 마지막으로 일치하는 규칙이 이긴다는 규칙과 셸 탈출이라는 함정을 알아야 합니다.
왜 이게 필요했나
자동화 계정과 당번 계정은 비밀번호를 물어볼 수 없어서 NOPASSWD 를 받습니다. 그런데 그 범위가 전권이면, 그 계정의 토큰이나 세션 하나가 새는 순간 공격자는 아무 명령이나 root 로 실행합니다. 권한 상승이 필요 없습니다 — 이미 전권이기 때문입니다.
처음에는 "일단 다 되게" 두고 나중에 좁히려 합니다. 그 나중이 오지 않습니다. 그래서 흔한 서버에 ALL=(ALL) NOPASSWD: ALL 을 받은 사람이 여럿 남습니다.
어떻게 동작하나
sudoers 규칙은 사용자 호스트=(실행계정) 명령 꼴입니다. 명령을 절대 경로와 인자까지 적으면 그 조합만 허용됩니다.
deployer ALL=(root) NOPASSWD: /usr/bin/systemctl restart shopapi
두 함정이 있습니다.
첫째, sudoers 는 여러 규칙이 일치하면 마지막 것을 적용합니다. 좁은 규칙을 추가해도 아래에 NOPASSWD: ALL 줄이 남아 있으면 그 줄이 이깁니다. 그래서 좁히는 일은 "추가" 가 아니라 "전권 줄을 지우고 좁은 줄로 대체" 입니다.
둘째, 셸 탈출입니다. 페이저(less), 편집기(vi), 또는 임의 명령을 부를 수 있는 도구를 NOPASSWD 로 주면, 그 안에서 !sh 같은 방법으로 셸로 빠져나가 사실상 전권이 됩니다. 그래서 파일을 편집하게 하려면 sudoedit 을, 로그를 보게 하려면 범위를 좁힌 journalctl 을 씁니다.
sudoers 를 고칠 때는 반드시 visudo 를 씁니다. 저장할 때 문법을 검사해서, 깨진 규칙으로 sudo 전체가 잠기는 사고를 막습니다. 드롭인은 /etc/sudoers.d/ 에 두고 파일 권한은 440 이어야 합니다. 특정 계정의 유효 규칙은 sudo -l -U <계정> 으로 봅니다 — 파일을 읽는 것과 sudo 가 실제로 해석한 결과는 다를 수 있습니다.
현장에서 만나는 모습
가장 흔한 사고는 "좁혔는데 안 좁혀진" 경우입니다. 좁은 규칙을 추가하면서 전권 줄을 지우지 않아, 테스트로 sudo -l 을 보면 좁은 규칙이 보이는데 실제로는 아래 전권 줄이 이깁니다. 둘째는 로깅입니다. sudo 사용을 logfile 과 log_input/log_output 으로 남기면, 사고가 났을 때 "누가 무엇을 root 로 했는가" 에 답할 수 있습니다.
English corner
- least privilege: 최소 권한. 일에 필요한 만큼만 줍니다.
- NOPASSWD: 비밀번호 없이 허용. 자동화 계정이 받지만 범위를 좁혀야 합니다.
- last match wins: 마지막으로 일치하는 규칙이 이긴다. sudoers 의 평가 방식입니다.
- shell escape: 셸 탈출. 허용된 프로그램에서 셸로 빠져나가 권한을 넓히는 것입니다.
다음 실습에서 할 것
전권 sudo 를 받은 두 팀 계정을 각자 꼭 필요한 명령으로 좁히고, 허용된 일은 되고 넘치는 일은 막히는지 양쪽을 확인한 뒤, sudo 사용을 로그로 남깁니다.
한 걸음 더 — 그룹과 Defaults
sudoers 는 개별 계정 말고 그룹에도 규칙을 겁니다(%wheel, %sudo). 그룹 규칙은 편하지만, 그 그룹에 누가 들어 있는지를 따로 보지 않으면 '좁힌 줄 알았는데 그룹을 통해 전권' 인 경우가 생깁니다. 권한 검토 때는 규칙과 그룹 구성원을 함께 봐야 합니다.
Defaults 줄도 보안에 영향을 줍니다. requiretty, env_reset, secure_path 가 그 예입니다. 특히 secure_path 는 sudo 가 쓰는 PATH 를 고정해, 공격자가 PATH 를 조작해 가짜 바이너리를 root 로 실행시키는 것을 막습니다. 명령을 절대 경로로 적는 습관과 secure_path 는 같은 위협을 두 겹으로 막는 셈입니다.
점검 순서
- 사람 계정에
NOPASSWD: ALL이나(ALL) ALL이 남아 있지 않은가(sudo -l -U). - 자동화 계정의 NOPASSWD 범위가 명령 단위로 좁혀져 있는가.
- NOPASSWD 로 준 명령에 셸·페이저·편집기 탈출 경로가 없는가.
- sudo 사용이 로그로 남는가. 그룹 규칙의 구성원이 검토됐는가.