Linux에서 비밀번호 정책 설정 및 공격 탐지

사이버 보안Beginner
지금 연습하기

소개

이 실습에서는 강력한 비밀번호 정책을 구현하고 적용하여 Linux 시스템의 보안을 강화하는 핵심 기법을 익힙니다. 시스템 전체에 적용되는 규칙을 설정하여 비밀번호의 최소 길이와 대문자, 소문자, 숫자 등 서로 다른 문자 유형의 조합을 요구합니다. 또한 비밀번호를 정기적으로 변경하도록 만료 정책을 설정하여, 핵심 시스템 구성 파일을 수정함으로써 유출된 비밀번호로 인한 위험을 줄입니다.

정책을 설정한 후에는 이러한 강력한 비밀번호 요구 사항이 새 사용자 계정에도 적용되는지 확인합니다. 이어서 실습은 사전 예방적 보안 조치에서 사후 탐지 단계로 전환되어 시스템 인증 로그를 모니터링하는 방법을 다룹니다. 로그를 분석하면 반복적인 로그인 실패 시도와 같은 의심스러운 활동을 식별할 수 있으며, 이는 무차별 대입 공격이나 기타 무단 접근 시도의 징후일 수 있습니다.

복잡도 및 만료를 위한 로컬 Linux 비밀번호 정책 설정

이 단계에서는 강력한 비밀번호 정책을 구성하여 Linux 시스템의 보안을 강화하는 방법을 익힙니다. 강력한 비밀번호 정책은 복잡도만료라는 두 가지 핵심 요소를 강제하는 기본적인 보안 제어 수단입니다. 복잡도 규칙은 여러 문자 유형을 조합하도록 하여 비밀번호를 쉽게 추측할 수 없게 합니다. 만료 규칙은 사용자가 주기적으로 비밀번호를 변경하도록 하여 자격 증명이 유출되었을 때의 위험을 줄입니다. 표준 Linux 유틸리티를 사용해 시스템 전체 구성 파일을 수정하고 이러한 정책을 적용합니다.

먼저 비밀번호 복잡도 설정을 살펴보겠습니다. Ubuntu와 같은 최신 Debian 기반 시스템에서는 pam_pwquality 모듈이 비밀번호 품질을 관리합니다. 이 모듈의 구성은 /etc/security/pwquality.conf 파일에 저장됩니다.

기본 설정부터 확인해 보겠습니다. cat 명령으로 구성 파일의 내용을 확인합니다. 출력 결과를 깔끔하게 보기 위해 grep으로 주석 처리된 줄과 빈 줄을 제외합니다.

grep -vE '^#|^$' /etc/security/pwquality.conf

일부 기본 설정이 표시되거나 활성 구성 항목이 없어 파일이 비어 있을 수도 있습니다. 이제 더 강력한 정책을 적용하겠습니다. 이 파일을 수정하려면 관리자 권한이 필요하므로 sudonano 편집기를 사용합니다.

sudo nano /etc/security/pwquality.conf

파일에 다음 줄을 추가하여 새 정책을 적용합니다. 이 설정은 비밀번호 길이를 최소 10자로 제한하고, 숫자 하나 이상, 대문자 하나 이상, 소문자 하나 이상을 포함하도록 요구합니다. 또한 관리자가 다른 사용자의 비밀번호를 설정할 때도 검사를 적용합니다.

minlen = 10
dcredit = -1
ucredit = -1
lcredit = -1
enforce_for_root

각 옵션의 의미는 다음과 같습니다.

  • minlen = 10: 비밀번호의 허용 가능한 최소 길이를 10자로 설정합니다.
  • dcredit = -1: 숫자를 하나 이상 포함하도록 요구합니다. 음수 값은 “최소 하나”를 의미합니다.
  • ucredit = -1: 대문자를 하나 이상 포함하도록 요구합니다.
  • lcredit = -1: 소문자를 하나 이상 포함하도록 요구합니다.
  • enforce_for_root: 관리자가 품질 검사를 통과하지 못한 비밀번호를 적용하지 못하도록 합니다. sudo adduser가 root 권한으로 새 사용자의 비밀번호를 설정하기 때문에 이 옵션이 필요합니다.

줄을 추가한 후 Ctrl+X, Y, Enter를 차례로 눌러 파일을 저장하고 nano를 종료합니다.

이제 비밀번호 만료 정책을 설정하겠습니다. 이 설정은 비밀번호의 최대 및 최소 사용 기간을 정의합니다. 새 사용자 계정에 적용되는 기본값은 /etc/login.defs에 저장됩니다.

