2018/09/15

WhiteHat Grandprix 2018 - Quals - Web02 aka Pepe sadboiz (chưa hoàn thiện)




# English version below (or Google Translate /m\)

Đề cung cấp source code, môi trường cài đặt trong một file zip duy nhất. Để cài đặt môi trường giống như server challenge thì chỉ cần dùng docker (docker-compose).
Src
Tự thú 1: Tôi là người tạo ra các đề bài Web02, Re07, Re08. Vì vậy rất xin lỗi nếu bạn đã cảm thấy phí thời gian vào những challenge này.
Tự thú 2: Có ít nhất 2 cách giải, 1 là cách mà tôi mong các đội làm ra, 1 cách khác mà tôi không chú ý.

Tôi định viết một bài thật là dài để cho các bạn mới chơi CTF đọc, nhưng mà bạn ơi, thời gian đâu :( Vậy nên tôi sẽ chỉ note một vài điểm mốc như sau:
- Tại sao lại là docker / docker-compose : NHANH, tất nhiên rồi, gõ vài lệnh và trong tíc tắc có môi trường phát triển có thể dùng được luôn, dễ đọc dễ hiểu (COPY, RUN, ... ?)
- Tại sao lại là php composer : các thư viện phổ biến, không ai phát minh lại cái bánh xe đúng không?
- Tại sao lại là XAMPP (LAMPP) : cũng như docker thôi, không cần cấu hình nhiều.
- Tại sao có phantomjs : để chụp ảnh website thôi mà
Tự thú 3: Script cài đặt môi trường trên tôi chỉnh lại từ  1 chỗ nào đó, tuy nhiên có vẻ thì nó đã bị xóa khỏi internet (https://hub.docker.com/r/skaparate/xampp/~/dockerfile/)

Do không tìm lại được file gốc nên những thay đổi của tôi khó nhận ra hơn, nhưng lại có vẻ giống với mặc định khi cài đặt XAMPP hơn, đó là : vẫn giữ giới hạn truy cập vào 1 số đường dẫn trong XAMPP
sed -i.bak s'/Require local/Require all granted/g' /opt/lampp/etc/extra/httpd-xampp.conf 


Chạy docker rồi vào web xem tính năng:
- Website cho đăng kí người dùng, thông tin lưu trong cookie
- Chụp ảnh website và lưu thông tin vào phiên làm việc của người dùng (sqlite database)

Tự thú 4: Có gì đó sai sai, đúng vậy, trong quá trình xem code có thể bạn đã nhận ra vài chỗ khả nghi :
1 nơi có khả năng inject command ($cacheFile, $cookieFile)

1 nơi dùng unserialize

1 nơi dùng cookie (kết hợp mật mã) để giải mã


Truy vết ngược lại $cacheFile (tương tự với $cookie): $cacheFile <- $meta['path'] . CK_PATH (cố định) <- ($user<-metadata) <- decrypt($_COOKIE['metadata'], $_COOKIE['username'])

Nếu ta can thiệp được vào 1 trong các giá trị này thì ta có thể thay $cacheFile thành bất cứ gì ta muốn => RCE (coi như xong)

Tuy nhiên những gì ta có thể can thiệp là 2 giá trị trong cookie, qua các hàm kiểm tra decrypt, encrypt thì việc thay đổi cookie không có kết quả (Tự thú 4.1: tôi không giỏi crypto nên cách làm không cần khai thác lỗ hổng crypto). Thế nhưng nếu bằng cách nào đó tạo được cookie hợp lệ, bằng key hợp lệ như cách hàm encrypt làm thì sao?

Có thể bạn đã từng dừng lại ở chuỗi 'blowfish_secret', điều này có gợi nhớ gì cho bạn không? Cái này không liên quan đến các loại cá lắm nhưng khá liên quan đến crypto (một lần nữa, bạn không cần phá mã gì ở đây cả). Giả sử bạn chạy được docker-compose và có một môi trường test:
grep blowfish_secret /app/

Ơ kìa, gì vậy chứ. Sau cuộc thi tôi có nhận được một vài câu hỏi, phần chung đều là không có một môi trường thích hợp tìm ra chuỗi khai thác. Có thể bạn thắc mắc là việc này thì có cái quái gì thực tế chứ? Shared host,  với cấu hình không an toàn, PHP có thể tự do tạo và sử dụng các file lưu các session dưới sự quản lý của Apache server, vậy nên trong trường hợp của tôi, phpmyadmin nếu dùng chung cookie (thực chất chính là PHPSESSID) có thể thoải mái chính sửa thông tin session và gây ảnh hưởng tới site khác dùng dữ liệu từ session.
Có 2 hướng can thiệp vào session: Sửa, Xem
- Sửa: tôi được chọn tự do 1 giá trị nào đó và gán vào 1 trường trong session
- Xem: tôi được xem 1 trường trong session.
Trong quá trình tìm hiểu phpmyadmin vô tình tôi phát hiện ra thư mục Setup củ PhpMyAdmin có thể được sử dụng để chèn dữ liệu vào session theo một cấu trúc định sẵn.
Do có phantomjs (có 1 đoạn code liên quan đến curl nhưng không liên quan đến challenge), bạn có thể nghĩ đến SSRF, tuy nhiên đường dẫn đã được lọc chỉ cho phép http hoặc https và script để chụp màn hình đã tắt Javascript.


Không thể sửa mà không có POST trong trường hợp này, cách còn lại là làm cách nào đó để lộ ra dữ liệu từ session.
- SESSION[$username]
<TODO: write>
https://github.com/phpmyadmin/phpmyadmin/blob/master/setup/config.php#L44

Một vấn đề khác đó là phpMyAdmin chỉ có thể truy cập từ localhost hoặc vùng mạng được cho phép (theo cấu hình httpd).
Đó cũng là khi tính năng chụp hình phát huy tác dụng. Nhưng mà bạn ơi, làm sao bypass SOP để set cookie bây giờ? Bạn gọi DNS rebinding trả lời. Tập hợp lại ta có 1 chain như sau:
- DNS rebinding cài đặt cookie phpmyadmin trùng với PHPSESSID hiện tại
- liên tục chụp đến khi ip phân giải ra ip server của bạn để vào trạng thái set cookie. Sau khi cài được cookie thì tiếp tục chụp đến khi ip trở về localhost (127.0.0.1) để làm lộ ra blowfish_secret
- Sử dụng blowfish_secret để chỉnh sửa metadata.
- Flag?

Tự thú 5: Tôi phá bánh xe. Cách trên không phải là cách mà tôi mong các đội làm ra. Như đã viết bên trên, có 1 chỗ sử dụng serialize/unserialize. Lí do tôi dùng chúng ở đây là vì có gadget khai thác unserialize để lấy flag thông qua thư viện Gregwar's Image /m\ (bản mới nhất tại thời điểm diễn ra CTF)
Khi setup, tôi đã lựa chọn .htaccess để chặn user xem thư mục của họ bằng file ảnh. Tuy nhiên về mặt lý thuyết, có thể xảy ra trường hợp race condition khi mà cronjob chưa kịp xóa hết cả thư mục thì đã xông vào lấy ra danh sách các file. ezpz.
Trở lại cái gadget.

Just say the magic word:

__toString


SPOILER ALERT: PoC here. Việc tìm ra bug này thì tôi sẽ không trình bày ở đây (về cơ bản là tìm các magic method được gọi khi unserialize, để thực thi payload ngay khi sử dụng ví dụ như toString khi ép thành kiểu string, hay khi destruct, hoặc overide method đặc biệt của class đặc biệt nào đó như rewind ), tuy nhiên bạn có thể trace theo để tìm payload khác.


Ngoài gadget xóa file thì còn nhiều gadget với nhiều công dụng khác ;)

Peace!
Tôi không có lựa chọn nào khác ngoài việc public một bài viết còn đang dang dở (tôi rất không thích điều này), nhưng thời gian ơi, bạn ở đâu :(

Links:
http://material.grandprix.whitehatvn.com/web02
https://github.com/phpmyadmin/phpmyadmin/blob/master/setup/config.php#L44
<redacted>
https://github.com/rapid7/metasploit-framework/issues/6192


## English version:

1 comment: