Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>

Contents

리눅스 사용자 계정 시스템

리눅스역시 다른 유닉스들과 마찬가지로 다중사용자(:12) 운영체제(:12)이다. 이렇다 보니 시스템 자원에 대한 접근권한이 매우 중요해 진다. 예를들어 특정 유저의 개인 신상정보를 가진 파일은 결코 다른 유저들이 볼 수 있어서는 안될 것이며 shutdown(1)과 같은 시스템 다운 명령은 특수한 유저(슈퍼유저)만이 제한적으로 실행가능 해야 할것이다. 아뭏든 네트워크장치, 파일, 프로세스, 장치(디스크, CD-ROM, 프린터등)의 모든 시스템 자원에 대해서 사용자 계정수준에서의 접근제어와 관련된 제한이 필요하게 될 것이다. 회사의 직책과 관련된 시스템과 동일하다고 보면 된다. 일반 사원인지, 대리인지, 과장인지, 사장인지에 따라서 접근할수 있는 회사자원의 레벨이 결정되는 것과 마찬가지다. 일반 공지사항이야 전직원이 볼 수 있지만 경영과 관련된 중요 문건은 최고경영진만 볼수 있어야 할것이다.

유저(User)

회사로 치원 사원 개개인이다. 리눅스 시스템 관점에서 보자면 시스템에 접근할 수 있는 최소단위 객체가 된다. 유저는 접근을 위해서 자신의 ID와 패스워드를 가지며, 이외에도 시스템에서의 원할한 활동을 위한 "사용자 홈디렉토리", "사용자 쉘", "포함되는 그룹"과 같은 각종 부가적인 정보들을 가지게 된다.

리눅스에서 유저는 크게 2개로 나누게 된다. 절대적인 권한을 가지는 슈퍼유저일반유저 유저다.

슈퍼유저는 보통 ID로 root를 가지며 시스템에서 절대적인 영향력을 행사한다. 시스템의 셧다운, 리부팅, 장치의 제어, 유저제어, 파일제어에 있어서 전혀 제한이 없다. 마음만 먹는다면 rm -rf /로 시스템의 모든 파일을 날려버릴 수도 있는 절대 권한자이다.

일반 유저는 슈퍼유저를 제외한 나머지 유저를 가리킨다. 일반유저는 슈퍼유저가 정하는 바에 따라서 시스템내에서의 권한과 활동영역에 있어서 제한을 받게 된다.

그룹

회사에서는 인적자원의 효율성을 높이기 위해서 개인별로 직책과 직급을 두고 이를 다시 묶어서 부서(팀)를 만들어서 관리한다. 기술개발팀, 경영지원팀, 회계팀, 인사팀등인데, 한명의 직원은 하나 혹은 그 이상의 팀에 소속될 수 있을 것이고 팀의 특징에 따라서 권한이 재조정 될것이다.

회사와 같이 부서(팀)을 만들어서 조직을 효율적으로 만드는것과 같은 구조는 다른 모든 집단에서 (이름만 약간 바꾸어서) 공통적으로 나타나며 운영체제역시 예외없이 이러한 구조를 따른다.

리눅스에서는 이를 그룹이라고 한다. 리눅스에서의 그룹역시 유저자원을 효율적으로 관리하기 위한 장치다. 하나의 유저는 하나이상의 그룹에 포함될 수 있다.

권한

유저와 그룹은 고유의 권한이 있으며, 이러한 권한은 주로 파일에 적용된다. 즉 파일일 읽을수 있는지(r), 쓸수 있는지(w), 실행할 수 있는지(x)에 대해 적의 하는 것으로 이루어진다. 리눅스에서 모든 것은 파일로 다루어지므로 파일에 대해서 권한을 설정한다는 것은 결국 시스템 전체에 대한 권한을 설정하는 것과 동일한 효과를 가진다.

