Cookie Arena CTF Season 2 Writeup - Magic Login

Hello Friends =))
Mình xin phép được góp vui cho event đợt này write up của một challenge thuộc mảng Web. Như mọi người đã thấy trên tiêu đề, là challenge: Magic Login.
Đối với cá nhân mình, có thể nói đây là challenge đơn giản nhất thuộc mảng Web (là challenge duy nhất thuộc mảng Web mình bypass được :sweat_smile: ).
Ok, vậy sau đây ta sẽ bước vào nội dung chính.
Để giải được challenge này, ta cần vận dụng kiến thức về Loose Comparision và File upload Vulnerability.
Đối với PHP, Loose Comparision được thể hiện qua biểu tượng ‘==’, hiểu nôm na có nghĩa là so sánh hai giá trị mà không cần quan tâm đến Data types. Cụ thể hơn khi chạy câu lệnh echo 0 == '0' thì kết quả sẽ trả về 1(tương đương với True), còn trong trường hợp khác nếu viết là echo 1 == '0' thì sẽ không hiển thị giá trị 1 như câu lệnh trước (đồng nghĩa với False).
Còn File upload Vulnerability hiểu đơn giản trong tình huống này là ta có thể upload file code PHP của chúng ta lên server.
Đầu tiên, khi truy cập vào đường link của challenge này, ta bắt gặp giao diện login như sau:

Việc đầu tiên cần làm(chắc chắn rồi :smile:), là nháy inspect để tìm xem có source code không. Ta liền tìm được một đoạn code như hình dưới đây:


Dễ dàng nhận định ngay rằng không thể tận dụng SQLi được rồi.
Đoạn code này cũng không hẳn là quá phức tạp, nếu password nhập vào($pas) qua được bước check $pas == “0” thì ta sẽ bypass được bước login và được điều hướng tới trang upload. Như bình thường thì cứ nhập 0 vào là được thôi, nhưng như vậy thì lại thành ra quá dễ dàng rồi.
Khúc lắt léo nằm ở dòng code:
$pas = hash(‘sha256’, mysql_real_escape_string($_POST[‘password’]));
Sau khi được filter qua hàm để chống SQLi, password sẽ được đưa vào hàm băm SHA256, và hiển nhiên là không có trường hợp nào sha256 trả về một giá trị bằng 0 cả.
Đến đây có một kiến thức nữa ta cần biết, đó là 0e, đối với PHP, có nghĩa là 0 mũ,ví dụ như 0e3 chính là cách viết của 0 mũ 3. Ta cũng nhận thấy rằng bước check password sử dụng dấu ‘==’, dấu hiệu của Loose Comparision.
Kết hợp những dữ kiện này lại, việc cần làm giờ đây chính là nhập một giá trị nào đó cho password sao cho sau khi password được đưa vào hàm băm sha256 ta sẽ được một chuỗi 0e…(0 mũ mấy vẫn cứ là 0 thôi mà ^^).
Và giá trị này là gì thì goolge trong phút mốt là ra: 34250003024812.
Sau khi bypass được phần login, ta được điều hướng đến trang upload:


Kiểm tra source code:


Đọc kỹ sẽ thấy không có cơ chế nào để ngăn ta gửi file code php lên server cả. Như vậy cứ mạnh dạn mà gửi thôi ^^. Payload mình sử dụng: system(“cat /flag.txt”).
Và thế là xong:


Write up đến đây là hết. Cũng là write up đầu tiên mình viết nên về nội dung và hình thức đôi chỗ sẽ không tránh khỏi thiếu xót, mong được mọi người thông cảm và góp ý, cám ơn các bạn :heart: :heart: :heart:
Cũng phải cảm ơn BTC đã tạo điều kiện cho anh em một sân chơi, event thật sự rất bổ ích(và cũng cay đắng không kém, mình mới bypass được có 3 challenge thôi, một chall về web và hai chall programming, nói chung là mình còn phải học nhiều :smile:)

4 Likes

Cảm ơn @JonaSon về bài writeup đầu tiên, chuẩn chỉ và đúng hướng luôngg. Do sự lỏng lẻo và thoải mái quá trong việc tự động ép kiểu kiểu dữ liệu khi so sánh == nên mới xảy ra cơ sự này (loose comparison).

Loose comparison còn xảy ra với các toán tử !=, <=, >=, hàm in_array() hoặc strcmp() trong PHP.
Để khắc phục lỗ hổng này thay vì sử dụng ==, chúng ta nên sử dụng strict comparison bằng các toán tử ===, !==.

Có một số challenge khác trong Cookie Arena mô phỏng lại lỗ hổng này các bạn có thể thực hành thêm:

Tài liệu tham khảo thêm

2 Likes

Cảm ơn @JonaSon vì bài writeup nhé. Bài này rất hay vì bao gồm tới cả 2 security vulnerability concepts. Nhất là phần 2 upload php file có script chạy trên server siêu đỉnh.

1 Like

hay qua!!!

1 Like