파일 · 권한 · 사용자 관리 07 / 50 · Part 1. Linux 파일 관리 기초
실습 환경: Rocky Linux 9.8 · Ubuntu 24.04.5 (Docker 격리 컨테이너, 테스트 계정analyst)
기초편 연계: 「리눅스 시스템 기초」 11. Linux 파일과 디렉터리 관리
mkdir은 디렉터리를 만든다. 여기까지는 누구나 안다. 그런데 새 디렉터리의 권한은 누가 정하는가? 라는 질문에는 답이 바로 나오지 않는다.
이번 글에서는 같은 mkdir normal 명령이 Rocky Linux 9.8에서는 755, Ubuntu 24.04에서는 775를 만드는 실제 결과를 보여 주고, 그 차이가 umask 에서 나온다는 것을 설명한다. umask 자체는 25편에서 깊게 다루고, 이번 글은 mkdir이 권한을 결정하는 흐름에 집중한다.
| 옵션 | 의미 | 사용 예 |
|---|---|---|
| (없음) | 디렉터리 1개 생성, 상위가 없으면 실패 | mkdir logs |
-p | 필요한 상위 디렉터리까지 생성, 이미 있어도 오류 없음 | mkdir -p a/b/c |
-v | 생성한 디렉터리마다 메시지 출력 | mkdir -pv a/b/c |
-m MODE | 권한을 직접 지정 (umask 무시) | mkdir -m 700 private |
최종 권한 = 요청 모드(mkdir 은 0777) AND NOT umask
0022 → 0777 - 0022 = 07550002 → 07750077 → 0700(엄밀히는 뺄셈이 아니라 비트 AND NOT 연산이다. 25편에서 차이를 설명한다.)
mkdir -m 700은 umask와 관계없이 지정한 권한을 만든다. GNU mkdir은 -m이 주어지면 umask 적용 결과가 아니라 지정한 모드가 최종 권한이 되도록 처리한다. 단, -p로 함께 만들어지는 상위 디렉터리 에는 -m이 적용되지 않고 umask 기준 권한이 적용된다.

mkdir 명령은 내부적으로 mkdir("normal", 0777) 시스템 콜을 호출한다. 커널은 이 요청 모드에서 프로세스의 umask에 해당하는 비트를 지운 값 으로 inode를 만든다. 그리고 새 디렉터리의 소유자는 요청한 프로세스의 UID, 그룹은 기본적으로 프로세스의 GID 가 된다 (상위 디렉터리에 SGID가 있으면 예외, 29편).
동시에 커널은 다음 작업을 함께 수행한다.
.(자기 자신)과 ..(상위) 엔트리 생성w·x 권한 필요..이 상위를 가리키므로)Rocky와 Ubuntu의 umask 차이는 다음에서 나온다.
| 배포판 | umask | 근거 |
|---|---|---|
| Rocky 9.8 | 0022 | /etc/pam.d/postlogin의 pam_umask → /etc/login.defs의 UMASK 022 적용 |
| Ubuntu 24.04 | 0002 | /etc/pam.d/common-session의 pam_umask + USERGROUPS_ENAB yes — 사용자 이름과 기본 그룹 이름이 같으면 그룹 비트를 소유자와 같게 맞춰 022 → 002 |
이 값은 이번 실습 컨테이너에서
su -로그인 세션으로 확인한 결과다. 서버의/etc/profile,/etc/bashrc,~/.bashrc설정에 따라 달라질 수 있으므로 항상umask로 직접 확인한다.
Rocky와 Ubuntu에서 같은 명령 을 실행했다.
mkdir ~/lab07 && cd ~/lab07
# 1) 상위 디렉터리가 없으면 실패 / -p 로 한 번에 생성
mkdir a/b/c
mkdir -pv a/b/c
# 2) umask 와 기본 권한
umask
mkdir normal
mkdir -m 700 private
ls -ld normal private
# 3) 하위 디렉터리가 생길 때 상위 링크 수 변화
ls -ld a && mkdir a/x a/y && ls -ld a
# 4) 8진수로 확인
stat -c '%a %A %n' normal private a
Rocky Linux 9.8

Ubuntu 24.04.5

