시스템보안

John the Ripper를 사용한 Password Crack과 mkpasswd를 사용한 패스워드 만들기에 대하여

JustSangRok 2026. 6. 19. 16:08

John the Ripper를 사용한 Password Crack과 mkpasswd를 사용한 패스워드 만들기

실습 환경

Kali Linux

Rocky Linux 9.7


1. John the Ripper란

John the Rippe 는 시스템 관리자가 자기 시스템에 약한 패스워드를 쓰는 사용자를 찾아내도록 도와주는 패스워드 크래킹 도구다.

원래 목적이 공격은 아니고, 패스워드 보안 감사(audit) 를 위해 만들어진 것이다.

john이 일하는 방식

john이 shadow 해시를 크랙하는 원리는 의외로 단순하다.

사전 파일 (rockyou.txt)               shadow 파일
   ┌─────────────┐                    ┌─────────────────────────┐
   │ 123456      │                    │ pse1:$6$rounds=100000$  │
   │ password    │                    │   <salt>$<해시값>       │
   │ qwerty      │                    └─────────────────────────┘
   │ iloveyou    │                              │
   │ ...         │                              │ ① salt와 rounds 추출
   └──────┬──────┘                              │
          │                                     ▼
          │  ② 후보 비밀번호 하나 꺼내서         ┌──────────────┐
          └──────────────────────────────────►  │ 같은 알고리즘 │
                                                │ 같은 salt    │
                                                │ 같은 rounds  │
                                                │ 로 해싱      │
                                                └──────┬───────┘
                                                       │
                                                       ▼
                                              ③ shadow의 해시값과 비교
                                                 ├ 일치 → 비밀번호 찾음
                                                 └ 불일치 → 다음 후보

사전 파일에서 단어를 하나씩 꺼내 shadow에 적힌 것과 똑같은 방식(같은 salt + 같은 rounds + 같은 알고리즘)으로 해싱한 뒤 결과를 비교하는 식이다. 해시는 단방향이라 복호화는 못 하지만, 후보 단어를 똑같이 해싱해서 맞춰보는 건 가능하다.


2. yescrypt 

shadow 파일을 보다 보면 SHA-256($5$), SHA-512($6$)는 익숙한데 가끔 $y$ 로 시작하는 해시가 보인다. 이게 yescrypt다.

SHA-512와 yescrypt는 둘 다 "해시 함수"지만 목적이 다르다.

구분  SHA-512   yescrypt
분류 범용 암호 해시 함수 패스워드 해싱 전용 함수 (KDF)
속도 빠름 의도적으로 느림
메모리 사용 작음 많이 먹음 (memory-hard)
용도 파일 무결성, 디지털 서명 등 비밀번호 저장 전용
GPU/ASIC 내성 약함 강함

여기서 핵심은 "의도적으로 느리고 메모리를 많이 먹는다" 는 점이다. 일반적인 소프트웨어는 빠를수록 좋지만, 패스워드 해싱은 느릴수록 좋다. 공격자가 brute force로 1초에 시도할 수 있는 횟수를 줄여주기 때문이다.

재미있는 점. yescrypt를 설계한 사람은 Alexander Peslyak, 일명 Solar Designer다. 그런데 이 사람이 바로 John the Ripper를 1996년에 만든 그 사람이다. 

yescrypt는 scrypt 기반으로 2013년에 발표됐고, 현재 Fedora, Debian, Ubuntu, Arch Linux등이 기본 패스워드 해시로 채택하고 있다. Rocky Linux 9는 아직 SHA-512가 기본이다.


3. John the Ripper로 Password Crack

시나리오.

어떤 서버에서 Privilege Escalation으로 root 권한 탈취에 성공했다는 시나리오이다.
그래서 /etc/shadow와 /etc/passwd를 그대로 빼냈다. 

1) unshadow로 두 파일 합치기

john은 shadow 파일 하나만 던져주면 잘 동작하지 않는다. 계정 정보(passwd)와 해시 정보(shadow)가 결합된 단일 형식이 필요하다. 그래서 john에 딸려오는 unshadow 도구를 쓴다.

unshadow /etc/passwd /etc/shadow > password

 

이렇게 하면 password라는 파일이 만들어지는데, 안을 들여다보면 /etc/passwd 형식인데 2번째 필드(원래 x)에 해시값이 들어가 있는 형태다.

pse1:$y$rounds=100000$PUADxGPDoCDAr0PB$DYz7RE5bb...KonDg.:1001:1001::/home/pse1:/bin/bash

이게 john이 좋아하는 형식이다.

