Chào các bạn, cũng lâu lâu rồi mình chưa viết gì lên cái blog này nhỉ. Và trong khoảng thời gian lâu lâu đó thì cuối cùng mình cũng đã báo cáo thành công lỗ hổng đầu tiên và nhận được phần thưởng từ Facebook (Yeahhhh). Trong niềm hân hoan vui sướng ấy, mình quyết định viết ngay bài writeup này để chia sẻ với mọi người rằng mình đã tìm ra lỗ hổng như thế nào.

Ờm, bắt đầu câu chuyện ở đâu nhỉ, vào một ngày đẹp trời, à nhầm, một ngày buồn chán, theo thói quen là cứ buồn chán thì mình sẽ kiếm hàng gì đó để chọc thôi. Và lần này mình bắt đầu với việc chọn API trên app mobile của Facebook để debug, chỉ để xem rằng liệu mình có thể tìm ra nguồn dữ liệu mới và hay ho nào từ bộ API của Facebook hay không. Cơ mà việc đọc đi đọc lại bộ API này hàng chục lần khiến mình cảm thấy nhàm chán (trước đó mình cũng từng làm nhiều rồi). Vì vậy nên ngay sau đó mình quyết định chuyển hướng sang debug một hệ thống API cực kì cũ và khó nhằn của Facebook: FQL.

Vấn đề của FQL đó là nó quá cũ và đã bị Facebook khai tử (trên lý thuyết) từ nhiều năm trước và tài liệu của bộ này đã bị Facebook xóa sạch bong, gần như không còn dấu vết. Mình nghĩ thậm chí hầu hết người dùng và kể cả dev đều không biết tới hệ thống API này nếu như không dùng Facebook từ tầm 5-7 năm về trước. Trước đây, cách duy nhất mà mình còn có thể đọc tài liệu về nó là bằng cách bỏ link bộ tài liệu cũ vào Wayback Machine, nhưng nó không ổn định, có khá nhiều bản ghi bị hỏng và trang thì cứ toàn refresh khi mình đang đọc, rất khó chịu. Mình trung thành với FBDevWiki từ khi biết tới trang này, dù cho có một số trường bị thiếu so với bản tài liệu gốc nhưng vẫn đủ để mình nghiên cứu FQL một cách cơ bản.

Với mình, để báo cáo thành công một lỗ hổng trên hệ thống FQL, mình cần tìm ra cách để đọc hoặc sửa một phần dữ liệu nào đó mà về lý thì mình không được làm. Nhưng vì FQL là một hệ thống thiên về truy xuất dữ liệu hơn là thay đổi dữ liệu, nên mình quyết định sẽ chỉ tập trung vào tìm cách truy xuất dữ liệu ẩn mà có thể người ta đã bỏ quên nó trong lúc phát triển hệ thống.

Để mở rộng thêm khả năng tìm kiếm những phần dữ liệu mới, mình quyết định không nghiên cứu thêm FBDevWiki vì dữ liệu trên trang này cũng chỉ tương đương với lượng thông tin của tài liệu chính thống đã bị xóa. Nơi tiếp theo mình "chọn mặt gửi vàng" để kiếm lượng thông tin này đó chính là Github. Sau một hồi tìm kiếm trên Github (mà thậm chí mình còn không nhớ từ khóa là gì), thì mình tìm thấy cái này

Một "kho" chứa mã nguồn của app Facebook đã được dịch ngược từ 7 năm trước, tuyệt vời!

Trong quá trình phân tích "kho" mã nguồn này, mình tìm thấy một thư mục chứa nhiều file mã nguồn Java có nhiệm vụ gọi API truy xuất/sửa đổi dữ liệu từ server. Và phần mã nguồn này xử lý dựa trên FQL!

Tiếp theo trong quá trình phân tích sâu hơn vào những file mà nguồn ấy, mình tìm thấy thứ này:

Một trường dữ liệu lạ tên là mobile_app_data

Thật ra mình tìm thấy nhiều nhiều trường hơn thế này, và đã phải thử rất nhiều để xem cái nào có dữ liệu và cái nào không, nhưng trong phạm vi của 1 bài writeup nho nhỏ nên mình sẽ chỉ đi thẳng vào vấn đề thôi.

Sau đó, mình viết một đoạn FQL query *bí mật* để xem liệu trường mobile_app_data này sẽ trả về dữ liệu gì từ server.

Và đây là dữ liệu mình nhận được:

Nhìn qua, nếu là một người dùng không có kinh nghiệm thì bạn chỉ thấy một đống dữ liệu trông có vẻ phức tạp và vô nghĩa. Nhưng bằng kinh nghiệm nghiên cứu của mình, để mình giải thích cho bạn những dữ liệu này là gì và tại sao nó lại có rủi ro nhé!

Nói chung, có 3 trường dữ liệu đã bị rò rỉ:

  • is_installed: Trường dữ liệu này cho biết người dùng đang cài ứng dụng (Facebook) gì trên điện thoại của họ, ví dụ Facebook for Android, Facebook for iOS,...Điều này giúp cho kẻ tấn công biết được người dùng có những thiết bị gì, vì nếu bạn dùng app Facebook for iOS, thì nhiều khả năng bạn có từng dùng một thiết bị iOS, điều tương tự xảy ra với Android, Blackberry,...
  • last_used: Trường dữ liệu này cho biết lần cuối người dùng sử dụng ứng dụng là khi nào. Điều này giúp cho kẻ tấn công biết được tần suất sử dụng ứng dụng của người dùng.
  • has_push: Cho biết người dùng có bật thông báo của ứng dụng trên thiết bị đó không.

Sâu hơn, trong 3 trường dữ liệu này, thay vì nêu thẳng tên của ứng dụng, thì dữ liệu trả về lại là JSON object với key là id của ứng dụng và giá trị là UNIX timestamp hoặc boolean. Để lấy tên của ứng dụng từ id, ta dùng graph API query sau:

https://graph.facebook.com/<app_id>?fields=name&access_token=<access_token>

Sau khi nghiên cứu thêm thì mình phát hiện ra chỉ có thể gây rò rỉ dữ liệu từ những người trong danh sách bạn. Nhưng vì vẫn tính là gây rò rỉ thông tin nên mình quyết định gửi báo cáo lên Facebook.

Timeline quá trình báo cáo như sau:

  • 18/6/2019: Báo cáo được gửi đi
  • 20/6/2019: Phản hồi từ Facebook, thông báo rằng họ đã nhận thấy vấn đề giống như mô tả trong báo cáo
  • 21/6/2019: Phản hồi từ Facebook, thông báo rằng họ đang chuyển thông tin qua cho team sản phẩm để nghiên cứu thêm
  • 20/7/2019: Hồi âm từ mình, yêu cầu cập nhật thông tin quá trình nghiên cứu
  • 24/7/2019: Phản hồi từ Facebook nói rằng họ đã khắc phục vấn đề, yêu cầu mình xác nhận lại
  • 24/7/2019: Hồi âm từ mình, xác nhận rằng vấn đề đã được khắc phục
  • 26/7/2019: Phản hồi từ Facebook với phần thưởng là $750
  • 30/7/2019: Tên mình đã xuất hiện trên Thanks page