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

NoSQL injection (phần 3)

0 0 3

Người đăng: Viblo Security

Theo Viblo Asia

V. Trích xuất dữ liệu hiệu quả hơn

Trong bài viết trước chúng ta đã tìm hiểu về phương pháp sử dụng tấn công brute force kết hợp toán tử $regex tìm ra từng ký tự của dữ liệu trong bảng. Có thể kết hợp thuật toán tìm kiếm Binary search để tối ưu thời gian tìm kiếm mật khẩu, chương trình minh họa:

# A function that returns True if the regex passes
def test_password(regex): data = { "username": "admin", "password": { "$regex": regex } } r = requests.post(URL, json=data, allow_redirects=False) return not 'Login Failed' in r.text # Binary Search algorithm
def search_once(test_function, prefix=""): min = 0 max = 127 while min <= max: mid = (min + max) // 2 if test_function(fr'^{re.escape(prefix)}[\x{mid:02x}-\x7f]'): min = mid + 1 else: max = mid - 1 return chr(max) # Keep searching until whole string found
def search(test_function): found = "" while True: found += search_once(test_function, prefix=found) print(found) if test_function(fr'^{found}$'): return found password = search(test_password)
print(password)

Trong phần này, chúng ta tiếp tục xem xét một số cách trích xuất dữ liệu hiệu quả hơn.

Một số toán tử và hàm cho phép thực thi một phần Javascript code, chẳng hạn toán tử $where, hàm mapReduce(), eval() trong MongoDB. Khi ứng dụng triển khai chương trình sử dụng chúng theo cách không an toàn sẽ có thể trở thành điểm tấn công của attacker.

1. Ví dụ sử dụng sai toán tử $where trong MongoDB

$where cho phép chạy các đoạn mã JavaScript tùy chỉnh để lọc tài liệu. Đây là một lựa chọn hiệu quả khi truy vấn cần điều kiện phức tạp, khó xử lý qua các toán tử truy vấn thông thường.

Ví dụ: Lọc các tài liệu có trường age lớn hơn height (tuổi lớn hơn chiều cao):

db.collection.find({ $where: function() { return this.age > this.height; }
});

Trong ví dụ này, $where sử dụng một hàm JavaScript để so sánh ageheight trong mỗi tài liệu, chỉ trả về các tài liệu thỏa mãn điều kiện.

Khi ứng dụng đưa trực tiếp dữ liệu đầu vào từ người dùng vào truy vấn $where, sẽ dẫn đến lỗ hổng NoSQL injection. Xét đoạn code với truy vấn chứa lỗi sau:

db.users.find({ $where: function() { return this.username === userInput; }
});

Truy vấn tìm kiếm người dùng theo tên, nhưng không thực hiện sàng lọc input từ người dùng. Attacker có thể truyền vào một đoạn mã JavaScript để truy xuất tất cả dữ liệu trong collection users, chẳng hạn với payload:

userInput = "''; return true; //"

Truy vấn trở thành:

db.users.find({ $where: function() { return this.username === ''; return true; // }
});

Kết quả $where sẽ trả về tất cả các tài liệu trong users vì điều kiện return true; luôn đúng, giúp attacker lấy toàn bộ dữ liệu mà không cần biết tên người dùng cụ thể.

2. Phân tích lab Exploiting NoSQL injection to extract data

Chúng ta sẽ cùng phân tích bài lab Exploiting NoSQL injection to extract data để hiểu sâu về kỹ thuật trích xuất dữ liệu nâng cao này. Mục đích của bài lab cần lấy được mật khẩu của người dùng administrator. Tài khoản người dùng thường đã được cung cấp wiener:peter.

Sau khi đăng nhập với người dùng wiener, ứng dụng dẫn tới trang chứa thông tin người dùng, bao gồm username, role, email:

image.png

Quan sát lịch sử các request và response từ proxy BurpSuite, có thể thấy request với endpoint /user/lookup, đây chính là API lấy thông tin người dùng dựa vào tham số user:

image.png

Có thể thấy ngay API này chứa lỗi IDOR cho phép xem thông tin người dùng bất kỳ, chẳng hạn administrator:

image.png

Để kiểm tra vị trí này tồn tại lỗ hổng NoSQL injection hay không, chúng ta có thể sử dụng ký tự + trong JavaScript kiểm tra cộng chuỗi 'administrato'+'r', payload ?user=administrato'%2b'r (URL encode), response trả về thành công:

image.png

Để chắc chắn hơn, kiểm tra thêm với:

Payload administrator' && '1'=='2 không trả về bản ghi nào:

image.png

Payload administrator' && '1'=='1 trả về bản ghi administrator thành công:

image.png

Tới đây thì mọi chuyện trở nên dễ dàng! Xác định độ dài mật khẩu với payload administrator' && this.password.length < 10 || 'a'=='b, giảm dần độ dài cho tới khi response không trả về thông tin:

image.png image.png

Xác định được độ dài mật khẩu là 99.

image.png

Công việc cuối cùng là tìm kiếm từng ký tự của mật khẩu với payload administrator' && this.password[0]=='a

image.png image.png

Có thể sử dụng tính năng Intruder của BurpSuite, sử dụng script tự động, các thuật toán tìm kiếm để tối ưu hóa thời gian.

Bạn đọc có thể luyện tập thêm với bài lab Exploiting NoSQL operator injection to extract unknown fields.

VI. Công cụ NoSQL map

Bên cạnh các kỹ thuật tấn công thủ công, chúng ta có thể sử dụng một số công cụ tự động với NoSQL injection. Một trong những công cụ được yêu chuộng của dạng lỗ hổng này là NoSQLmap có mã nguồn mở tại Github, link cài đặt: https://github.com/codingo/NoSQLMap

VII. Ngăn chặn NoSQL injection

1. Làm sạch và xác thực đầu vào

Xác minh và giới hạn kiểu dữ liệu mà ứng dụng nhận từ người dùng (ví dụ: chỉ cho phép các ký tự chữ và số).

Loại bỏ các ký tự đặc biệt hoặc các ký tự có thể gây lỗi cú pháp, chẳng hạn như ', ", ;, {, }, &&, ||, và ký tự null \u0000.

Chẳng hạn một hàm sanitizeCategoryInput() chỉ cho phép các ký tự chữ và số:

function sanitizeCategoryInput(category) { const sanitizedCategory = category.replace(/[^a-zA-Z0-9]/g, ''); return sanitizedCategory;
}

2. Sử dụng các thư viện kiểm tra đầu vào

Dùng thư viện hoặc middleware để xử lý và kiểm tra đầu vào, đảm bảo rằng chỉ những giá trị hợp lệ mới được đưa vào truy vấn. Ví dụ sử dụng các thư viện như validator hoặc express-validator:

const { query, validationResult } = require('express-validator'); app.get('/product/lookup', [ query('category').isAlphanumeric().withMessage('Category chỉ cho phép chữ và số'),
], async (req, res) => { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ errors: errors.array() }); } const category = req.query.category; try { const products = await Product.find({ category: category, released: true }); res.json(products); } catch (error) { res.status(500).json({ message: 'Lỗi truy vấn', error: error.message }); }
});

3. Thay thế các điều kiện truy vấn bằng tham số hóa

Khi có thể, sử dụng các phương pháp khác để kiểm tra các giá trị đầu vào hợp lệ, chẳng hạn như đưa ra danh sách chọn tĩnh từ phía server thay vì để người dùng nhập trực tiếp.

const allowedCategories = ['fizzy', 'juice', 'snacks']; app.get('/product/lookup', async (req, res) => { let category = req.query.category; if (!allowedCategories.includes(category)) { return res.status(400).json({ message: 'Danh mục không hợp lệ' }); } try { const products = await Product.find({ category: category, released: true }); res.json(products); } catch (error) { res.status(500).json({ message: 'Lỗi truy vấn', error: error.message }); }
});

4. Sử dụng các công cụ lọc như MongoDB $regex an toàn:

Khi cần tìm kiếm linh hoạt, hãy sử dụng $regex với kiểm tra chặt chẽ hoặc các phương thức lọc khác thay vì truy vấn trực tiếp.

app.get('/product/lookup', async (req, res) => { let category = req.query.category; if (!category || !/^[a-zA-Z0-9]+$/.test(category)) { return res.status(400).json({ message: 'Danh mục không hợp lệ' }); } try { const products = await Product.find({ category: { $regex: new RegExp(`^${category}$`, 'i') }, released: true }); res.json(products); } catch (error) { res.status(500).json({ message: 'Lỗi truy vấn', error: error.message }); }
});

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 102

- 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 80

- 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 85

- 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 46

- 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 178

- 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 45