[Write-ups] CSAW CTF Quals 2017

CSAW là giải CTF dành cho học sinh/sinh viên được tổ chức hàng năm, có chất lượng khá tốt. Bởi vì năm ngoái có team được mời đi UAE dự final, nên năm nay cố thi biết đâu may mắn =))

Thật không may là giải này anh em bận gần hết, chỉ còn khoảng 2-3 anh em vào làm vài bài, rồi cũng bận. Thế nên… mình cân hết các mảng. Và dĩ nhiên, một người thì không thể nào bằng một team được. Đây là write-ups cho những bài mình làm được:

  1. Another Xor – Crypto 100
    Link: cipher.py encrypted

    Đọc qua file cipher.py, không khó để nhận ra rằng thuật toán mã hoá chỉ là phép XOR với key repeat, và chúng ta chưa biết key length. Với những thể loại XOR bình thường này thì có một tool đơn giản mà hiệu quả, xử đẹp trong vòng vài nốt nhạc, là cribdrag.

    Giờ phần việc khó nhất là đoán key. Sau một lúc thử, từ A qualification, A quantum,… thì mình tìm thấy một từ có vẻ có nghĩa: A quart. Đem đi google, thì, may mắn và magic, key xuất hiện trước mắt mình. Và mình vẫn không biết tại sao như vậy.

  2. Shia Labeouf-off! – Web 150

    Pick 1:
    http://web.chal.csaw.io:5487
    http://web.chal.csaw.io:5488
    http://web.chal.csaw.io:5489
    http://web.chal.csaw.io:5490

    Đề cho một website code trên framework Django. Và điều đầu tiên mình nghĩ đến khi thấy Django/Flask là Server-Side Template Injection. Để kiểm chứng, ta cần tìm một field nào cho input, và mình thấy http://web.chal.csaw.io:5487/ad-lib/.

    Thử input {% abc %}, kết quả như hình:

    Ok, server bật DEBUG = True, và ta có thể confirm là có bug SSTI.

    Vì có DEBUG = True, mình sẽ tìm tất cả các link, các cách input có thể sao cho server trigger ra exception, rất có thể chúng ta sẽ leak được source code hay cái gì đó đại loại vậy. Sau một lúc fuzzing thì mình thấy ở URL http://web.chal.csaw.io:5487/polls/3/vote/

    Ta thấy có hai filter method/attribute là listmegetme.

    Vậy tóm lại, lợi dụng bug SSTI ở trên, cùng với hai filter vừa tìm được, ta sẽ có flag, với điều kiện biết được object nào có chứa flag. Nếu để ý, ta sẽ thấy object này cũng đã được show ra ở bước confirm bug SSTI:

    Quay lại http://web.chal.csaw.io:5487/ad-lib/ để lấy flag thôi:

  3. Little Query – Web 200

    http://littlequery.chal.csaw.io

    View source web, ta thấy có một đoạn code bị comment:

    Check thử xem sao:


    Tiếp tục:


    Ơ dễ dãi vậy, cho đọc db và table à?

    Đoán tên db thôi 😀 bài là Little Query, vậy đoán thử db=littlequery xem sao:

    Đúng luôn kìa!

    Để ý một tí, ở trên tên db và tên table nằm trong cặp ngoặc (backquote). Còn tên db đúng thì không nằm trong cặp backquote. Vậy rất có thể có bug SQLi ở đây. Mình thử với một payload khá “truyền thống và gia giáo”:


    À quên, còn cái table. user xem thử:

    Magic 😮

    Login thôi.

    À nếu bạn nghĩ challenge đến đây là hết thì xin chúc mừng bạn, bạn đã lầm.

    Thử lại bằng Live HTTP Header:

    Và đây là flag 😀

  4. baby_crypt – Crypto 350

    The cookie is input + flag AES ECB encrypted with the sha256 of the flag as the key.
    nc crypto.chal.csaw.io 1578

    Rất may mắn, mình vừa làm bài này ở WhiteHat Challenge 04, thậm chí bài này còn dễ hơn bài của WhiteHat nữa.

    Lấy code cũ ra modify lại thôi :v

Conclusion: Dù kết quả không cao lắm, nhưng nói chung là great game 😀 Thank you for reading!

0CTF 2017 Quals: EasiestPrintf (pwn 150)

Warm UP! A traditional Format String Attack.

It’s running on Debian 8.

nc 202.120.7.210 12321

EasiestPrintf

libc.so.6_0ed9bad239c74870ed2db31c735132ce

 

Trong thời gian chuẩn bị HITB GSEC CTF 2017, mình ngồi lục lại các bài pwn trong giải 0CTF 2017 Quals luyện tập.

Nhìn lên nhìn xuống thấy có 2 bài dễ nhất là char 130 points, EasiestPrintf 150 points.

Cơ mà mình lại thích Format String nên chọn EasiestPrintf.

$ file EasiestPrintf
EasiestPrintf: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=61cd88e3d189854473fddf7c0ace6450986e4b02, not stripped

Debug ta thấy trong main gọi 2 hàm chính là do_readleave.

do_read thì cho phép ta đọc giá trị tại địa chỉ bất kì do người dùng nhập vào.

hàm leave đọc 158 bytes từ người dùng rồi in ra và chính nó làm format luôn nên dẫn tới lỗi format string.

nhưng ngay sau đó thì call ngay hàm _exit.

 

Ta không có quyền ghi đè _exit GOT vì vậy phải exploit ngay trong hàm print

Debug ta thấy printf gọi tới vfprintf, vfprintf gọi tới buffered_vfprintf.

Trong buffered_vfprintf có đoạn mã sau:

Chương trình sẽ call [ecx+0x1c]ecx_IO_file_jumps trong libc.

vtable _IO_file_jumps nằm trong vùng nhớ không có quyền ghi (write).

Trace ngược lại ta thấy:

_IO_file_jumps nằm tại _IO_2_1_stdout_+0x94 mà vùng này ta có quyền ghi (write).

Hướng xử lý là ta sẽ đổi địa chỉ _IO_file_jumps và tạo 1 vtable fake mới để chương trình gọi tới system.

_IO_2_1_stdout_ ta sẽ đổi thành sh\x00\x00

 

Cụ thể như sau:

new_IO_file_jumps = _IO_2_1_stdout_+0x150

new_IO_file_jumps+0x1c = system

_IO_2_1_stdout_ = “sh\x00”
Vậy ta cần địa chỉ của _IO_2_1_stdout_system.

Các địa chỉ này ta sẽ có được bằng cách đọc giá trị tại địa chỉ bất kỳ trong hàm do_read.

Mình đọc địa chỉ của _IO_2_1_stdout_ từ 0x804a044 trong bss.

libc đề đã cho => tính được system.

Hiện tại server của 0ctf không còn kết nối được nữa nên mình chỉ exploit local thôi.

Full payload here.