- vừa được xem lúc

# Prototype Pollution attack (phần 3)

0 0 3

Người đăng: Viblo Security

Theo Viblo Asia

IV. Phân tích và khai thác các kỹ thuật phát hiện, tấn công Server-side - Prototype Pollution

1. Điểm khác biệt với lỗ hổng phía client

Khác với lỗ hổng xảy ra ở phía client, Server-side - Prototype Pollution chỉ các lỗ hổng xuất hiện với các dữ liệu hoạt động tại máy chủ. Mặc dù JavaScript ban đầu là một ngôn ngữ chuyên sinh ra với mục đích lập trình cho hệ thống front end, nhưng theo sự thay đổi của thời gian, ngôn ngữ JavaScript nói chung được các nhà phát triển ứng dụng sử dụng rộng rãi để xây dựng máy chủ, API cũng như các hệ thống back end khác. Bạn đọc có thể đọc thêm cuốn sách JavaScript from Frontend to Backend.

2. Khó khăn

Khi kiểm tra và khai thác lỗ hổng Prototype Pollution xảy ra ở phía server, chúng ta sẽ phải đối đầu với một số khó khăn, vấn đề phát sinh cần giải quyết.

  • Không có mã nguồn: Tất nhiên, ở phía server thì các lỗ hổng sẽ không hề liên quan tới các tệp .js mà chúng ta có thể đọc tùy ý ở trang web. Có thể coi việc kiểm tra dạng lỗ hổng Prototype Pollution dạng server-side giống như một công cuộc kiểm thử "blackbox".
  • Không có dấu hiệu rõ ràng: Với client-side pollution, chúng ta có thể dễ dàng kiểm tra các thuộc tính đã bị lây nhiễm chưa thông qua Object.prototype trong console tool. Với server-side, các giá trị thuộc tính thường không hiển thị trong giao diện (một số trường hợp reflect trong response có thể dễ dàng kiểm tra), chúng ta chỉ có thể cố gắng tìm kiếm các dấu hiệu để thực hiện nhận biết.
  • Ảnh hưởng tới hệ thống: Một số thuộc tính bị thay đổi trong môi trường server-side có thể ảnh hưởng tới luồng hoạt động của chương trình, dẫn đến hệ thống gặp lỗi không mong muốn.
  • Khó khôi phục dữ liệu: Việc không thể biết giá trị ban đầu của thuộc tính sau khi thực hiện lây nhiễm thành công dẫn đến khó khôi phục lại thuộc tính đó trở về giá trị lúc trước, gây ảnh hưởng tới toàn bộ hệ thống.

Bên cạnh việc tìm kiếm và xác nhận lỗ hổng, chúng ta còn phải chú ý tránh các tác động xấu tới server. Hãy cùng xem xét một số phương pháp độc đáo giúp chúng ta phát hiện dạng lỗ hổng này mà vẫn đảm bảo hoạt động bình thường của hệ thống trong các phần tiếp theo.

3. Phát hiện lỗ hổng trong trường hợp dữ liệu được hiển thị trong response

Chắc hẳn với các bạn trong ngành Công nghệ thông tin nói chung đều đã rất quen thuộc với vòng lặp for. Xem xét cấu trúc for...in trong ngôn ngữ JavaScript để liệt kê tất cả thuộc tính trong một đối tượng.

const testObject = {'a': 1, 'b': 2};
for (propertyKey in testObject) { console.log(propertyKey);
}
// Output: a b

Điều đặc biệt là vòng lặp này sẽ liệt kê cả các thuộc tính mà đối tượng kế thừa từ nguyên mẫu (đối tượng không chứa thuộc tính đó). Thật vậy, bổ xung thuộc tính test vào Object.prototype:

const testObject = {'a': 1, 'b': 2};
Object.prototype.test = '3';
for (propertyKey in testObject) { console.log(propertyKey);
}

Kết quả:

image.png

Như vậy, khi các lập trình viên sử dụng vòng lặp for...in trong quá trình xây dựng chức năng hiển thị các thuộc tính của đối tượng, sẽ "vô tình" giúp kẻ tấn công có thể kiểm tra lỗ hổng một cách dễ dàng hơn. Ví dụ một chương trình như sau:


function getUserData(data) { const userData = {}; for (const key in data) { console.log(key) userData[key] = data[key]; } return userData;
} // ... // Reflect the data in the response
res.json({ Message: "Profile updated successfully", UserData: getUserData(dataProfile),
});

Bài lab Privilege escalation via server-side prototype pollution minh họa cho sự sai sót này.

Đăng nhập ứng dụng, sử dụng chức năng update thông tin:

image.png

image.png

Ứng dụng gửi dữ liệu tới server bằng JSON và response hiển thị các thông tin của người dùng wiener. Chúng ta có thể thêm tùy ý cặp key:value

image.png

Tải lại trang và submit các lần sau nhận thấy cặp test:viblo vẫn tồn tại, thuộc tính mới dường như được thêm và lưu trữ cố định vào object trong server.

image.png

Đồng thời trong response có thuộc tính đặc biết isAdmin (trong giao diện sẽ không hiển thị):

image.png

Như vậy, ý tưởng rất tự nhiên là sử dụng kỹ thuật tấn công prototype pollution nhằm thay đổi thuộc tính isAdmin thành true:

image.png

Tải lại trang web, thành công trở thành vai trò administrator.

image.png

Như vậy, khi sử dụng cấu trúc for...in trong các chức năng hiển thị thuộc tính đối tượng, chúng ta nên thêm một bước kiểm tra đối tượng có thuộc tính đang xét không data.hasOwnProperty(key) nhằm tránh việc ứng dụng hiển thị các thuộc tính kế thừa từ prototype. Ví dụ:

function getUserData(data) { const userData = {}; for (const key in data) { if (data.hasOwnProperty(key)) { userData[key] = data[key]; } } return userData;
}

Các phần tiếp theo chúng ta sẽ cùng tìm hiểu về một số phương pháp phát hiện lỗ hổng trong trường hợp trang web không trả về các dữ liệu input từ người dùng.

4. Sử dụng một số thuộc tính trong thư viện qs thực hiện kiểm tra

4.1. Thuộc tính parameterLimit

Trong Express, body-parser là một middleware được sử dụng để phân tích (parse) dữ liệu trong request được gửi từ client và đưa vào thuộc tính req.body để sử dụng trong quá trình xử lý. Chú ý tùy chọn parameterLimit, theo https://github.com/expressjs/body-parser#parameterLimit:

The parameterLimit option controls the maximum number of parameters that are allowed in the URL-encoded data. If a request contains more parameters than this value, a 413 will be returned to the client. Defaults to 1000.

Có thể hiểu thuộc tính parameterLimit được sử dụng để giới hạn số lượng tham số (parameters) mà Express sẽ phân tích trong request. Đặc biệt, khi ứng dụng sử dụng thư viện qs, ví dụ trong phiên bản v6.4.0:

options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : defaults.parameterLimit;

Chương trình kiểm tra thuộc tính parameterLimit nếu có kiểu number sẽ sử dụng luôn giá trị đó làm số lượng tham số giới hạn, ngược lại để giá trị mặc định 10001000. Bởi vậy, nếu ứng dụng tồn tại lỗ hổng Prototype pollution phía server, chúng ta có thể kiểm tra bằng cách thay đổi thuộc tính parameterLimit, và quan sát response với số lượng tham số trong request vượt giới hạn đó.

Ví dụ một chương trình luôn trả về giá trị tham số test do người dùng nhập từ URL, nếu không tìm thấy sẽ trả về undefined:

image.png

Cố gắng thay đổi giá trị thuộc tính parameterLimit với payload:

"__proto__": { "parameterLimit": 1
}

Nếu lỗ hổng tồn tại, chúng ta chỉ có thể sử dụng một tham số duy nhất:

image.png

4.2. Thuộc tính ignoreQueryPrefix

Thông thường, khi chúng ta truyền tham số dạng ??test= hệ thống sẽ không thể phân tích cú pháp hợp lệ, dẫn đến giá trị test không được tiếp nhận.

image.png

Tuy nhiên, trong thư viện qs chứa tùy chọn ignoreQueryPrefix nếu có giá trị true sẽ cho phép ứng dụng chấp nhận kiểu truy vấn như trên. Tham khảo thêm tại https://github.com/ljharb/qs/blob/main/dist/qs.js#L270

image.png

Nếu thay đổi được giá trị thuộc tính ignoreQueryPrefix:

"__proto__": { "ignoreQueryPrefix": true
}

Kiểm tra lại trang web, kết quả cho thấy tham số đã được chấp nhận:

image.png

4.3. Thuộc tính allowDots

Tương tự với ignoreQueryPrefix, tùy chọn allowDots cho phép tham số sử dụng dấu chấm . trở thành vai trò như một object:

image.png Nguồn: https://portswigger.net/

Bạn đọc tham khảo thêm mã nguồn tại: https://github.com/ljharb/qs/blob/main/dist/qs.js#L259

image.png

Các tài liệu tham khảo

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tổng quan một số kỹ thuật khai thác lỗ hổng bảo mật Web (P1)

Trong thời đại công nghệ phát triển hiện nay, việc đảm bảo an ninh thông tin trên không gian mạng đang là vấn đề dành được nhiều sự quan tâm. Nguy cơ mất an toàn thông tin đang là mối đe dọa lớn và ngày càng gia tăng đối với an ninh quốc gia.

0 0 83

- vừa được xem lúc

[Secure coding - Part 3] Là developer cần làm gì để ứng dụng của mình an toàn và bảo mật hơn?

Tổng quan về vấn đề bảo mật. Đây là nội dung nối tiếp trong phần 1.

0 0 50

- vừa được xem lúc

[Secure coding - Part 4] Là developer cần làm gì để ứng dụng của mình an toàn và bảo mật hơn?

Tổng quan về vấn đề bảo mật. Trở lại với chuỗi bài viết về hướng dẫn lập trình an toàn cho lập trình viên, bài viết thứ tư trong series's post: Secure coding for developers sẽ tiếp tục với nội dung về

0 0 67

- vừa được xem lúc

[Secure coding - Part 5] Là developer cần làm gì để ứng dụng của mình an toàn và bảo mật hơn?

Tổng quan về vấn đề bảo mật. Trở lại với chuỗi bài viết về hướng dẫn lập trình an toàn cho lập trình viên, bài viết thứ tư trong series's post: Secure coding for developers sẽ tiếp tục với nội dung về

0 0 25

- vừa được xem lúc

IDOR là gì và ứng dụng bạn code có bị lỗi IDOR không?

Tổng quan. Nếu bạn là một pentester thì có thể đã quen với lỗ hổng bảo mật IDOR.

0 0 163

- vừa được xem lúc

Lỗ hổng Business logic trong bảo mật ứng dụng website

Tổng quan. Các lỗ hổng bảo mật website như SQL Injection, UnBroken Access Control, Unrestricted File Upload, XSS chắc không còn xa xạ với nhiều người làm bảo mật hay lập trình viên.

0 0 23