2) 사전 파일 압축 해제

Kali Linux에는 rockyou.txt 라는 유명한 사전 파일이 기본으로 깔려 있다. 2009년 RockYou 서비스가 해킹당했을 때 유출된 3,200만 개의 실제 비밀번호 목록이다.

 

3) john 실행

john --format=crypt --wordlist=/usr/share/wordlists/rockyou.txt password

옵션 의미

--format=crypt — 시스템의 crypt(3) 라이브러리를 통해 해시 처리 (SHA-512, yescrypt 등 다양한 shadow 해시를 처리할 수 있음)

--wordlist=... — 어떤 사전 파일을 쓸지 지정

마지막 인자 — 크랙할 해시가 담긴 파일 (위에서 만든 password)

비밀번호가 약하면 몇 초 안에 크랙된다.

4) john.pot 

john은 한 번 크랙에 성공한 비밀번호를 /root/.john/john.pot 디렉터리 안의 john.pot 파일에 저장해둔다. 그래서 다음에 같은 해시를 다시 크랙하려고 하면, 이미 알고 있는 해시는 자동으로 건너뛴다.

이게 편하긴 한데 같은 해시를 다시 실습해보고 싶을 때는 좀 귀찮다. 다시 처음부터 돌려보고 싶으면 john.pot을 지워주면 된다.

rm -rf john.pot

 


4. Rocky Linux에서 John 컴파일해서 쓰기

Kali에는 john이 기본으로 깔려 있지만, Rocky Linux엔 없다. 그래서 소스에서 직접 컴파일해야 한다.

1) Rocky Linux로 파일 전송하기

Kali에는 john이 기본으로 깔려 있지만, Rocky Linux엔 없다. 그래서 소스를 받아서 직접 컴파일해야 한다. 일단 john 소스 파일을 어떻게든 Rocky Linux 안으로 옮겨야 하는데, 방법은 여러 가지가 있다.

가장 평범한 방법은 호스트 PC(VMware 바깥의 내 컴퓨터)에서 cmd를 열고 ssh/scp로 직접 보내는 것이다.

scp john-1.9.0.tar.gz user@<Rocky_IP>:/home/user/

VMware에 SSH 포트만 열려 있으면 한 줄로 끝난다. 가장 빠르고 표준적인 방법이다.

하지만 나는 일부러 다른 방법을 실습해봤다. VMware 안에 윈도우 게스트를 하나 더 띄워두고, 그 안에서 Rocky Linux로 파일을 보내는 시나리오다.

● VMware 안의 윈도우 게스트에 알드라이브(FTP 클라이언트)를 설치

● Rocky Linux에 vsftpd(FTP 서버)를 설치하고 실행

● 알드라이브에서 Rocky Linux로 ftp 연결

● 알드라이브로 Rocky Linux에 접속해서 파일 드래그앤드롭

 

# Rocky Linux에서 FTP 서버 설치 및 실행
dnf -y install vsftpd
systemctl start vsftpd
systemctl enable vsftpd     # 부팅 시 자동 실행도 켜두면 편함

알드라이브에서 Rocky Linux IP로 접속하면 사용자 홈 디렉터리로 들어가게 되고, 거기에 파일을 드래그하면 끝이다.

2) Makefile 수정 — SHA-512 지원 추가

일단 로키에서 cd /home/pse1으로 들어가서 tar -xvf로 파일 압축을 해제해준다.

그런 뒤에 john파일 안에 src파일로 들어간다.

거기에 보면 Makefile이라는게 있다.

 

Rocky Linux 9는 기본 패스워드 해시가 SHA-512($6$) 다. 그런데 john 기본 빌드에는 시스템 crypt(3) 라이브러리 연결이 빠져 있어서, 이대로 컴파일하면 $6$ 해시를 만나도 "No password hashes loaded" 만 뜨고 못 깬다.

src/Makefile을 열어서 -lcrypt 를 추가해서 이렇게 만든다.

LDFLAGS = -s -lcrypt

-lcrypt는 시스템의 crypt(3) 라이브러리를 john과 함께 링크하는 옵션이다. 이게 있어야 SHA-512, yescrypt 같은 시스템 의존적인 해시를 시스템 자체 함수를 호출해서 검증할 수 있다.

3) 컴파일

gcc부터 설치한다.

GCC = GNU Compiler Collection. 소스 코드를 컴퓨터가 실행할 수 있는 기계어(바이너리)로 바꿔주는 컴파일러 모음이다.

dnf -y install gcc

그 다음 src 디렉터리에서 명령어를 순서대로 실행한다.

make              # 사용 가능한 빌드 target 목록을 보여줌 (아직 컴파일은 안 함)
make clean        # 이전 빌드물이 있다면 정리
make linux-x86-64 # 실제 컴파일 실행

첫 번째 make는 빌드를 시작하는 게 아니라 어떤 환경에서 빌드 가능한지를 보여주는 단계다. 그 목록 중에서 우리 시스템에 맞는 linux-x86-64를 선택해서 실제로 컴파일한다.

빌드가 끝난 뒤 run 디렉터리로 들어가보면 john 이라는 실행 파일이 생성되어 있다. 이제 Rocky Linux에서도 john을 쓸 수 있다.

4) 주의할 점 — 경로와 파일명

직접 컴파일한 john은 시스템 PATH에 등록되어 있지 않다. 그래서 명령어를 칠 때 반드시 ./을 붙여줘야 한다.

./unshadow /etc/passwd /etc/shadow > passwd.txt
./john --wordlist=password.lst ./passwd.txt

./이 없으면 셸이 PATH에서 찾다가 못 찾고 "command not found"를 뱉는다. 매번 ./을 붙이기 귀찮으면 run 디렉터리를 PATH에 추가해두거나, /usr/local/bin에 심볼릭 링크를 걸어두면 된다.


5. mkpasswd로 직접 해시 만들기

shadow에 들어가는 해시를 직접 만들어내는 도구가 mkpasswd다. shadow 파일 변조 실습의 핵심 도구이기도 하다.

1) Rocky Linux에 mkpasswd 설치하기

설치 방법

dnf -y install epel-release
dnf -y install mkpasswd

Rocky Linux 9에서는 mkpasswd가 AppStream 저장소에 별도 RPM 패키지로 따로 패키징되어 있다(mkpasswd-5.5.9-4.el9). 의존성으로 whois-nls가 같이 따라온다. Debian/Ubuntu 계열은 whois 패키지를 통째로 깔아야 mkpasswd가 딸려오지만, RHEL 9 / Rocky 9에서는 mkpasswd만 집어서 깔 수 있게 분리해뒀다.

주의 — expect 패키지의 mkpasswd는 다른 도구다.

같은 이름이지만 옵션이 완전히 다른 mkpasswd가 expect 패키지 안에 들어있다. Rocky 9에서는 다행히 이름 충돌을 피하려고 그쪽을 mkpasswd-expect 로 별도 패키징해뒀지만, 다른 배포판에서는 그냥 mkpasswd로 깔리는 경우도 있다. man mkpasswd로 옵션이 --method/--salt/--rounds가 맞는지 한 번 확인해야 한다.

2) mkpasswd 사용법

mkpasswd --method=SHA-512 --salt=abcdefgh 123456

옵션을 풀어보면.

--method=SHA-512 — 암호화 알고리즘 지정 (MD5, SHA-256, SHA-512, yescrypt 등)

--salt=abcdefgh — salt 값 지정 (생략하면 랜덤 생성)

123456 — 마지막 인자가 평문 비밀번호

실행 결과는 이렇게 나온다.

$6$abcdefgh$fsQAa16ibv7N/pkIMTWAm9JGNGOIC4zzMpCqrfg2f6e5sTkTI49pdvKD4Wjy8PO6mzddXEf0oICL6PtgHim/F.

shadow 파일에서 봤던 것과 똑같은 형식이다. 알고리즘ID($6$) → salt → 해시값 의 구조.

3) shadow 해시 그대로 재현해보기

이제 진짜 신기한 걸 해보자. 이미 shadow에 있는 해시를 mkpasswd로 똑같이 재현할 수 있을까?

먼저 사용자를 만들고 비밀번호를 설정한다.

useradd pse1
passwd pse1     # 123456으로 설정

/etc/shadow를 들여다보면 이렇게 들어있다.

pse1:$6$rounds=100000$9D1fYdDtDG2WRqnd$qnQkTT.mlISAzDZZuuHoo0YlC8GYiQYDv5wlPxVX7fOw4nYKYU2xsrprdtr0VUmZZY1nzOndxxCSyk2eav9un0:20623:0:99999:7:::

암호 부분만 잘라서 분해해본다.

$6$                  → 알고리즘 (SHA-512)
rounds=100000        → stretching 100,000회
$9D1fYdDtDG2WRqnd$   → salt 값
qnQkTT.mlISAzD...    → 실제 해시값

이 정보를 그대로 mkpasswd에 넣어주면.

mkpasswd --rounds=100000 --method=SHA-512 --salt=9D1fYdDtDG2WRqnd 123456

결과:

$6$rounds=100000$9D1fYdDtDG2WRqnd$qnQkTT.mlISAzDZZuuHoo0YlC8GYiQYDv5wlPxVX7fOw4nYKYU2xsrprdtr0VUmZZY1nzOndxxCSyk2eav9un0

완벽히 똑같은 해시가 나온다. 이게 가능한 이유는 SHA-512 해시 함수가 결정적(deterministic) 이기 때문이다. 같은 입력(비밀번호 + salt + rounds)을 넣으면 같은 출력이 나오게 설계됐다. 그렇지 않으면 로그인 검증 자체가 불가능하니 당연한 얘기이기도 하다.


6. shadow 파일 변조해서 다른 사람으로 로그인하기

shadow 파일을 root 권한으로 변조해서 남의 계정 비밀번호를 우리가 아는 값으로 변조해볼 수 있다.

1) 변조용 해시 만들기

먼저 임의의 salt로 SHA-512 해시를 하나 만든다. 비밀번호는 우리가 외울 수 있는 123456으로.

mkpasswd --rounds=100000 --method=SHA-512 --salt=A1b2C3D4e5F6G7h8 123456

결과:

$6$rounds=100000$A1b2C3D4e5F6G7h8$ZrPbzzs7zLE6.beMPZ27koyDclEzJPC64LfUKZzGGecnMLLt5PnkrDXH49whCgnVcZ..r7r6l8PxdN49UxjAd.

 

2) shadow 파일 수정

먼저 pse1의 비밀번호를 우리가 모르는 값으로 임의 변경해본다(원래 알고 있던 비밀번호의 영향을 배제하기 위해).

passwd pse1     # 아무 비밀번호나 입력

그 다음 /etc/shadow를 열어서 pse1 줄의 해시 부분을 위에서 만든 해시로 교체한다.

vi /etc/shadow
변경 전:
pse1:$6$rounds=100000$<원래salt>$<원래해시>:20623:0:99999:7:::

변경 후:
pse1:$6$rounds=100000$A1b2C3D4e5F6G7h8$ZrPbzzs7zLE6...UxjAd.:20623:0:99999:7:::

:wq!로 저장한다.

3) 가상 콘솔에서 로그인 시도

Ctrl + Alt + F3로 가상 콘솔을 띄운다. pse1 계정으로 로그인을 시도하고, 비밀번호엔 우리가 mkpasswd로 만들 때 썼던 123456 을 입력해본다.

그냥 로그인된다. 

4) 이게 가능한 이유

Linux는 단방향 해시 방식으로 비밀번호를 저장한다. 즉 shadow 파일에 들어있는 건 비밀번호 자체가 아니라 비밀번호를 해시한 결과다. 해시는 단방향이라 거꾸로 비밀번호를 알아낼 수 없다.

그렇다면 로그인할 때는 어떻게 검증하는가?

사용자가 비밀번호 입력
       │
       ▼
shadow에 저장된 해시와 동일한 방식
(같은 알고리즘 + 같은 salt + 같은 rounds)
로 입력 비밀번호를 해싱
       │
       ▼
결과를 shadow의 해시값과 비교
       │
       ├─ 일치 → 인증 성공
       └─ 불일치 → 인증 실패

즉 시스템은 저장된 해시와 똑같은 결과가 나오는 입력값이라면 무조건 통과시킨다. 우리는 mkpasswd로 "123456"을 SHA-512 + 특정 salt로 해싱한 결과" 를 shadow에 직접 박아 넣었으니, 로그인 시점에 시스템이 123456을 같은 방식으로 해싱하면 당연히 일치한다. 그래서 통과된다.

비밀번호의 본질은 "원본"이 아니라 "해시 결과의 일치" 이다.

방어자 입장에서 해야할 것

/etc/shadow의 권한이 절대 새지 않게 유지 — 600 또는 000, 소유자 root. 

root 권한 자체를 보호 — 이 공격의 전제는 "root 권한이 있다"는 것이다. 즉 본질적으로는 Privilege Escalation 방어가 핵심이다. SUID 바이너리 점검, sudo 정책 강화, 커널 업데이트.

무결성 모니터링 — AIDE, Tripwire 같은 도구로 /etc/shadow 변경을 탐지. 누가 언제 shadow를 건드렸는지 알 수 있어야 한다.

약한 비밀번호 자체 감사 — 관리자가 정기적으로 john을 돌려 자기 시스템의 약한 비밀번호를 먼저 찾아내고 교체 요구. 공격자보다 빨라야 한다.