리눅스는 각각의 파일에 대해서 r, w, x 권한을 유저,그룹,다른유저(other)에 대해서 명시하는 것으로 권한을 제어한다. 권한에 대한 자세한 내용은 유닉스파일을 참고하도록 하자.

유저 정보 얻어오기

사원과 팀의 정보를 유지하기 위해서 인사카드가 있는 것처럼 리눅스 역시 이러한 정보를 관리하기 위한 파일을 유지한다. 이번장에서는 이러한 유저정보관련 파일과 이를 제어하는 방법에 대해서 알아보도록 하겠다.

passwd 파일분석을 이용한 기본유저 정보

User 의 정보는 /etc/passwd 파일에 존재하므로, 우선은 passwd 파일에 사용자의 정보가 어떻게 저장되는 지를 알아보도록 하겠다. 다음은 passwd 파일의 내용중 일부 내용이다
yundream:x:500:500::/home/yundream:/bin/bash
passwd 파일은 하나의 행에 하나의 유저 정보를 가지고 있으며, 7개의 정보를 가지고 있다. 각 정보는 ":" 를 통해 구분된다. 각 필드가 가지고 있는 정보는 다음과 같다.
계정:패스워드:UID:GID:GECOS:디렉토리:쉘
  1. 계정은 시스템내에서 사용되는 사용자의 이름으로 영문소문자의 조합으로 이루어 진다.
  2. "패스워드는 사용자가 로그인시 사용되는 비밀번호이다.
  3. ID는 유저ID 로 숫자로 구성되어 있으며, 해당시스템내에서 유일한 값을 가진다. 일반적인 시스템 프로그램은 UID 를 통하여서 유저를 구분한다.
  4. GID는 사용자가 포함된 그룹이며 UID 와 마찬가지로 숫자로 표기된다. LInux 상에서는 계정이 생성되면 자신의 그룹이 만들어지며, 해당 그룹에 포함되게 된다. Solaris 상에서 계정이 생성되면 "other" 그룹에 포함되게 된다. 각 계정에 대한 그룹 정책은 OS에 따라서 약간식 다르게 책정되어 지는데 보통 그룹에 대한 정보는 /etc/group 에 저장된다.
  5. GECOS 에는 유저에 대한 기타정보가 저장되며, 이 필드는 채울수도 있고, 그렇지 않고 비워둘수도 있다.
  6. 디렉토리는 사용자가 사용하는 홈디렉토리인데 쉘상에서 echo 를 통해서 자신의 홈디렉토리를 알아볼수 있다.
  7. 은 사용자가 로그인해서 사용하는 shell 의 종류이다. Unix 는 Windows 와는 달리 다양한 종류의 쉘이 존재하는데, 사용자는 그중 원하는 쉘을 선택해서 사용할수 있다. 보통 bash(배쉬쉘), csh(씨쉘) 을 많이 사용한다.
위의 passwd 파일의 내용에는 yundream 계정사용자는 UID 번호가 500 이고, GID 는 500 이며, 홈디렉토리는 /home/yundream 이고 bash 쉘을 사용한다" 라는 정보를 포함하고 있다.

Shadow Password을 이용한 유저 패스워드

그런데 위의 정보를 보면 두번째 패스워드 필드가 "x" 로 채워져 있는것을 볼수 있다. 이는 사용자의 패스워드 정보를 "다른파일" 에 저장해 두었다는것을 나타낸다.

/etc/passwd 파일을 보면 그 권한이 "644" 로 누구든지 읽기 가능하도록 되어 있다는 것을 알수 있다. 이는 누구든지 해당 계정 사용자의 패스워드 를 가져올수 있다라는 의미가 된다. 비록 패스워드가 "암호화" 되어있기는 하지만, 일단 패스워드 파일을 얻어낼수 있다면, 이를 이용해서 사용자의 패스워드를 크랙하는 방법이 가능해 진다.

