Sentinel Value và Chrome v8 HardenProtect vượt qua
Giá trị Sentinel là giá trị đặc biệt trong thuật toán, thường được sử dụng làm điều kiện dừng trong các thuật toán lặp hoặc đệ quy. Giá trị đặc biệt này được sử dụng rộng rãi trong mã nguồn Chrome. Gần đây có nghiên cứu cho thấy, việc rò rỉ một số đối tượng giá trị Sentinel có thể cho phép thực thi mã tùy ý trong sandbox của Chrome.
Bài viết này sẽ khám phá cách sử dụng đối tượng Uninitialized Oddball để vượt qua cơ chế HardenProtect của Chrome v8. Phương pháp này lần đầu tiên được thành viên Project0 đưa ra trong Issue1352549 và hiện vẫn có thể được sử dụng trong phiên bản V8 mới nhất, Google vẫn chưa có bản sửa lỗi cho vấn đề này.
Cần lưu ý rằng phương pháp này có tính tổng quát cao:
Issue1216437(CVE-2021-30551) đã lần đầu tiên cung cấp poc rò rỉ internal uninitialized oddball.
Issue1314616(CVE-2022-1486) cũng đã trực tiếp rò rỉ đối tượng UninitializedOddball.
Issue1352549( không có CVE) hiển thị đầy đủ chuỗi khai thác của phương pháp này.
Những trường hợp này cho thấy, phương pháp vượt qua này có thể ảnh hưởng đến nhiều phiên bản phần mềm. Đến thời điểm hiện tại, phần mềm như Skype vẫn chưa khắc phục được lỗ hổng này.
Giá trị Sentinel trong V8
Trong mã nguồn V8 định nghĩa một lượng lớn đối tượng nguyên sinh, bao gồm nhiều giá trị Sentinel khác nhau. Những đối tượng này được sắp xếp liền kề trong bộ nhớ. Một khi các đối tượng nguyên sinh không nên bị rò rỉ được lộ ra cho JavaScript, có thể thực hiện bất kỳ mã nào trong sandbox.
Để xác minh phương pháp này, chúng ta có thể sửa đổi hàm V8的%TheHole() để nó trả về đối tượng Uninitialized Oddball.
Vượt qua HardenType
Mã dưới đây cho thấy cách tận dụng đối tượng Oddball chưa được khởi tạo bị rò rỉ để thực hiện đọc tùy ý:
javascript
function read(obj, idx) {
return obj[idx];
}
let uninitialized_oddball = %GetUninitialized();
let ab = new ArrayBuffer(8);
let f64 = new Float64Array(ab);
let u32 = new Uint32Array(ab);
for (let i = 0; i < 0x10000; i++) {
đọc({prop: 1.1}, 0);
}
%Tối ưu hóa hàm trên cuộc gọi tiếp theo(đọc);
let val = read({prop: uninitialized_oddball}, 0x1234);
f64[0] = val;
console.log(u32[0].toString(16), u32[1].toString(16));
Mã lắp ráp của hàm read đã được tối ưu hóa cho thấy, hàm chỉ kiểm tra thuộc tính prop của obj, không kiểm tra giá trị của obj.prop mà đã trực tiếp tính toán độ dịch, dẫn đến nhầm lẫn kiểu và thực hiện đọc tùy ý.
Đề xuất giải pháp sửa chữa: Khi trả về các phần tử của mảng từ hàm đã tối ưu, hãy thêm kiểm tra đối với map của mảng, tránh tính toán độ lệch trực tiếp.
Cảnh báo PatchGap
Phương pháp này không chỉ ảnh hưởng đến lỗ hổng lịch sử mà còn có thể ảnh hưởng đến phần mềm hiện tại. Ví dụ, Skype hiện vẫn chưa khắc phục vấn đề này. Trên nền tảng x86, do thiếu nén địa chỉ, phạm vi đọc và ghi tùy ý lớn hơn.
Bản vá lần này không chỉ liên quan đến Vấn đề 1352549, mà còn làm giảm đáng kể độ khó khai thác các vấn đề tương tự như Vấn đề 1314616 và Vấn đề 1216437. Khuyến nghị các nhà sản xuất tiến hành kiểm tra toàn diện các lỗ hổng liên quan.
Tóm tắt
Bài viết này giới thiệu về phương pháp thực hiện đọc tùy ý V8 bằng cách sử dụng Uninitialized Oddball. Trong V8 còn có nhiều giá trị Sentinel khác, có thể tồn tại các mối nguy hiểm về bảo mật tương tự. Đề xuất nghiên cứu thêm:
Có thể thực hiện RCE V8 từ việc rò rỉ giá trị Sentinel khác không?
Thêm giá trị Sentinel vào biến của Fuzzer, khai thác các nguyên thủy khai thác mới.
Nhận thức về những rủi ro an ninh có thể phát sinh từ những vấn đề như vậy
Dù vấn đề này có được chính thức liệt kê là lỗ hổng bảo mật hay không, nó vẫn có thể rút ngắn đáng kể chu kỳ khai thác hoàn chỉnh của hacker. Hy vọng bài viết này có thể thu hút sự chú ý của các bên liên quan.
Trang này có thể chứa nội dung của bên thứ ba, được cung cấp chỉ nhằm mục đích thông tin (không phải là tuyên bố/bảo đảm) và không được coi là sự chứng thực cho quan điểm của Gate hoặc là lời khuyên về tài chính hoặc chuyên môn. Xem Tuyên bố từ chối trách nhiệm để biết chi tiết.
Chrome v8 HardenProtect vượt qua: sử dụng Sentinel Value để thực hiện mã tùy ý
Sentinel Value và Chrome v8 HardenProtect vượt qua
Giá trị Sentinel là giá trị đặc biệt trong thuật toán, thường được sử dụng làm điều kiện dừng trong các thuật toán lặp hoặc đệ quy. Giá trị đặc biệt này được sử dụng rộng rãi trong mã nguồn Chrome. Gần đây có nghiên cứu cho thấy, việc rò rỉ một số đối tượng giá trị Sentinel có thể cho phép thực thi mã tùy ý trong sandbox của Chrome.
Bài viết này sẽ khám phá cách sử dụng đối tượng Uninitialized Oddball để vượt qua cơ chế HardenProtect của Chrome v8. Phương pháp này lần đầu tiên được thành viên Project0 đưa ra trong Issue1352549 và hiện vẫn có thể được sử dụng trong phiên bản V8 mới nhất, Google vẫn chưa có bản sửa lỗi cho vấn đề này.
Cần lưu ý rằng phương pháp này có tính tổng quát cao:
Issue1216437(CVE-2021-30551) đã lần đầu tiên cung cấp poc rò rỉ internal uninitialized oddball.
Issue1314616(CVE-2022-1486) cũng đã trực tiếp rò rỉ đối tượng UninitializedOddball.
Issue1352549( không có CVE) hiển thị đầy đủ chuỗi khai thác của phương pháp này.
Những trường hợp này cho thấy, phương pháp vượt qua này có thể ảnh hưởng đến nhiều phiên bản phần mềm. Đến thời điểm hiện tại, phần mềm như Skype vẫn chưa khắc phục được lỗ hổng này.
Giá trị Sentinel trong V8
Trong mã nguồn V8 định nghĩa một lượng lớn đối tượng nguyên sinh, bao gồm nhiều giá trị Sentinel khác nhau. Những đối tượng này được sắp xếp liền kề trong bộ nhớ. Một khi các đối tượng nguyên sinh không nên bị rò rỉ được lộ ra cho JavaScript, có thể thực hiện bất kỳ mã nào trong sandbox.
Để xác minh phương pháp này, chúng ta có thể sửa đổi hàm V8的%TheHole() để nó trả về đối tượng Uninitialized Oddball.
Vượt qua HardenType
Mã dưới đây cho thấy cách tận dụng đối tượng Oddball chưa được khởi tạo bị rò rỉ để thực hiện đọc tùy ý:
javascript function read(obj, idx) { return obj[idx]; }
let uninitialized_oddball = %GetUninitialized(); let ab = new ArrayBuffer(8); let f64 = new Float64Array(ab); let u32 = new Uint32Array(ab);
for (let i = 0; i < 0x10000; i++) { đọc({prop: 1.1}, 0);
}
%Tối ưu hóa hàm trên cuộc gọi tiếp theo(đọc);
let val = read({prop: uninitialized_oddball}, 0x1234); f64[0] = val; console.log(u32[0].toString(16), u32[1].toString(16));
Mã lắp ráp của hàm read đã được tối ưu hóa cho thấy, hàm chỉ kiểm tra thuộc tính prop của obj, không kiểm tra giá trị của obj.prop mà đã trực tiếp tính toán độ dịch, dẫn đến nhầm lẫn kiểu và thực hiện đọc tùy ý.
Đề xuất giải pháp sửa chữa: Khi trả về các phần tử của mảng từ hàm đã tối ưu, hãy thêm kiểm tra đối với map của mảng, tránh tính toán độ lệch trực tiếp.
Cảnh báo PatchGap
Phương pháp này không chỉ ảnh hưởng đến lỗ hổng lịch sử mà còn có thể ảnh hưởng đến phần mềm hiện tại. Ví dụ, Skype hiện vẫn chưa khắc phục vấn đề này. Trên nền tảng x86, do thiếu nén địa chỉ, phạm vi đọc và ghi tùy ý lớn hơn.
Bản vá lần này không chỉ liên quan đến Vấn đề 1352549, mà còn làm giảm đáng kể độ khó khai thác các vấn đề tương tự như Vấn đề 1314616 và Vấn đề 1216437. Khuyến nghị các nhà sản xuất tiến hành kiểm tra toàn diện các lỗ hổng liên quan.
Tóm tắt
Bài viết này giới thiệu về phương pháp thực hiện đọc tùy ý V8 bằng cách sử dụng Uninitialized Oddball. Trong V8 còn có nhiều giá trị Sentinel khác, có thể tồn tại các mối nguy hiểm về bảo mật tương tự. Đề xuất nghiên cứu thêm:
Dù vấn đề này có được chính thức liệt kê là lỗ hổng bảo mật hay không, nó vẫn có thể rút ngắn đáng kể chu kỳ khai thác hoàn chỉnh của hacker. Hy vọng bài viết này có thể thu hút sự chú ý của các bên liên quan.