텍스트 원본(실제 출력) — Rocky:
[analyst@rocky9-lab ~]$ mkdir ~/lab07 && cd ~/lab07
[analyst@rocky9-lab lab07]$ mkdir a/b/c
mkdir: cannot create directory ‘a/b/c’: No such file or directory
[analyst@rocky9-lab lab07]$ mkdir -pv a/b/c
mkdir: created directory 'a'
mkdir: created directory 'a/b'
mkdir: created directory 'a/b/c'
[analyst@rocky9-lab lab07]$ umask
0022
[analyst@rocky9-lab lab07]$ mkdir normal
[analyst@rocky9-lab lab07]$ mkdir -m 700 private
[analyst@rocky9-lab lab07]$ ls -ld normal private
drwxr-xr-x 2 analyst analyst 4096 Sep 24 10:15 normal
drwx------ 2 analyst analyst 4096 Sep 24 10:15 private
[analyst@rocky9-lab lab07]$ ls -ld a && mkdir a/x a/y && ls -ld a
drwxr-xr-x 3 analyst analyst 4096 Sep 24 10:15 a
drwxr-xr-x 5 analyst analyst 4096 Sep 24 10:15 a
[analyst@rocky9-lab lab07]$ stat -c '%a %A %n' normal private a
755 drwxr-xr-x normal
700 drwx------ private
755 drwxr-xr-x a
텍스트 원본(실제 출력) — Ubuntu:
analyst@ubuntu-lab:~$ mkdir ~/lab07 && cd ~/lab07
analyst@ubuntu-lab:~/lab07$ mkdir a/b/c
mkdir: cannot create directory ‘a/b/c’: No such file or directory
analyst@ubuntu-lab:~/lab07$ mkdir -pv a/b/c
mkdir: created directory 'a'
mkdir: created directory 'a/b'
mkdir: created directory 'a/b/c'
analyst@ubuntu-lab:~/lab07$ umask
0002
analyst@ubuntu-lab:~/lab07$ mkdir normal
analyst@ubuntu-lab:~/lab07$ mkdir -m 700 private
analyst@ubuntu-lab:~/lab07$ ls -ld normal private
drwxrwxr-x 2 analyst analyst 4096 Sep 24 10:15 normal
drwx------ 2 analyst analyst 4096 Sep 24 10:15 private
analyst@ubuntu-lab:~/lab07$ ls -ld a && mkdir a/x a/y && ls -ld a
drwxrwxr-x 3 analyst analyst 4096 Sep 24 10:15 a
drwxrwxr-x 5 analyst analyst 4096 Sep 24 10:15 a
analyst@ubuntu-lab:~/lab07$ stat -c '%a %A %n' normal private a
775 drwxrwxr-x normal
700 drwx------ private
775 drwxrwxr-x a
| 출력 | 해석 |
|---|---|
mkdir: cannot create directory 'a/b/c': No such file or directory | 상위 a/b가 없어서 실패. mkdir은 기본적으로 한 단계만 만든다 |
mkdir -pv 의 3줄 메시지 | a → a/b → a/b/c 순서로 생성 |
Rocky umask 0022 → normal = 755 | 그룹·기타의 w 비트 제거 |
Ubuntu umask 0002 → normal = 775 | 기타의 w만 제거. 그룹(= 사용자 전용 그룹 analyst)에 쓰기 허용 |
private = 700 (양쪽 동일) | -m은 umask 영향을 받지 않는다 |
a 링크 수 3 → 5 | a/b가 있어 3, a/x, a/y 추가로 5. 2 + 하위 디렉터리 수 와 일치 |
Ubuntu의 775는 위험해 보이지만, 그룹이 사용자 전용 그룹(User Private Group) 이라 그룹 구성원이 사실상 본인뿐이다. 문제는 이 사용자를 다른 사용자와 같은 그룹에 넣거나, 공유 그룹이 기본 그룹으로 설정된 경우다. 이때는 775가 다른 사용자의 쓰기 허용 이 된다 (39편).
| 위험 | 설명 | 대응 |
|---|---|---|
| 예측 가능한 임시 디렉터리 | 스크립트가 /tmp/backup을 mkdir하기 전에 공격자가 먼저 만들어 두면, 이후 파일이 공격자 소유 디렉터리 에 저장된다 | mktemp -d로 임의 이름 생성 |
mkdir -p 오류 무시 | -p는 이미 존재해도 성공한다 → 기존 디렉터리의 소유자·권한을 검증하지 않음 | 생성 후 stat으로 소유자·권한 확인 |
| 서비스 디렉터리 권한 과다 | 업로드·캐시 디렉터리를 777로 생성 | 서비스 계정 소유 + 750/770 |
| umask 차이 무시 | 같은 배포 스크립트가 Ubuntu에서 그룹 쓰기 가능한 디렉터리를 만듦 | 스크립트에서 -m 또는 install -d -m 명시 |
install -d -m 750 -o app -g app /srv/app/data처럼 install 명령을 쓰면 생성·소유자·권한 지정을 한 번에 처리할 수 있어 배포 스크립트에서 자주 사용한다.
| 관점 | 내용 |
|---|---|
| Detection | 디렉터리 생성은 기본 로그에 남지 않는다. auditd로 mkdir, mkdirat 시스템 콜을 감시하거나 FIM으로 특정 경로를 감시해야 한다 |
| IOC | 위협 보고서에 자주 나오는 디렉터리명: /tmp/.X11-unix/.x, /var/tmp/.ICE-unix/..., /dev/shm/.cache 처럼 정상 이름을 흉내 낸 숨김 디렉터리 |
| Evidence | 새 디렉터리가 생기면 상위 디렉터리의 mtime·ctime 이 바뀐다. 상위 디렉터리 타임스탬프가 사고 시간대와 일치하는지 확인한다 |
| Investigation | 디렉터리 소유자 = 생성한 프로세스의 계정이다. /tmp의 수상한 디렉터리 소유자가 apache라면 웹 서버 경유 침입을 의심한다 |
[Detection] FIM: /var/tmp/.ICE-unix/.. (공백 포함 디렉터리) 신규 생성, owner=apache
↓
[판단] 정상 서비스가 만들 이유 없는 위장 이름 + 웹 서버 계정 소유
↓
[Evidence] stat 로 birth time 확인 → 웹 액세스 로그 동시간대 POST 요청 대조
↓
[Response] 디렉터리 내용 보존·해시 → 웹 취약점 점검
| 실수 | 결과 | 예방 |
|---|---|---|
디렉터리를 만들고 나서 chmod 777 | 모든 사용자가 파일 생성·삭제 | 필요한 계정만 소유자·그룹으로 지정 |
mkdir -m 700 -p a/b/c로 상위도 700이라 생각 | 상위 a, a/b는 umask 기준 | 상위도 필요하면 따로 chmod |
/tmp에 고정 이름 디렉터리 사용 | 선점·심볼릭 링크 공격 | mktemp -d |
| 배포판별 umask 차이 무시 | 서버마다 권한 불일치 | umask 확인, 스크립트에서 모드 명시 |
| 링크 수를 "파일 개수"로 해석 | 디렉터리 분석 오류 | 링크 수 = 2 + 하위 디렉터리 수 |
[ ] mkdir 과 mkdir -p 의 차이를 확인했다
[ ] umask 값을 확인하고 기본 디렉터리 권한을 계산했다
[ ] Rocky 와 Ubuntu 의 mkdir 결과 차이를 비교했다
[ ] mkdir -m 이 umask 영향을 받지 않음을 확인했다
[ ] 하위 디렉터리 추가 시 상위 링크 수 변화를 확인했다
[ ] 공용 경로에서는 mktemp -d 를 써야 하는 이유를 이해했다
mkdir은 0777을 요청하고 커널이 umask 비트를 지워 최종 권한을 만든다.755, Ubuntu(umask 002) → 775로 결과가 다르다.-m은 umask와 무관하게 지정한 권한을 적용하지만, -p로 함께 생기는 상위 디렉터리에는 적용되지 않는다.w·x 권한 이 필요하고, 상위의 mtime·ctime과 링크 수가 바뀐다.mktemp -d를 사용한다.다음 글 「08. touch와 파일 생성」 에서는 touch로 빈 파일을 만드는 것 외에, 파일 시간을 임의의 과거로 바꾸는 기능 을 다룬다. 공격자가 흔적을 숨기는 타임스탬프 조작(timestomping)을 재현하고, 그래도 숨길 수 없는 시간(ctime)이 무엇인지 확인한다.