지난 4회차까지 우리는 리눅스 서버 외곽에 단단한 성벽을 쌓는 네트워크 방화벽(UFW, Firewalld)과 SSH 접근 통제 기법을 마스터했습니다. 외부로부터의 침입 통로를 성공적으로 좁혔다면, 이제 시선을 내부로 돌려야 합니다. 보안 사고는 외부의 공격뿐만 아니라 내부 사용자의 부주의, 취약한 계정 관리, 혹은 권한 남용으로 인해서도 빈번하게 발생하기 때문입니다.
특히 여러 명의 개발자나 엔지니어가 하나의 리눅스 서버를 공유하여 사용하는 환경이라면 계정 보안의 중요성은 더욱 커집니다. 누군가 추측하기 쉬운 비밀번호를 사용하거나 권한을 과도하게 부여받았다면, 그 계정 하나가 뚫리는 순간 서버 전체가 위험에 빠집니다.
연재 다섯 번째 시간인 이번 글에서는 리눅스 내부 보안의 핵심인 '최소 권한의 원칙'에 입각한 계정 관리법과 시스템 인증을 총괄하는 PAM(Pluggable Authentication Modules)을 활용한 강력한 패스워드 규정 및 계정 잠금 정책을 구체적인 예시와 함께 알아보겠습니다.
리눅스 서버 보안에서 계정을 관리할 때 가장 먼저 선행되어야 할 원칙은 '최소 권한의 원칙(Principle of Least Privilege)'입니다. 각 사용자에게는 업무를 수행하는 데 꼭 필요한 최소한의 권한만 부여해야 하며, 공동 계정(예: 모두가 root로 로그인하거나 하나의 일반 계정을 공유하는 행위)의 사용을 철저히 금지해야 합니다. 공동 계정을 사용하면 보안 사고가 발생했을 때 '누가' 그 명령을 내렸는지 역추적하는 '책임 추적성'이 완전히 상실되기 때문입니다.
오랫동안 사용하지 않고 방치된 휴면 계정은 해커들의 좋은 타깃이 됩니다. 특정 계정(예: 퇴사자나 장기 휴가자의 계정 user01)을 완전히 삭제하기 전, 시스템 접근을 임시로 차단하려면 계정을 잠금 처리해야 합니다.
Bash
# 계정 잠금 (비밀번호 인증을 무효화합니다)
sudo usermod -L user01
# 계정 잠금 해제 (다시 복귀했을 때)
sudo usermod -U user01
비밀번호를 평생 바꾸지 않고 사용하는 것을 막기 위해 정책적으로 만료 주기를 강제해야 합니다. chage 명령어를 사용하면 세밀한 제어가 가능합니다.
Bash
# user01 계정의 비밀번호를 최소 7일간 변경 불가, 최대 90일마다 변경 강제, 만료 7일 전부터 경고 알림
sudo chage -m 7 -M 90 -W 7 user01
# 현재 특정 계정의 패스워드 만료 정보 상세 확인
sudo chage -l user01
리눅스에서 계정의 비밀번호 복잡성을 강제하거나 로그인 실패 시 잠금 기능을 구현하려면 PAM이라는 개념을 반드시 이해해야 합니다.
PAM은 리눅스 시스템 내의 다양한 애플리케이션(SSH, FTP, 로컬 로그인 등)과 실제 인증 기술(로컬 비밀번호, 생체 인식, OTP 등) 사이를 연결해 주는 플러그인 방식의 인증 프레임워크입니다. 개발자가 인증 프로그램을 매번 새로 짤 필요 없이, PAM 설정 파일만 수정하면 시스템 전체의 인증 규칙을 유연하게 바꿀 수 있습니다.
PAM 설정 파일은 주로 /etc/pam.d/ 디렉토리에 서비스별로 존재하며, 공통 정책은 system-auth 또는 password-auth(RedHat 계열), common-auth 또는 common-password(Ubuntu 계열) 파일에 정의됩니다.
쉬운 비밀번호(예: password123, admin!!)를 쓰지 못하도록 글자 수, 대소문자, 숫자, 특수문자 배화를 강제하는 설정을 해보겠습니다. 리눅스에서는 pam_pwquality(또는 과거 pam_cracklib) 모듈을 사용합니다.
RedHat 계열에서는 주로 /etc/security/pwquality.conf 파일에서 통합 관리가 가능합니다. 파일을 편집기로 엽니다.
Bash
sudo nano /etc/security/pwquality.conf
주석을 풀고 다음과 같이 값을 수정하여 엄격한 패스워드 룰을 적용합니다.
Plaintext
# 최소 패스워드 길이를 12자리로 제한
minlen = 12
# 최소한 포함해야 할 대문자 개수
ucredit = -1
# 최소한 포함해야 할 소문자 개수
lcredit = -1
# 최소한 포함해야 할 숫자 개수
dcredit = -1
# 최소한 포함해야 할 특수문자 개수
ocredit = -1
# 기존 비밀번호와 최소 몇 글자 이상 달라야 하는지 지정
difok = 3
참고: 크레딧(credit) 설정 시 음수(
-1)로 지정하면 해당 조건을 '최소 1개 이상 반드시 포함해야 하는 필수 조건'으로 강제한다는 의미가 됩니다.
Ubuntu 환경에서는 /etc/pam.d/common-password 파일을 직접 수정하거나 설정을 추가합니다.
Bash
sudo nano /etc/pam.d/common-password
비밀번호 변경을 담당하는 라인을 찾아 다음과 같이 매개변수를 추가 및 수정합니다.
Plaintext
password requisite pam_pwquality.so retry=3 minlen=12 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1
이렇게 설정을 마치면, 일반 사용자가 passwd 명령어로 단순한 비밀번호로 변경을 시도할 때 시스템이 거부 메시지를 출력하며 변경을 원천 차단합니다.
외부 공격자나 내부의 악의적인 사용자가 특정 계정의 비밀번호를 알아내기 위해 지속적으로 대입 기법을 시도할 때, 일정 횟수 이상 실패하면 해당 계정을 일시적으로 얼려버리는 정책이 필요합니다. 과거에는 pam_tally2 모듈을 썼으나, 최신 리눅스 커널 시스템(Rocky Linux 8/9, Ubuntu 22.04 이후) 표준은 pam_faillock 모듈입니다.
로컬 및 원격(SSH) 로그인 시 모두 적용되도록 설정을 진행해 보겠습니다.
/etc/pam.d/system-auth와 /etc/pam.d/password-auth 파일 상단에 규칙을 삽입해야 합니다. (최신 배포판은 authselect 도구를 사용해 프로파일을 생성하는 것을 권장하지만, 원리 이해를 위해 수동 설정 파일 기준으로 설명합니다.)
Bash
sudo nano /etc/pam.d/system-auth
auth 섹션과 account 섹션에 각각 다음과 같이 라인을 배치합니다.
Plaintext
# auth 섹션 최상단에 추가
auth required pam_faillock.so preauth silent audit deny=5 unlock_time=900
auth sufficient pam_unix.so try_first_pass
auth [default=die] pam_faillock.so authfail audit deny=5 unlock_time=900
# account 섹션 최상단에 추가
account required pam_faillock.so
deny=5: 연속으로 5회 로그인 실패 시 계정을 잠급니다.
unlock_time=900: 잠금 유지 시간입니다. 단위는 초(Second)이며, 900은 15분을 의미합니다. (0으로 설정하면 관리자가 수동으로 풀어주기 전까지 영구 잠금 상태가 됩니다.)
silent: 로그에 실패 기록은 남기되 사용자 화면에는 불필요한 프롬프트 경고를 띄우지 않아 보안 힌트를 주지 않습니다.
pam_faillock 모듈을 적용해 두면 실제 사용자가 비밀번호를 입력하다가 실수로 계정이 잠기는 트러블슈팅 상황이 빈번히 발생합니다. 시스템 관리자는 이를 모니터링하고 수동으로 풀어줄 수 있어야 합니다.
Bash
# user01 계정의 실패 로그 및 잠금 여부 확인
sudo faillock --user user01
명령어를 실행하면 유효한 실패 횟수와 타임스탬프, 접속을 시도했던 IP 주소 목록이 상세히 나옵니다.
사용자의 신원이 확인되었거나 오인 잠금인 경우, 관리자가 즉시 잠금을 해제하여 업무에 복귀시킬 수 있습니다.
Bash
# user01 계정의 실패 기록을 리셋하고 잠금을 해제합니다
sudo faillock --user user01 --reset
이번 시간에는 리눅스 시스템 내부 보안의 핵심 이정표인 촘촘한 권한 관리와 PAM 모듈 활용법에 대해 자세히 다루어 보았습니다.
아무리 튼튼한 방화벽을 세우고 포트 번호를 변경했더라도, 내부 사용자가 유추하기 쉬운 만만한 패스워드를 방치하거나 퇴사자의 계정이 버젓이 살아 움직인다면 인프라의 성벽은 내부에서부터 무너지게 됩니다.
사용자별 독립 계정 발급, 주기적인 패스워드 만료제 도입, PAM을 통한 복잡성 강제 및 자동 잠금 정책 수립은 내부 위협과 자원 남용을 막는 가장 확실한 예방 주사입니다. 귀찮더라도 초기에 계정 정책을 엄격하게 수립해 두는 것이 엔터프라이즈급 인프라 안전성을 확보하는 지름길입니다.
다음 6회차에서는 시스템 내부 보안을 한 단계 더 깊숙이 파고들어 가 보겠습니다. 리눅스의 모든 파일과 디렉토리를 보호하는 근간인 권한 체계를 분석하고, 특수 권한(SetUID, SetGID, Sticky Bit)의 위험성 점검 및 더 정교한 통제가 가능한 '파일 시스템 권한 강화와 ACL 활용법'에 대해 상세히 알아보겠습니다.