Chrome zero-day: “Khai thác này là tự nhiên”, vì vậy hãy kiểm tra phiên bản của bạn ngay bây giờ

Chrome zero-day: “Khai thác này là tự nhiên”, vì vậy hãy kiểm tra phiên bản của bạn ngay bây giờ

Nút nguồn: 2704382

Bản cập nhật Chrome mới nhất của Google đã hết và lần này công ty đã không băm nhỏ lời nói của nó về một trong hai bản vá bảo mật bao gồm:

Google biết rằng một khai thác cho CVE-2023-3079 tồn tại trong tự nhiên.

Không có sự phân biệt hai cấp độ, như chúng ta thường thấy từ Google trước đây, để nói rằng công ty “biết về các báo cáo” về một vụ khai thác.

Lần này, đó là “chúng tôi tự nhận thức được tất cả”, điều này thậm chí còn được dịch một cách thẳng thắn hơn thành “chúng tôi biết rằng kẻ gian đang lạm dụng điều này khi chúng tôi nói”, vì báo cáo lỗi đến trực tiếp từ Nhóm nghiên cứu mối đe dọa của chính Google.

Như thường lệ, điều này ngụ ý rằng Google đang điều tra một cuộc tấn công đang hoạt động (dù là nhằm vào chính Google hay một tổ chức bên ngoài nào đó mà chúng tôi không biết) trong đó Chrome đã bị lỗ hổng bảo mật chưa biết trước đó xử lý.

Lỗi này được mô tả đơn giản là: Gõ nhầm lẫn trong V8. (Có thể hiểu được, Google không nói nhiều hơn thế ở giai đoạn này.)

Như chúng tôi đã giải thích trước đây, một loại nhầm lẫn lỗi xảy ra khi bạn cung cấp cho chương trình một đoạn dữ liệu mà nó phải phân tích cú pháp, xác thực, xử lý và hành động theo một cách nào đó…

…nhưng sau đó bạn xoay sở để đánh lừa chương trình diễn giải dữ liệu theo một cách khác, trái phép, không hợp lệ và có khả năng gây nguy hiểm.

Loại nhầm lẫn nguy hiểm giải thích

Hãy tưởng tượng rằng bạn đang viết một chương trình bằng C. (Không quan trọng bạn có biết C hay không, bạn vẫn có thể làm theo.)

Trong C, bạn thường khai báo các biến riêng lẻ, do đó không chỉ dành bộ nhớ nơi chúng có thể được lưu trữ mà còn báo hiệu cho chương trình cách các biến đó được sử dụng.

Ví dụ:

 dài dài int JulianDayNumber; char đã ký * Tên khách hàng;

Khai báo biến đầu tiên dự trữ 64 bit để lưu trữ một giá trị số nguyên cũ đơn giản biểu thị số ngày thiên văn. (Trong trường hợp bạn đang thắc mắc, chiều nay là JDN 23157 – Ngày Julian bắt đầu vào buổi trưa, không phải nửa đêm, vì các nhà thiên văn học thường làm việc vào ban đêm, với nửa đêm là giữa ngày làm việc của họ.)

Thứ hai dự trữ 64 bit để lưu trữ địa chỉ bộ nhớ nơi có thể tìm thấy chuỗi văn bản tên của khách hàng.

Như bạn có thể tưởng tượng, tốt hơn hết là bạn không nên trộn lẫn hai giá trị này, bởi vì một số hợp lý và an toàn để sử dụng làm số ngày, chẳng hạn như 23157, gần như chắc chắn sẽ không an toàn khi sử dụng làm địa chỉ bộ nhớ.

Như bạn có thể thấy từ kết xuất bộ nhớ này của một chương trình Windows đang chạy, địa chỉ bộ nhớ thấp nhất được phân bổ để sử dụng bắt đầu tại 0x00370000, là 3,604,480 ở dạng thập phân, lớn hơn nhiều so với bất kỳ số ngày hợp lý nào.

Các địa chỉ bộ nhớ thực được Windows sử dụng thay đổi ngẫu nhiên theo thời gian, để làm cho bố cục bộ nhớ của bạn khó đoán hơn đối với kẻ gian, vì vậy nếu bạn chạy cùng một chương trình, bạn sẽ nhận được các giá trị, tuy nhiên chúng sẽ giống nhau:

Và (mặc dù nó nằm ở dưới cùng của hình trên) địa chỉ bộ nhớ của phần dữ liệu người dùng thời gian chạy khi chương trình này chạy từ 0x01130000 đến 0x01134FFF, đại diện cho phạm vi ngày không chắc chắn từ ngày 22 tháng 44631 năm 16 đến ngày 44687 tháng XNUMX năm XNUMX.

Thật vậy, nếu bạn cố trộn lẫn hai biến đó với nhau, trình biên dịch sẽ cố gắng cảnh báo bạn, chẳng hạn như thế này:

 JulianDayNumber = Tên khách hàng; Tên khách hàng = JulianDayNumber; cảnh báo: phép gán tạo số nguyên từ con trỏ mà không ép kiểu cảnh báo: phép gán tạo con trỏ từ số nguyên mà không ép kiểu

Bây giờ, nếu bạn đã từng lập trình bằng C, bạn sẽ biết rằng để thuận tiện, bạn có thể khai báo các biến với nhiều cách hiểu khác nhau bằng cách sử dụng union từ khóa, như thế này:

 công đoàn { long long int JulianDayNumer; char đã ký * Tên khách hàng; } dữ liệu;

Bây giờ bạn có thể tham chiếu chính xác cùng một biến trong bộ nhớ theo hai cách khác nhau.

Nếu bạn viết data.JulianDayNumber, bạn diễn giải một cách kỳ diệu dữ liệu được lưu trữ dưới dạng số nguyên, nhưng viết data.CustomerName cho trình biên dịch biết bạn đang tham chiếu đến một địa chỉ bộ nhớ, mặc dù bạn đang truy cập cùng một dữ liệu được lưu trữ.

Điều bạn đang làm, ít nhiều, đang thừa nhận với trình biên dịch rằng đôi khi bạn sẽ coi dữ liệu bạn có là ngày tháng và đôi khi là địa chỉ bộ nhớ, và điều đó bạn chịu trách nhiệm ghi nhớ cách giải thích nào áp dụng vào thời điểm nào trong mã.

Bạn có thể quyết định có một biến thứ hai, được gọi là tag (thường là một số nguyên) để đi cùng với union để theo dõi loại dữ liệu bạn đang làm việc ngay bây giờ, ví dụ:

 cấu trúc { thẻ int; công đoàn { long long int JulianDayNumer; char đã ký * Tên khách hàng; } dữ liệu; } giá trị;

Bạn có thể quyết định rằng khi value.tag được thiết lập để 0, dữ liệu chưa được khởi tạo để sử dụng, 1 có nghĩa là bạn đang lưu trữ một ngày, 2 có nghĩa là đó là địa chỉ bộ nhớ và bất kỳ thứ gì khác biểu thị lỗi.

Chà, tốt hơn hết là bạn đừng để bất kỳ ai khác làm phiền điều đó value.tag cài đặt, hoặc chương trình của bạn có thể kết thúc hoạt động sai đáng kể.

Một ví dụ đáng lo ngại hơn có thể giống như thế này:

 cấu trúc { thẻ int; // 1 = hash, 2 = con trỏ hàm union { unsign char hash[16]; // lưu trữ một hàm băm ngẫu nhiên struct { void* openfunc; // hoặc hai void* closefunc được xác thực cẩn thận; // con trỏ mã để thực hiện sau } xác thực; } } giá trị;

Bây giờ, chúng tôi đang làm quá tải cùng một khối bộ nhớ để đôi khi chúng tôi có thể sử dụng nó để lưu trữ hàm băm 16 byte và đôi khi để lưu trữ hai con trỏ 8 byte tới các hàm mà chương trình của chúng tôi sẽ gọi sau này.

Rõ ràng, khi value.tag == 1, chúng tôi rất sẵn lòng để phần mềm của mình lưu trữ bất kỳ chuỗi 16 byte nào vào bộ nhớ được phân bổ cho liên kết, bởi vì các giá trị băm là giả ngẫu nhiên, do đó, mọi tập hợp byte đều có khả năng như nhau.

Nhưng khi value.tag == 2, mã của chúng tôi cần phải cực kỳ cẩn thận để không cho phép người dùng cung cấp các địa chỉ hàm không xác thực, không đáng tin cậy, không xác định để thực thi sau này.

Bây giờ, hãy tưởng tượng rằng bạn có thể gửi một giá trị cho mã này trong khi thẻ được đặt thành 1, vì vậy mã không được kiểm tra và xác thực…

…nhưng sau đó, ngay trước khi chương trình thực sự sử dụng giá trị được lưu trữ, bạn có thể đánh lừa mã để chuyển thẻ thành 2.

Sau đó, mã sẽ chấp nhận các địa chỉ hàm chưa được xác thực của bạn là “đã biết và đã được xác minh là an toàn” (mặc dù chúng không phải như vậy) và sẽ gửi việc thực thi chương trình một cách đáng tin cậy đến một vị trí giả mạo trong bộ nhớ mà bạn đã lén lút chọn trước.

Và đó là những gì xảy ra trong một lỗi nhầm lẫn kiểu, mặc dù sử dụng một ví dụ giả định và đơn giản hóa,

Bộ nhớ sẽ an toàn để sử dụng nếu được xử lý theo một cách độc hại được gửi đến chương trình để xử lý theo cách thay thế, không an toàn.

Phải làm gì?

Đảm bảo bạn có phiên bản Chrome hoặc Chromium mới nhất.

Bạn muốn Chrome 114.0.5735.106 hoặc mới hơn trên Mac và Linux, và 114.0.5735.110 hoặc mới hơn trên Windows.

Microsoft Edge, dựa trên Chromium, cũng bị ảnh hưởng bởi lỗi này.

Microsoft cho đến nay [2023-06-06T16:25:00Z] lưu ý rằng

Microsoft nhận thức được các khai thác gần đây tồn tại trong tự nhiên. Chúng tôi đang tích cực làm việc để phát hành một bản vá bảo mật.

Edge hiện đang ở phiên bản 114.0.1823.37, vì vậy mọi thứ đều được đánh số muộn hơn thế nên bao gồm các bản vá lỗi CVE-2023-3079 của Microsoft.

Để kiểm tra phiên bản của bạn và buộc cập nhật nếu có phiên bản bạn chưa nhận được:

  • Google Chrome Menu ba chấm (⋮) > Trợ giúp > Giới thiệu về Chrome.
  • MicrosoftEdge. Cài đặt và hơn thế nữa (…) > Giúp đỡ và phản hồi > Giới thiệu về Microsoft Edge.

Không có gì.


Dấu thời gian:

Thêm từ An ninh trần trụi