[여기보기] 알리바바가 외친 “열려라 참깨”에는 열리지 않는 문

🧐 | 2022-07-19

[여기보기]는 “여기서 보안의 기본을 챙기고 가자”의 약자로, 개발 과정에서 꼭 최소한으로 챙기면 좋은 보안 기초 설정을 앞으로 하나씩 공유할 예정입니다. 기초 내용이 주를 이루겠지만, 혹시라도 빼먹고 계신 것이 없는지 가끔 한 번씩 둘러봐 주세요.

리눅스 서버의 계정과 패스워드 설정

안녕하세요, 넷마블 보안실 보안개발팀 이대성입니다.

아라비안나이트에 나오는 ‘알리바바와 40인의 도둑’ 이야기를 잠시 떠올려보겠습니다. 도둑이 멀리서 외치는 암호가 알리바바에게 유출됐고, 유출된 암호였던 “열려라 참깨”는 계속 재사용됐습니다. 길이조차도 그리 길지 않아서 기억하기 좋았습니다. (알리바바의 형은 왜 그걸 동굴 안에서 까먹은 걸까요?)

여기서 몇 가지 가설을 추가해보겠습니다. 만약, 40인의 도둑이 각자 다른 입구와 다른 암호를 쓰고 있었다면 어땠을까요? 암호가 주기적으로 바뀌었다면 어땠을까요? 암호가 쉽게 기억할 수 없는 매우 긴 문장이었다면 어땠을까요? 들어갈 수 있는 사람과 암호 둘 다 철저하게 관리하고 출입 대장을 기록하고 있었다면, 알리바바는 동굴에 들어갈 수 없었을지도 모릅니다. 설령 들어갔다고 하더라도, 빨리 추적 당했을 수도 있습니다. 계정과 패스워드를 분리 관리하고 최소 관리 요소를 챙겨야 하는 이유입니다.

[여기보기] 두 번째 콘텐츠, 리눅스 서버 보안을 위한 계정과 패스워드 설정에 대한 내용을 시작합니다.

계정

계정 설정에서 기본 방향성은 “더 이상 쓰지 않는 계정을 정리하고, 불필요한 권한을 제거하라”입니다. 답이 정해져 있지 않으므로 정책을 설정할 때 방향성을 잘 잡으셔야 합니다.

불필요한 계정은 제거하라

개발 과정에서 사용자가 직접 생성한 계정 중, 더 이상 쓰지 않는 계정을 정리하는 것은 딱히 다른 설명이 필요 없으리라 생각합니다. 사용하지 않는 계정 이외에 리눅스에서는 OS나 패키지를 설치할 때 기본으로 생성되는 계정이 있습니다. 대표적으로 ‘lp’, ‘uucp’, ‘nuucp’ 등이 있습니다. 동일한 설치 조건에서는 늘 같은 계정 이름으로 생성됩니다.

  • 리눅스에서는 OS나 패키지를 설치할 때 기본으로 생성되는 계정 예시:
    adm, ip, sync, shutdown, halt, news, uucp, operator, games, gopher, nfsnobody, squid 등

이들은 시스템이나 패키지 실행을 위해 각자 독립적인 역할을 맡고 있습니다. 하지만, 실제 서버 운영 목적으로는 쓰지 않는 기능을 맡고 있을 수도 있습니다. 그래서 사전 대입 공격 등의 타깃이 되기 쉬운 계정입니다. 그래서 업무 영향도를 살펴보고, 영향이 없다면 삭제해두시기를 추천합니다.

조치 방안

직접 찾아서 삭제하기

불필요한 계정을 찾는 가장 간단한 방법은 ‘/etc’ 디렉터리의 ‘passwd’ 파일을 직접 열어 눈으로 확인하고 삭제하기입니다.

$ cat /etc/passwd

$ cat /etc/passwd | egrep “****|****|****|****”

$ userdel <user_name>

로그로 계정 영향도 파악하기

계정별로 최근 로그인 여부나 의심스러운 활동 여부는 로그를 조회하면 알 수 있습니다. 이때 로그는 직접 로그인 접속과 ‘su’ 명령어를 활용한 사용자 전환 접속을 구분해서 확인해야 합니다.

직접 로그인한 내역은 ‘/var/log’ 디렉터리에 있는 ‘wtmp’ 파일 또는 ‘last’ 명령어로 볼 수 있습니다.

$ cat /var/log/wtmp
$ strings /var/log/wtmp
$ last

‘su’ 명령어를 활용한 사용자 전환 접속은 ‘/var/log’ 디렉터리에 있는 ‘sulog’ 파일에서 로그를 확인할 수 있습니다.

$ cat /var/log/sulog

단, 리눅스 설치 환경에 따라서 ‘sulog’ 파일에 로그가 자동으로 쌓이지 않는 경우도 있습니다. 그럴 땐 ‘/etc’ 디렉터리에 있는 ‘login.defs’ 파일과 ‘rsyslog.conf’ 파일에서 설정을 수정하고, ‘rsyslog’를 재시작해야 합니다.

// 설정 항목 앞에 있는 주석을 제거하거나 추가 입력해야 합니다. 
$ vi /etc/login.defs
SULOG_FILE	/var/log/sulog

$ vi /etc/rsyslog.conf 
authpriv.info	/var/log/sulog

‘/etc/passwd’ 파일은 각 줄 앞에 ‘#’을 삽입해도 주석처리가 되지 않습니다. 계정을 삭제하려는 경우에는 반드시 주석처리가 아니라, 삭제해야 합니다.

모든 계정은 각자 다른 UID를 사용하라

UID(User Identification)는 여러 사용자가 동시에 사용하는 시스템에서 각 사용자를 식별하는 번호입니다. (예시로 ‘root’ 계정은 UID가 ‘0’ 입니다.) 식별자로 쓰기 때문에 서로 다른 계정끼리 이름이 다르더라도 UID가 같다면, 리눅스에서는 같은 사용자로 인식합니다. 접근할 수 없는 디렉터리와 실행할 수 없는 명령어 등의 접근 제어가 무너질 수밖에 없습니다. 또한, 사용자 감사 추적을 할 때도 UID가 같다 보니 어려움을 겪을 수밖에 없습니다.

그래서 파일과 디렉터리 접근 예방과 침해사고 감사추적을 위해서는 모든 계정은 서로 다른 UID를 사용해야 합니다.

조치 방안

같은 UID를 사용하는 계정이 있다면, ‘usermod’ 명령어로 UID를 수정하면 됩니다.

$ usermod -u <변경할 UID> <user_name>

로그인 실패 임곗값을 설정하라

패스워드를 잘못 입력했거나, 인증키 설정을 잘못해서 한 번에 로그인하지 못했던 경험이 다들 있으실까요? 혹시나 잘 기억나지 않아서 3~4번까지 바꿔가며 로그인하신 분들도 계시지 않나요? 무작위 대입 공격, 사전 대입 공격, 추측 공격 등도 이와 비슷한 패턴으로 계속 로그인을 시도합니다. 단, 우리는 우리의 답을 알고 있지만 공격자는 답을 모르기 때문에 무한 반복하며 패스워드를 찾습니다.

이럴 때 로그인을 계속 시도하도록 방치할 것이 아니라, 최소 방어막이 될 수 있도록 로그인 자체를 차단할 시스템 정책이 있어야 합니다. 차단 방법 중 하나가 로그인 실패 임곗값 설정입니다. 로그인 실패 임곗값을 설정하면, 시스템에 로그인할 때 발생하는 실패 횟수가 지정한 횟수를 초과할 때 로그인 자체를 차단합니다. 몇 회까지 허용하고, 몇 회부터 막을지는 각자 내부 정책에 맞춰 정하시면 됩니다.

조치 방안

이번 예시에서는 로그인 실패 임곗값을 ‘5’라고 가정하겠습니다. 레드햇 계열과 데비안 계열 설정 파일명이 서로 다르므로, 각자 환경과 정책에 맞춰서 옵션을 수정하거나 추가하시면 됩니다. 주로 사용하는 옵션은 아래와 같습니다.

  • no_magic_root: root 계정은 로그인 잠금 설정을 적용하지 않음.
  • deny=5: 입력 실패 5회 발생 시 로그인을 잠금.
  • unlock_time=120: 로그인 실패로 잠금 처리된 시각부터 120초가 지나면 자동으로 로그인 잠금 해제(단위: 초).
  • reset: 접속 시도 성공 시 실패한 횟수 초기화.

레드햇 계열

레드햇 계열에서는 ‘/etc/pam.d’ 디렉터리에 있는 ‘system-auth’ 파일을 수정해야 합니다.

$ vi /etc/pam.d/system-auth

auth required /lib/security/pam_tally.so deny=5 unlock_time=120 no_magin_root
account required /lib/security/pam_tally.so no_magic_root reset

데비안 계열

데비안 계열에서는 설정값을 적용하려면 ‘/lib/x86_64-linux-gnu/security’ 디렉터리에 ‘pam_tally2.so’ 파일이 있는지 확인 후, 꼭 파일 최상단에 설정값을 넣어야 합니다. 수정할 파일은 ‘/etc/pam.d’ 디렉터리에 있는 ‘common-auth’ 파일과 ‘common-account’ 파일입니다.

$ vi /etc/pam.d/common-auth

auth required pam_tally2.so deny=5 unlock_time=120

$ vi /etc/pam.d/common-account

account required /lib/security/pam_tally2.so

셸로 접근할 계정을 선별하라

셸(Shell)은 사용자가 입력하는 명령어를 OS가 이해하고 실행할 수 있게 연결해주는 사용자 인터페이스입니다. 그래서 OS 설치 시 기본으로 생성되는 계정이 셸로 접근할 수 있는 권한을 가지고 있다면, 공격자에게 좋은 먹잇감이 됩니다. 어떤 공격인지는 위에서 계속 설명했었으니 넘어가겠습니다.

조치 방안

서비스나 시스템 운영상으론 필요하지만, 셸 접근이나 로그인 자체는 불필요한 계정이라면 계정 설정에서 ‘/bin/false’나 ‘/sbin/nologin’으로 셸 접근 권한을 막아 시스템 명령어를 실행할 수 없도록 막아두는 것이 좋습니다.

계정 선별

<일반적으로 셸 접근이 불필요한 계정>

  • daemon, bin, sys, adm, listen, nobody, nobody4, noaccess, diag, operator, games, gopher 등
  • 일반적으로 UID가 100 이하이거나, 60000 이상인 시스템 계정
$ cat /etc/passwd | egrep "^daemon|^bin|^sys|^adm|^listen|^nobody|^nobody4|^noaccess|^diag|^operator|^games|^gopher" | grep -v "admin"

위에 나열한 예시 계정을 참고해 접근을 막을 계정을 찾는 방법도 있습니다만, 접근을 허용할 계정만 열어두고 나머지는 다 막는 것도 좋은 방법일 수 있습니다.

셸 접근 차단 설정

셸 접근을 막는 옵션은 ‘/bin/false’나 ‘/sbin/nologin’이 있습니다.

  • /bin/false:
    로그인을 허용하지 않으며, 로그인 실패 메시지도 보여주지 않습니다.
  • /sbin/nologin:
    로그인을 허용하지 않습니다. “This account is currently not available” 메시지로 답을 주며, 답변 텍스트는 수정할 수 있습니다.

셸 접근 차단 옵션은 ‘/etc’ 디렉터리에 있는 passwd 파일에서 계정 정보 맨 마지막에 입력하면 됩니다.

// 수정 전
root:x:0:0:root:/root:/bin/bash

// 수정 후
root:x:0:0:root:/root:/bin/false
또는
root:x:0:0:root:/root:/sbin/nologin

패스워드

계정을 집 주소에 비유한다면, 패스워드는 그 집 자물쇠와 열쇠입니다. 집 주소가 노출되더라도 그 집 자물쇠와 열쇠를 잘 관리할 수 있다면, 함부로 집에 불청객이 들어올 수 없습니다.

패스워드 관리 방안은 갑론을박이 항상 일어나는 만큼, 답이 정해져 있지도 않습니다. 각자에게 도움 되는 방향으로 정책을 설정하시길 추천합니다.

패스워드 복잡성

패스워드 복잡성은 무작위 대입 공격이나 사전 대입 공격으로부터 직접적으로 방어 계책을 높이는 방법중 하나입니다. 패스워드 설정 시 대문자, 소문자, 숫자, 특수문자를 혼합하고 최소 글자 수를 제한하면 패스워드 복잡성이 오를 수밖에 없습니다. 그래서 공공기관 등에는 국가정보보안기본지침에 따라 패스워드를 9자 이상으로 설정해둬야 하는 기본 제한 조건이 있기도 합니다.

조치 방안

리눅스 계열과 버전에 따라 다르지만, 주로 ‘/etc/security’ 디렉터리에 있는 ‘pwquality.conf’ 파일에서 패스워드 복잡성을 설정할 수 있습니다. 만약 해당 파일이 보이지 않는다면, ‘pam pwquality’ 모듈을 설치하시면 됩니다.

//레드햇 계열
$ yum install libpwquality

//데비안 계열
$ apt-get install libpam-pwquality

‘pwquality.conf’ 파일에서 설정할 수 있는 패스워드 복잡성 관련 옵션은 아래와 같습니다.

  • minlen: 패스워드 최소 글자 수, 6자 미만은 불가.
  • dcredit: 최소로 포함해야 하는 숫자 개수, ‘-1’ 입력 시 반드시 1개 이상 포함해야 함.
  • ucredit: 최소로 포함해야 하는 대문자 개수, ‘-1’ 입력 시 반드시 1개 이상 포함해야 함.
  • lcredit: 최소로 포함해야 하는 소문자 개수, ‘-1’ 입력 시 반드시 1개 이상 포함해야 함.
  • ocredit: 최소로 포함해야 하는 특수문자 개수, ‘-1’ 입력 시 반드시 1개 이상 포함해야 함.
  • minclass: 최소로 조합해야 하는 글자 종류.

위 옵션 이외에도 ‘retry’나 ‘difok’ 같은 다른 옵션도 ‘pwquality.conf’ 파일안에 있으므로, 필요에 맞춰서 설정하시면 됩니다.

패스워드 유지기간

패스워드 최대 사용기간 설정이 필요한 이유는 따로 설명하지 않아도 다들 아시리라 생가합니다. 한번 설정한 패스워드를 최대로 유지할 수 있는 기간을 설정함과 동시에 최소로 유지해야 하는 기간도 함께 설정해야 한다는 특징도 꼭 같이 봐주셨으면 좋겠습니다.

패스워드 변경 후 최소 사용기간이 설정되지 않은 경우, 사용자에게 익숙한 패스워드로 즉시 변경할 수 있습니다. 즉, 원래 사용했던 암호를 같은 날 다시 사용할 수 있다는 의미입니다. 이는 패스워드 변경 정책이 무의미해질 수 있으므로, 조직 계정 보안성을 낮춥니다.

물론, 패스워드 복잡성을 설정하는 ‘pwquality.conf’ 파일에서 기존에 사용했던 패스워드를 다시 사용하는 것을 방지하는 ‘difok’ 옵션이 있습니다. 하지만 이 역시 패스워드 최소 유지기간 조건이 없다면 설정한 횟수만큼 바로 변경할 수 있으므로, ‘difok’ 옵션 설정만으로는 한계가 있다고 볼 수 있습니다.

조치 방안

패스워드 유지기간 설정은 ‘/etc’ 디렉터리에 있는 ‘login.defs’ 파일에서 수정할 수 있습니다.

# 패스워드 설정일로부터 60일까지 사용 가능
PASS_MAX_DAYS	60

# 최소 1일 경과 후 패스워드 변경 가능
PASS_MIN_DAYS	1

# 7일이 남은 시점부터 패스워드 변경 알림
PASS_WARN_AGE	7

쉽게 안 열리는 동굴

위에서 소개한 설정 외에도 계정과 패스워드를 보호할 수 있다면, 더 많은 방어 계책을 적용해두는 것이 좋습니다. 리눅스 서버가 스스로를 방어할 수 있도록 최소한의 조치를 소개해 드린 것으로 알아주셨으면 합니다. 단, 몇몇 설정을 변경하면 웹, WAS, DB 연동 구간에서 문제가 발생할 수도 있으므로 연동구간에 미칠 영향을 잘 살펴 가며 적용하셔야 합니다.

이제 알리바바가 멀리서 지켜보고 따라 외친 한마디 “열려라, 참깨!”에는 더 이상 동굴이 쉽게 열리지 않았으면 좋겠습니다.