grep으로 이 파일에서 관련 설정을 찾습니다.

grep -E 'PASS_MAX_DAYS|PASS_MIN_DAYS|PASS_WARN_AGE' /etc/login.defs

기본값이 표시됩니다. 일반적으로 PASS_MAX_DAYS가 매우 큰 값으로 설정되어 있어 비밀번호 만료가 사실상 비활성화되어 있을 수 있습니다.

##       PASS_MAX_DAYS   Maximum number of days a password may be used.
PASS_MAX_DAYS   99999
##       PASS_MIN_DAYS   Minimum number of days allowed between password changes.
PASS_MIN_DAYS   0
##       PASS_WARN_AGE   Number of days warning is given before a password expires.
PASS_WARN_AGE   7

이제 비밀번호 만료 기간을 9000일로 설정하겠습니다. sudo nano로 파일을 엽니다.

sudo nano /etc/login.defs

PASS_MAX_DAYS 줄을 찾아 값을 99999에서 9000으로 변경합니다. 사용자가 비밀번호를 너무 자주 변경하지 못하도록 PASS_MIN_DAYS7로 설정할 수도 있습니다.

##       PASS_MAX_DAYS   Maximum number of days a password may be used.
PASS_MAX_DAYS   9000
##       PASS_MIN_DAYS   Minimum number of days allowed between password changes.
PASS_MIN_DAYS   7
##       PASS_WARN_AGE   Number of days warning is given before a password expires.
PASS_WARN_AGE   14

파일을 저장하고 nano를 종료합니다. /etc/login.defs의 이 설정은 변경 후 생성되는 사용자에게 적용됩니다. 기존 사용자에게 정책을 적용하려면 chage 명령을 사용해야 합니다. 여기서는 labex 사용자에게 적용합니다.

먼저 labex 사용자의 현재 만료 정보를 확인합니다.

sudo chage -l labex

비밀번호가 만료되지 않도록 설정되어 있는 것을 확인할 수 있습니다.

Last password change                                    : Jul 22, 2023
Password expires                                        : never
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 99999
Number of days of warning before password expires       : 7

이제 chage-M 옵션을 사용하여 labex 사용자의 최대 사용 기간을 9000일로 설정합니다.

sudo chage -M 9000 labex

다시 사용자 만료 정보를 확인하여 변경 사항을 검증합니다.

sudo chage -l labex

이제 Password expires 날짜가 갱신되고 최대 사용 기간이 9000일로 설정된 것을 확인할 수 있습니다. 만료 정책이 성공적으로 적용되었습니다.

Last password change                                    : Jul 22, 2023
Password expires                                        : Jan 01, 2048
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 9000
Number of days of warning before password expires       : 7

이제 Linux 시스템에 비밀번호 복잡도 정책과 만료 정책을 모두 성공적으로 설정했습니다.

새 사용자 계정에 강력한 비밀번호 적용

이 단계에서는 이전 단계에서 설정한 비밀번호 복잡도 및 만료 정책이 새 사용자 계정에 적용되는지 확인합니다. 가장 좋은 테스트 방법은 새 사용자를 생성한 다음 규칙을 위반하는 비밀번호를 설정해 보는 것입니다. 이를 통해 pam_pwquality 모듈과 시스템 기본 설정이 함께 작동하여 계정 생성 시점부터 새 계정을 보호하는 방식을 확인할 수 있습니다.

Debian 기반 시스템에서 사용자를 생성할 때는 사용하기 편리한 대화형 스크립트인 adduser 명령을 사용합니다. testuser라는 새 사용자를 생성해 보겠습니다.

sudo adduser testuser

시스템에서 즉시 새 사용자의 비밀번호를 설정하라는 메시지가 표시됩니다. 이 단계에서 정책이 검증됩니다.

먼저 정책을 위반하는 간단하고 약한 비밀번호를 입력해 보겠습니다. 새 비밀번호를 입력하라는 메시지가 나타나면 password를 입력하고 Enter를 누릅니다.

Adding user `testuser' ...
Adding new group `testuser' (1001) ...
Adding new user `testuser' (1001) with home directory `/home/testuser' ...
Copying files from `/etc/skel' ...
New password:

password는 너무 짧고 대문자나 숫자를 포함하지 않으므로 규칙을 위반합니다. 따라서 시스템이 이를 거부합니다. 정확한 메시지는 다를 수 있지만 BAD PASSWORD로 시작하며, 다시 새 비밀번호를 입력하라는 메시지가 표시됩니다.

BAD PASSWORD: The password fails the dictionary check
New password:

비밀번호가 여러 규칙을 위반했지만, 시스템은 다시 입력을 요청하기 전에 거부 사유 중 하나를 표시합니다.

경고 메시지만 표시되는 경우에는 반드시 거부되는 것은 아닙니다. 명령이 다시 새 비밀번호를 입력하라고 요청해야 실제로 거부된 것입니다. 1단계에서 추가한 enforce_for_root 설정은 권한을 가진 adduser 프로세스가 약한 비밀번호를 허용하지 않도록 합니다.

팁: 실수로 사용자를 생성했다면 sudo deluser testuser를 사용하여 사용자를 삭제한 후 다시 시도할 수 있습니다.

이제 모든 조건을 만족하는 비밀번호를 입력합니다. 비밀번호 입력 메시지가 나타나면 N7vQ2mR9xK4p를 입력하고 Enter를 누릅니다. 확인을 위해 같은 비밀번호를 다시 입력하라는 메시지가 표시됩니다.

New password:
Retype new password:
passwd: password updated successfully

성공했습니다! 시스템이 강력한 비밀번호를 허용했습니다. 이제 사용자에 대한 추가 정보를 입력하라는 메시지가 표시됩니다. 각 항목에서 Enter를 눌러 기본값을 그대로 사용하면 됩니다.

Changing the user information for testuser
Enter the new value, or press ENTER for the default
        Full Name []:
        Room Number []:
        Work Phone []:
        Home Phone []:
        Other []:
Is the information correct? [Y/n] Y

이제 testuser 사용자가 생성되었습니다. id 명령을 사용하여 사용자가 존재하는지 확인할 수 있습니다.

id testuser

사용자 ID, 그룹 ID 및 소속 그룹이 표시됩니다.

uid=1001(testuser) gid=1001(testuser) groups=1001(testuser)

다음으로 /etc/login.defs에 설정한 비밀번호 만료 정책이 새 사용자에게 자동으로 적용되었는지 확인합니다. chage 명령으로 testuser의 만료 정보를 확인합니다.

sudo chage -l testuser

Maximum number of days between password change가 설정한 값인 9000으로 표시됩니다.

Last password change                                    : Jul 22, 2023
Password expires                                        : Jan 01, 2048
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change          : 7
Maximum number of days between password change          : 9000
Number of days of warning before password expires       : 14

마지막으로 시스템을 깔끔하게 유지하기 위해 테스트 사용자를 삭제합니다. deluser 명령으로 사용자 계정을 제거할 수 있습니다.

sudo deluser testuser

시스템에서 사용자가 제거되었다는 확인 메시지를 표시합니다.

Removing user `testuser' ...
Warning: group `testuser' has no more members.
Done.

새 사용자를 생성하고 비밀번호 정책 적용 여부를 테스트했으며, 기본 만료 규칙이 적용되었는지도 확인했습니다.

인증 로그에서 로그인 실패 시도 모니터링

이 단계에서는 무차별 대입 공격과 같은 잠재적인 보안 위협을 탐지하기 위해 시스템 인증 로그를 모니터링하는 방법을 익힙니다. 시스템 관리에서 중요한 업무 중 하나는 로그를 정기적으로 검토하여 의심스러운 활동을 파악하는 것입니다. 로그인 실패 시도는 무단 접근 시도를 나타내는 중요한 지표입니다. 여기서는 로그인 실패를 직접 발생시킨 다음 표준 Linux 명령으로 해당 로그 항목을 찾아 분석합니다.

Ubuntu와 같은 Debian 기반 시스템에서는 성공 및 실패를 포함한 인증 이벤트가 일반적으로 /var/log/auth.log 파일에 기록됩니다. 이 파일을 읽으려면 관리자 권한이 필요합니다.

먼저 로그인 실패를 하나 발생시켜 보겠습니다. su(사용자 전환) 명령으로 자신의 사용자 계정인 labex로 전환을 시도하되, 의도적으로 잘못된 비밀번호를 입력하면 안전하게 테스트할 수 있습니다.

su labex

시스템에서 비밀번호를 입력하라는 메시지가 표시됩니다. wrongpassword와 같이 잘못된 비밀번호를 입력하고 Enter를 누릅니다.

Password:
su: Authentication failure

실패 패턴을 만들기 위해 한 번 더 시도합니다.

su labex

다시 잘못된 비밀번호를 입력합니다. 이제 로그 데이터가 생성되었으므로 인증 로그 파일을 확인해 보겠습니다. 최신 이벤트가 기록되는 /var/log/auth.log의 마지막 몇 줄을 sudotail 명령으로 확인합니다.

sudo tail /var/log/auth.log

실패한 su 시도와 관련된 새 로그 줄이 여러 개 표시됩니다. 출력에는 타임스탬프, 프로세스(su), 실패 메시지가 다음과 비슷한 형태로 나타납니다.

Jul 22 16:45:01 labex-vm su[12345]: pam_unix(su:auth): authentication failure; logname=labex uid=1000 euid=0 tty=/dev/pts/0 ruser=labex rhost=  user=labex
Jul 22 16:45:01 labex-vm su[12345]: FAILED SU (to labex) labex on /dev/pts/0
Jul 22 16:45:15 labex-vm su[12346]: pam_unix(su:auth): authentication failure; logname=labex uid=1000 euid=0 tty=/dev/pts/0 ruser=labex rhost=  user=labex
Jul 22 16:45:15 labex-vm su[12346]: FAILED SU (to labex) labex on /dev/pts/0

로그를 직접 검색하면 시간이 오래 걸릴 수 있습니다. 더 효율적인 방법은 grep으로 특정 키워드가 포함된 줄만 필터링하는 것입니다. "authentication failure"가 포함된 모든 줄을 검색해 보겠습니다.

sudo grep "authentication failure" /var/log/auth.log

이 명령은 지정한 패턴과 일치하는 줄만 표시하므로 방금 생성한 로그인 실패 기록을 쉽게 확인할 수 있습니다.

이제 모니터링 과정을 자동화하는 간단한 셸 스크립트를 만들어 보겠습니다. 이 스크립트는 로그에서 실패 기록을 확인하고 요약 결과를 출력합니다. ~/project 디렉터리에서 nano를 사용해 log_monitor.sh라는 새 파일을 만듭니다.

nano log_monitor.sh

편집기에 다음 Bash 스크립트를 입력합니다. 이 스크립트는 grep-c 옵션으로 로그인 실패 횟수를 계산한 다음 상태 메시지를 출력합니다.

#!/bin/bash

LOG_FILE="/var/log/auth.log"
FAILURE_COUNT=$(sudo grep -c "authentication failure" $LOG_FILE)

echo "--- Authentication Log Monitor ---"
if [ "$FAILURE_COUNT" -gt 0 ]; then
  echo "WARNING: Found $FAILURE_COUNT failed login attempts."
else
  echo "OK: No failed login attempts found."
fi
echo "--------------------------------"

Ctrl+X, Y, Enter를 차례로 눌러 파일을 저장하고 nano를 종료합니다.

다음으로 chmod 명령을 사용하여 새 스크립트를 실행 가능하게 만듭니다.

chmod +x log_monitor.sh

마지막으로 모니터링 스크립트를 실행하여 결과를 확인합니다.

./log_monitor.sh

앞에서 로그인 실패를 발생시켰으므로 스크립트가 이를 탐지하고 정확한 횟수와 함께 경고 메시지를 표시합니다.

--- Authentication Log Monitor ---
WARNING: Found 2 failed login attempts.
--------------------------------

이제 인증 실패 시도를 시뮬레이션하고 탐지하는 방법과 기본적인 모니터링 스크립트를 작성하는 방법을 익혔습니다. 이는 시스템 보안을 유지하는 데 매우 중요한 기술입니다.

요약

이 실습에서는 강력한 로컬 비밀번호 정책을 설정하여 Linux 시스템의 보안을 강화하는 방법을 익혔습니다. /etc/security/pwquality.conf 파일을 수정하고 pam_pwquality 모듈을 사용하여 비밀번호 복잡도 규칙을 적용했습니다. 여기에는 최소 비밀번호 길이를 설정하고 숫자, 대문자, 소문자를 각각 하나 이상 포함하도록 요구하여 쉽게 추측할 수 있는 자격 증명으로부터 시스템을 보호하는 과정이 포함되었습니다.

또한 새 사용자 계정을 생성할 때 이러한 강력한 비밀번호 정책이 적용되도록 하는 방법을 살펴보았습니다. 아울러 반복적인 로그인 실패 시도와 같은 보안 이벤트를 탐지하고 분석하기 위해 시스템 인증 로그를 모니터링하는 핵심 기술도 익혔습니다. 이러한 활동은 잠재적인 공격을 나타낼 수 있습니다.