해서 사용자의 패스워드 정보를 오직 root 권한자만이 읽을수 있는 파일에 저장하도록 해서 패스워드 정보의 보안을 높이는 방법을 채택했는데, 이를 shadow 패스워드라고 하며 /etc/shadow 에 저장된다. shadow 파일의 권한을 보면 아래와 같다.
rw-------    1 root     root         1019 12월 30 01:32 /etc/shadow
오직 "root" 권한자만이 읽고 쓸수 있도록되어 있음을 알수 있다. shadow 패스워드의 내용은 다음과 같다.
yundream:$1$pT/VnlSK$PApp4lLLblRLoZVfsd3XX1:11657:0:99999:7:::
cvs:$1$3UzIhJPn$qClbSInt/C1X45X1j7SKK1:11545:0:99999:7:::
passwd 파일과 마찬가지로 ":" 를 통해서 각 필드를 구분하며, 눈치 챘겠지만 2번째 필드에 있는 내용이 암호화된 패스워드 문자열 이다. shadow 에는 패스워드 갱신일, 패스워드의 유효기간 등의 정보가 추가로 들어있다. 각필드에 대한 자세한 내용은 shadow(5) 를 참고 하기 바란다.

최신의 Unix 는 대부분 shadow 패스워드를 지원하고 있다. 보통 패스워드는 crypt(3) 함수를 통해서 만들어 지는데, 리눅스의 경우 더복잡한 패스워드를 만들기 위해서 crypt 후 MD5 암호화 까지 적용 한다. Solaris 와 같은 많은 Unix 운영체제는 여전히 crypt 만 적용하기도 한다.

유저 정보 얻기 프로그래밍

passwd 나 shadow 파일에서 유저 정보를 가져오기 위해서 파일을 직접열어서 각 행을 읽어들이고, ":" 를 기준으로 해서 각 필드를 구분해서 유저정보를 가져오는 방법도 있겠지만, 보통은 C 에서 제공하는 함수들을 많이 사용한다.

  • passwd 정보 : getpwent(3), setpwent(3), endpwent(3)
  • shadow 정보 : getspent(3), getspnam(3), setspent(3), endspent(3)
예제 : 패스워드 검사 프로그램
/* 이예제는 사용자 아이디와 패스워드가 올바른지를 
   검사하는 프로그램이다.
   프로그램 아규먼트로 아이디와 패스워드를 입력하면, 
   입력한 아이디 값을 이용해서 /etc/shadow  파일을 검색하여 패스워드 
   파일을 가져오고, 입력한 패스워드와 일치하는 지를 검사한다. 
   암호화된 패스워드와의 비교를 위해서 crypt(3) 함수를 사용했다.
*/
#include <shadow.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    struct spwd *myspwd;
    char *user_name;
    char *user_pass;

    if (argc !=3)
    {
        printf("Usage : ./shadow [id] [passwd]\n");
        exit(0);
    }

    user_name = argv[1];
    user_pass = argv[2];

    myspwd = getspnam(user_name);
    if (myspwd == NULL) 
    {
        printf("cannot found user\n");
        exit(0);
    }

    if (strcmp(myspwd->sp_pwdp, (char *)crypt(user_pass, myspwd->sp_pwdp)) == 0)
        printf("Ok Passwd!!\n");
    else
        printf("Not Passwd!!\n");
}
위의 코드를 약간만 응용하면 소위 말하는 사전공격 을 수행하는 패스워드 크랙 프로그램을 만들수 있다. 자주 사용할만한 단어를 미리 파일등에 입력해 놓고, 그 파일을 crypt(3) 에 대입해서 암호화된 패스워드 파일과 일치하는지 loop 를 돌면서 계속 검사하도록 루틴을 수정하면 된다. 물론 사전데이타는 어떻게 해서든지 얻어와야 한다.

shadow 패스워드 방식을 사용한다면, 패스워드파일이 누출될 가능성이 줄어들긴 하겠지만, 이왕이면 사전공격에 걸리지 않는 패스워드를 사용하는게 바람직 할것이다.