[Web]picoCTF 2021

Câu chuyện về picoCTF 2021 và dân chơi noob bị lừa :< vô làm web mà có tích hợp crypto, re,... :|

GET aHEAD

Link chall: http://mercury.picoctf.net:34561/

Đề bài cũng nói ra được cách làm.

Mở burpsuite mở challenge lên và click chọn màu ĐỎ/XANH và thay đổi method GET/POST thành HEAD và đọc gói tin gửi về sẽ thấy flag.

picoCTF{r3j3ct_th3_du4l1ty_8f878508}

flag

Cookies

Link chall: http://mercury.picoctf.net:29649/

Nhập vào 1 loại cookie thì sẽ được redirect đến /check và value của cookie name sẽ thay đổi theo thứ tự của mảng cookie đó phía server.

Mình thử sửa giá trị cookie name thành 7, 8, 9 gì đó thì sẽ in ra màn hình 1 loại cookie. Vậy nên mình quyết định tăng giá trị đó từ từ. Limit của mình lúc đó là 20, nếu đến 20 vẫn chưa có thì mình sẽ viết script chạy :v Nhưng may mà mới 18 đã thành công.

picoCTF{3v3ry1_l0v3s_c00k135_a1f5bdb7}

thay đổi giá trị cua cookie name

Scavenger Hunt

Link chall: http://mercury.picoctf.net:39698/

Bài này mình từng gặp lúc practice :v cứ đi theo manh mối có được xem các file html, js, css, robots.txt,...

picoCTF{th4ts_4_l0t_0f_pl4c3s_2_lO0k_fa04427c}

index.html
mycss.css
robots.txt
.htaccess

Tới lúc này mình có hơi khựng vì chưa dùng Mac bao giờ :< may mà nhanh trí đi hỏi 1 anh senpai có kinh nghiệm code Mac lâu năm :v

.DS_Store

Some Assembly Required 1

Link chall: http://mercury.picoctf.net:36152/index.html

Lúc này mình có hơi dại vì gòi coi source code, decode đoạn js các kiểu thì thấy có 1 file Web Assembly nhưng mà từ đầu dùng dev tool mở tab sources ra thì có lẽ tiết kiệm 1 khoảng thời gian :v

Flag nằm luôn trong file đó đỡ phải đọc code.

picoCTF{d88090e679c48f3945fcaa6a7d6d70c5}

flag nè

More Cookies (after-end)

Link chall: http://mercury.picoctf.net:34962/

Link reference: https://crypto.stackexchange.com/questions/66085/bit-flipping-attack-on-cbc-mode

Source code lượm được

bitflip.py
from base64 import b64decode
from base64 import b64encode
import requests


def split(word):
    return [char for char in word]


def bitFlip(pos, bit, data):
    raw = b64decode(data).decode("utf-8")

    data = split(raw)
    data[pos] = chr(ord(data[pos]) ^ bit)
    raw = ''.join(data)
    return b64encode(raw.encode())


currentCookie = ""

for i in range(128):
    for j in range(128):
        c = bitFlip(i, j, currentCookie).decode("utf-8")
        cookies = {'auth_name': c}
        r = requests.get("http://mercury.picoctf.net:25992/", cookies=cookies)
        if "picoCTF{" in r.text:
            print(r.text)
            break
        print(c)
        print("no_oke")

Super Serial

Link chall: http://mercury.picoctf.net:2148/

Truy cập vào robots.txt thấy chặn truy cập đến /admin.phps thì phản xạ mình nghĩ đến việc thêm s vào /index.php và quả thật nhận được source code tại đây.

source index.phps

Lúc này mình biết sự tồn tại của /cookie.php/authentication.php . Việc của mình là thêm s vào để đọc được source của 2 file.

Mình để ý ngay đến chỗ unserialize vì đây là chỗ nhạy cảm dễ có lỗi để khai thác.

unserialize, decode base64 và decode url cookie login

Đi đọc source 1 hồi thì mình thấy thêm magic function __toString() (tự trigger mỗi khi khai báo object) trong file authen. Ở function này mình thấy nó trả về content của bất kì file nào mình truyền vào. Nhớ lại 1 xíu hint là flag đang ở đường dẫn ../flag .

đọc file

Từ 2 source code trên và từ hint mình tạo một serialize rồi lần lượt đi base64encode, urlencode.

serialize object và gán biến log_file là path đên

Sau khi encode: TzoxMDoiYWNjZXNzX2xvZyI6MTp7czo4OiJsb2dfZmlsZSI7czo3OiIuLi9mbGFnIjt9

Cuối cùng mình có thể gửi 1 request đến authentication.php với cookie login là đoạn encoded trên.

picoCTF{th15_vu1n_1s_5up3r_53r1ous_y4ll_8db8f85c}

Giải thích thêm: Request đến authentication.php, trong đây có include cookie.php, đoạn cookie mình vừa gửi cookie.php sẽ xử lý decode và unserialize, vì vốn object của mình là access_log nên không gọi được method is_guest thì liền quăng lỗi ra để catch, trong catch error có in object access_log nên lúc này hàm __toString được gọi trả về giá trị đó chính là nội dung của file ../flag.

flag

Who are you?

Bài này sửa hàng loạt các giá trị của các trường theo pico yêu cầu:

User-Agent: PicoBrowser

Referer: http://mercury.picoctf.net/

Date: Wed, 21 Otc 2018

X-Forwarded-For: 2.16.66.0

Accept-Language sv

picoCTF{http_h34d3rs_v3ry_c0Ol_much_w0w_8d5d8d77}

It is my Birthday

Lần đầu đọc đề thì liền có suy nghĩ submit 2 file PDF khác nhau nhưng có hash MD5 giống nhau.

Để làm 2 file có cùng hash mình thấy hơi khoai nên suy nghĩ đơn giản hơn xíu là có nội dung hash giống nhau. Lúc này đầu mình liền nhảy số đến MAGIC HASHES MD5 in PHP.

Reference: https://github.com/spaze/hashes/blob/master/md5.md

Lúc này mình tạo 2 file pdf nhưng nội dung bên trong là 2 chuỗi có hash bằng nhau:

Sau khi up thì chúc mừng "trùng khớp với ý pé"

FLAG: picoCTF{c0ngr4ts_u_r_1nv1t3d_aad886b9}

Most Cookies

Bài này có cho ta source code, ngồi phân tích 1 xíuuuu

Workflow của flask session:

  • <data> + <secret key> --e-n-c-r-y-p-t--> server session stored

  • <client cookie> + <secret key> --d-e-c-r-y-p-t--> server session compared

Đọc source code thì secret key là 1 chuỗi random của 1 mảng cho sẵn:

Đọc thêm xíu thì biết được endpoint mà ta cần để lấy flag:

/display

Khi truy cập vào web thì ta được cấp cho 1 cookie là session có giá trị {very_auth: blank}

Giờ việc của mình sẽ là tìm ra một secret key để generate cookie có giá trị {very_auth: admin}

Ok bắt tay vào làm mình tìm được một công cụ là flask-unsign.

Reference: https://pypi.org/project/flask-unsign/

(mình decode cookie ban đầu)

Công cụ này hộ trợ unsign một cookie và cho mình biết secret key (default sẽ là wordlist của nó, mình có thể bỏ wordlist của mình - mảng cookie trong source)

Mình đã tìm ra secret key giờ mình dùng tool này generate 1 cookie {very_auth: admin}!!!!!!!

Okieeeee giờ modify cookie rồi request đến /display.

Flag: picoCTF{pwn_4ll_th3_cook1E5_3646b931}

Web Gauntlet 2

Ở bài này ban đầu nhìn vào SQLite và mớ filter của nó thì có làm mình hoang mang và bí ý tưởng 1 thời gian. Nhưng may mình từng gặp 1 dạng bài SQLite trước đây và có sử dụng || để ghép chuỗi nên mình mới kịp thời quan lại cuộc chơi =)))))

filter

Payload đầu tiên của mình:

Username: ad'||'min

Password: ad'||'min

Pass được filter rồi nè, nhưng phải tìm được password? :< Tính comment đoạn sau mà không được cả!

Sau 1 hồi vắt óc thì trong đầu mình suy nghĩ ra biến tất cả thành 1 chuỗi rồi sau đó sử dụng 1 hàm để chỉ lấy 5 ký tự đầu (admin) và làm cho từ đọan AND... mất đi!

Ban đầu mình đi kiếm hàm left() nhưng có vẻ sqlite không có @@ nên thôi quay sang đi kiếm hàm substring thì ở sqlite có 1 hàm là substr().

Với nhiều lần thử đi thử lại mình đã tìm được payload hợp lý nhất:

Username: '||substr('ad'||'min'||

Password: ,1,5)||'

Mình mất 10s lag lag không hiểu chuyện gì đã xảy ra? Rõ là đúng mà sao không thấy flag thì sau 10s hết lag mới nhìn ra cái alert success! :> Vào filter.php kiểm tra ngayyy

FLAG: picoCTF{0n3_m0r3_t1m3_e2db86ae880862ad471aa4c93343b2bf}

Web Gauntlet 3

Câu này mình mất khá nhiều thời gian, xem cheat sheet, đọc doc để tìm ra cái-gì-đó-mới-mẻ.

Vì sự giới hạn độ dài nên mình thất bại ở payload trên và khiến mình có suy nghĩ giờ username chỉ có thể dùng ad'||'min thôi và password phải đoán đúng hoặc cách nào đấy cho password luôn đúng! Và thế ý payload đầu mình nghĩ ra ngay lúc đó:

Username: ad'||'min

Password: ' LIKE '%

Tất nhiên là không được! like đã bị lọc :< Thế là mình tìm 1 function nào đó tương tự! Và mình mất cả ngày không thu thập được gì :> Ơ tự nhiên trong đầu nghĩ ra 1 cách search:

sqlite like vs

=")) lụm phải vàng nên bắt đầu mình tìm hiểu các cách sử dụng operator khác như =, matchglob. Mình cuối cùng cũng tìm được glob là phù hợp nhất thay thế like và thay vì dùng '%' and '_' wildcards thì glob dùng UNIX wildcards. PAYLOAD lúc này của mình:

Username: ad'||'min

Password: 'GLOB'*

Thành công thì vào /filter.php check flag thôiiii

Flag: picoCTF{k3ep_1t_sh0rt_6fdd78c92c7f26a10acd3ece176dea4d

X marks the spot

Last updated

Was this helpful?