20/07/2019, 09:58

Tấn công Prototype Pollution trên các ứng dụng NodeJS

Tấn công Prototype Pollution giống như cái tên đã gợi ý phần nào, là hình thức tấn công (thêm/sửa/xoá thuộc tính) vào prototype của Object trong trong Javascript dẫn đến sai khác logic, nhiều khi dẫn đến việc thực thi những đoạn code tuỳ ý trên hệ thống (Remote Code Excution – RCE). ...

Tấn công Prototype Pollution giống như cái tên đã gợi ý phần nào, là hình thức tấn công (thêm/sửa/xoá thuộc tính) vào prototype của Object trong trong Javascript dẫn đến sai khác logic, nhiều khi dẫn đến việc thực thi những đoạn code tuỳ ý trên hệ thống (Remote Code Excution – RCE). Lỗ hổng này đã được phát hiện ra từ năm 2018 trên một số thư viện Javascript hay dùng là JQuery và đến gần đây lại tiếp tục phát hiện ra lỗ hổng này trên thư viện Lodash, một trong những thư viện phổ biến. Chúng ta cùng thử tìm hiểu xem hình thức tấn công này như thế nào nhé.

Đối tượng trong Javascript

Trước hết, ta cần hiểu qua về Object trong javascript. Object đơn giản là tập hợp của các cặp khoá và giá trị, thường được gọi là các property (thuộc tính) của đối tượng đó. Ví dụ:

Sử dụng {} giúp chúng ta khai báo một đối tượng mới và gán cho nó các thuộc tính name và user_id tương ứng. Sau khi khai báo xong, ta có thể truy cập đến các thuộc tính này như bình thường. Tuy nhiên, bên trong của object user không chỉ có những thuộc tính ta đã gán mà còn có rất nhiều thông tin khác như ở câu lệnh cuối cùng chỉ ra. Vậy những thuộc tính này đến từ đâu?

Trong Javascript, Object là đối tượng cơ bản, là khuôn mẫu cho tất các đối tượng được tạo mới. Ta hoàn toàn có thể tạo một đối tượng rỗng bằng cách truyền null vào Object.create tuy nhiên, đối tượng mới được tạo ra cũng sẽ có kiểu tương ứng với tham số truyền và kế thừa tất cả các thuộc tính cơ bản.

Hàm/Lớp trong Javascript

Trong Javascript, khái niệm của class (lớp) và function (hàm) khá liên quan đến nhau (function bản thân nó đóng vai trò như là constructor (hàm khởi tạo) cho class và bản chất thực tế thì ko có khái niệm “class” trong javascript). Chúng ta cùng xem VD sau:

Trong ví dụ ở trên, chúng ta đã định nghĩa một hàm tên là person và khởi tại 2 đối tượng tên person1 và person2. Nếu chúng ta nhìn vào thuộc tính của những đối tượng mới được tạo, chúng ta có thể để ý thấy 2 điều:

  • Khi hàm được tạo, javascript engine đã bao gồm thuộc tính prototype vào trong hàm. Thuộc tính prototype này là một đối tượng (được gọi là prototype object)) có một thuộc tính constructor mặc định chỉ về hàm mà chứa thuộc tính prototype này.
  • Khi đối tượng được tạo, javascript engine sẽ thêm một thuộc tính __proto__ vào trong đội tượng mới được tạo ra, thuộc tính này chỉ tới prototype object của hàm constructor. Nói một cách ngắn gọn, object.__proto__ chỉ đến function.prototype.

Constructor là gì?

  • Constructor là một thuộc tính đặc biệt trả về hàm đã được dùng để tạo ra đối tượng đó. Prototype object có constructor chỉ đến hàm đó và constructor của constructor sẽ là hàm constructor toàn cục (global). Ví dụ: