Hành trình truy tìm lỗ hổng bảo mật
Trước hết, tớ xem xét đặc điểm chung của cả hai trang web này:- Đây đều là 2 diễn đàn lớn (mục tiêu càng lớn, càng nhiều người dùng thì càng tỉ lệ thuận với sự nguy hiểm của một lỗi bảo mật được phát hiện).
- Cùng sử dụng nền tảng Xenforo.
- Cùng sử dụng một add-on giống nhau để tạo trình chuyển hướng liên kết.
Trong 3 đặc điểm này thì điều thứ 3 chính là mấu chốt:
- http://kenhsinhvien.vn/redirect/?url=https://junookyo.blogspot.com/
- http://forum.vietdesigner.net/redirect/?url=https://junookyo.blogspot.com/
Tại sao tớ biết rằng 2 trang cùng dùng một add-on? Ngoài việc dựa theo cấu trúc liên kết, thì tớ xem mã nguồn trang chuyển hướng của cả 2 và cùng một thấy từ khóa quan trọng sau:
Tìm từ khóa đó trên Google:
Sau khi tìm được mã nguồn của add-on này, tớ khám phá ra dữ liệu (tức URL cần chuyển hướng) được xử lý tại đường dẫn
library\GFNCoders\UrlRedirector\ControllerPublic\Redirect.php:
filterSingle()
không có trong class này nên dựa theo dòng 2 thì tớ có thể đoán được method này được kế thừa từ class XenForo_ControllerPublic_Abstract
của XenForo.Sử dụng công cụ chuyên dụng (FileSeek Pro) để quét thì tìm thấy method này được tạo ra từ
library\XenForo\Input.php
dòng 137.filterSingle()
này, dữ liệu sẽ tiếp tục được chuyển qua cho _doClean()
. Trong _doClean()
, nó lại được chuyển tiếp qua cho cleanString()
tại dòng 231.switch
sao? Tại sao ông lại biết nó sẽ dính case đầu tiên?"Chắc có bạn sẽ thắc mắc điều này. Hãy nhìn vào dòng 7 của tập tin Redirect.php trong hình phía trên (hình thứ 4 từ trên xuống). Bạn có thấy tham số thứ 2 là hằng
XenForo_Input::STRING
được truyền vào khi gọi filterSingle()
không? Do đó tớ có thể dễ dàng biết chắc chắn dữ liệu sẽ đi vào case self::STRING
.Tiếp tục tìm tới
cleanString()
nào!Vecter XSS:
- http://kenhsinhvien.vn/redirect/?url=[XSS]
- http://forum.vietdesigner.net/redirect/?url=[XSS]
Và khi áp dụng kịch bản tương tự như đối với SinhVienIT.Net, tớ phát hiện ra CSRF cũng khả thi. Tức là nếu ai đó chẳng may click vào liên kết chứa vecter XSS thì tớ có thể chiếm được Security Token để đăng bài, gửi tin nhắn, đổi mật khẩu, đổi email,... hay bất cứ hành động nào mà một người dùng có thể làm, và tương tự với các tài khoản admin (nếu họ sơ suất).
PoC (Proof of Concept)
XSS/CSRF trên KenhSinhVien.vn
XSS/CSRF trên VietDesigner.Net
Timeline
- 2:17 PM - 19/07/2016: Tớ liên hệ với quản trị viên VietDesigner.net và thông báo có lỗ hổng bảo mật XSS/CSRF.
- 2:23 PM - 19/07/2016: Quản trị viên VietDesigner.net cho biết đã nhận được báo cáo từ người khác trước đó gần 2, 3 tháng nhưng chưa có thời gian fix.
- 2:25 PM - 19/07/2016: Tớ trả lời lại và cung cấp kịch bản tấn công để cho thấy mức độ nguy hiểm nếu có kẻ xấu khai thác. Đồng thời chủ động đề nghị hỗ trợ quản trị viên trong việc fix lỗi.
- 2:29 PM - 19/07/2016: Tớ liên hệ với quản trị viên KenhSinhVien.vn và thông báo phát hiện ra lỗ hổng bảo mật.
- 2:31 PM - 19/07/2016: Quản trị viên KSV trả lời lại. Tớ cung cấp hình ảnh PoC về lỗ hổng XSS/CSRF.
- 2:47 PM - 19/07/2016: Quản trị viên KSV xác nhận lỗ hổng và fix ngay sau đó.
- 9:45 AM - 22/07/2016: Quản trị viên VietDesigner gửi tin nhắn cho biết rằng lỗ hổng đã được khắc phục và đề nghị tớ kiểm tra lại.
- 5:23 PM - 22/07/2016: Tớ đọc được tin nhắn và xác nhận lại rằng lỗ hổng đã được khắc phục.
* Lỗ hổng trên KenhSinhVien.vn được tính vào bug bounty cùng đợt với các lỗ hổng mà tớ phát hiện bên Phimmoi.net.
Mặc dù tại thời điểm đăng bài viết này thì 2 diễn đàn trên đều đã được vá lỗ hổng. Tuy nhiên, không chỉ có 2 diễn đàn này sử dụng add-on này làm trình chuyển hướng. Nên chắc chắn vẫn còn rất nhiều các diễn đàn XenForo khác có thể bị khai thác. Nếu có thể, hãy chia sẻ bài viết này với quản trị viên mà bạn biết!
Cách khắc phục lỗ hổng
Hiện lỗ hổng bảo mật này đã được tác giả khắc phục trong phiên bản mới nhất 1.0.5, các bạn có thể cập nhật lên là xong. Hoặc tự vá bằng cách sửa lại tập tin Redirect.php từ dòng 9-13 thành:$noUrl = (!$url || empty($url) || !filter_var($url, FILTER_VALIDATE_URL))
// Prevent XSS Attacks (by Juno_okyo)
$url = htmlentities(strip_tags($url), ENT_QUOTES, 'UTF-8');
Trước và sau khi patch: