MongoDB là một document database được sử dụng trong nhiều ứng dụng web hiện đại. Nó được phân loại là NoSQL database, vì nó không dựa vào cấu trúc cơ sở dữ liệu quan hệ dựa trên bảng truyền thống. Thay vào đó, nó sử dụng các tài liệu giống như JSON với các lược đồ động (dynamic schemas).
MongoDB không bật xác thực theo mặc định, nghĩa là bất kỳ người dùng nào có quyền truy cập vào máy chủ nơi cơ sở dữ liệu được cài đặt đều có thể thêm và xóa dữ liệu mà không bị hạn chế. Để bảo vệ lỗ hổng này, bài viết này sẽ hướng dẫn bạn cách tạo người dùng quản trị và kích hoạt xác thực. Sau đó, bạn sẽ kiểm tra để xác nhận rằng chỉ người dùng quản trị này mới có quyền truy cập vào cơ sở dữ liệu.
Để hoàn thành hướng dẫn này, bạn sẽ cần những điều sau đây:
Kể từ khi phát hành phiên bản 3.0, MongoDB daemon được thiết lập cấu hình để chỉ chấp nhận các kết nối từ Unix socket cục bộ và nó không tự động mở ra Internet rộng hơn. Tuy nhiên, xác thực vẫn bị tắt theo mặc định. Điều này có nghĩa là bất kỳ người dùng nào có quyền truy cập vào máy chủ cài đặt MongoDB cũng có quyền truy cập đầy đủ vào cơ sở dữ liệu.
Bước đầu tiên để bảo vệ lỗ hổng này, bạn sẽ tạo một người dùng quản trị (administrative user). Sau đó, bạn sẽ bật xác thực và kết nối với tư cách người dùng quản trị này để truy cập cơ sở dữ liệu.
Để thêm người dùng quản trị, trước tiên bạn phải kết nối với Mongo shell. Vì xác thực bị tắt nên bạn có thể làm như vậy bằng lệnh mongo
mà không có bất kỳ tùy chọn nào khác:
- mongo
Sẽ có một số đầu ra phía trên Mongo shell prompt. Bởi vì bạn chưa kích hoạt xác thực, điều này sẽ bao gồm một cảnh báo rằng kiểm soát truy cập không được kích hoạt cho cơ sở dữ liệu, và quyền truy cập đọc và ghi vào dữ liệu cũng như cấu hình của cơ sở dữ liệu không bị hạn chế:
OutputMongoDB shell version v4.4.0
. . .
2020-06-09T13:26:51.391+0000 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2020-06-09T13:26:51.391+0000 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
. . .
>
Những cảnh báo này sẽ biến mất sau khi bạn kích hoạt xác thực, nhưng hiện tại chúng có nghĩa là bất kỳ ai có thể truy cập máy chủ Ubuntu của bạn cũng có thể kiểm soát cơ sở dữ liệu của bạn.
Để minh họa, hãy chạy lệnh show dbs
của Mongo:
- show dbs
Lệnh này trả về danh sách mọi cơ sở dữ liệu trên máy chủ. Tuy nhiên, khi bật xác thực, danh sách sẽ thay đổi dựa trên vai trò của Mongo user hoặc mức độ truy cập của nó đối với một số cơ sở dữ liệu nhất định. Tuy nhiên, vì xác thực bị vô hiệu hóa nên nó sẽ trả về mọi cơ sở dữ liệu hiện có trên hệ thống mà không bị hạn chế:
Outputadmin 0.000GB
config 0.000GB
local 0.000GB
Trong kết quả ví dụ này, chỉ có cơ sở dữ liệu mặc định xuất hiện. Tuy nhiên, nếu bạn có bất kỳ cơ sở dữ liệu nào chứa dữ liệu nhạy cảm trên hệ thống của mình, bất kỳ người dùng nào cũng có thể tìm thấy chúng bằng lệnh này.
Là một phần của việc giảm thiểu lỗ hổng này, bước này tập trung vào việc thêm người dùng quản trị. Để thực hiện việc này, trước tiên bạn phải kết nối với cơ sở dữ liệu admin
. Đây là nơi lưu trữ thông tin về người dùng, như tên người dùng, mật khẩu và vai trò của họ:
- use admin
Outputswitched to db admin
MongoDB được cài đặt sẵn một số phương thức JavaScript-based shell mà bạn có thể sử dụng để quản lý cơ sở dữ liệu của mình. Một trong số đó, phương thức db.createUser
, được sử dụng để tạo người dùng mới trên cơ sở dữ liệu mà phương thức này được chạy.
Bắt đầu phương thức db.createUser
:
- db.createUser(
Phương pháp này yêu cầu bạn chỉ định tên người dùng và mật khẩu cho user, cũng như bất kỳ vai trò nào bạn muốn người dùng có. Nhớ lại rằng MongoDB lưu trữ dữ liệu của nó trong các tài liệu giống như JSON. Như vậy, khi bạn tạo một người dùng mới, tất cả những gì bạn đang làm là tạo một tài liệu để chứa dữ liệu người dùng thích hợp dưới dạng các trường riêng lẻ.
Cũng như đối tượng trong JSON, tài liệu trong MongoDB bắt đầu và kết thúc bằng dấu ngoặc nhọn ({
và }
). Để bắt đầu thêm người dùng, hãy nhập dấu ngoặc nhọn mở:
Lưu ý: Mongo sẽ không đăng ký phương thức db.createUser
là hoàn tất cho đến khi bạn nhập dấu ngoặc đơn đóng. Cho đến khi bạn làm như vậy, lời nhắc sẽ thay đổi từ dấu lớn hơn (>
) thành dấu chấm lửng (...
).
- {
Tiếp theo, nhập trường user:
với tên người dùng bạn muốn làm giá trị trong dấu ngoặc kép theo sau là dấu phẩy. Ví dụ dưới đây chỉ định tên người dùng AdminSammy, nhưng bạn có thể nhập bất kỳ tên người dùng nào bạn muốn:
- user: "AdminSammy",
Tiếp theo, nhập trường pwd
với phương thức passwordPrompt()
làm giá trị. Khi bạn thực thi phương thức db.createUser
, phương thức passwordPrompt()
sẽ nhắc bạn nhập mật khẩu của mình. Cách này an toàn hơn cách khác, đó là nhập mật khẩu của bạn ở dạng văn bản rõ ràng như bạn đã làm với tên người dùng của mình.
Lưu ý: Phương thức passwordPrompt()
chỉ tương thích với MongoDB phiên bản 4.2 trở lên. Nếu bạn đang sử dụng phiên bản MongoDB cũ hơn, thì bạn sẽ phải viết mật khẩu của mình ở dạng văn bản rõ ràng, tương tự như cách bạn viết tên người dùng của mình:
- pwd: "password",
Đảm bảo cũng theo dõi trường này bằng dấu phẩy:
- pwd: passwordPrompt(),
Sau đó, nhập các vai trò mà bạn muốn người dùng quản trị của mình có. Bởi vì bạn đang tạo một người dùng quản trị, tối thiểu bạn nên cấp cho họ vai trò userAdminAnyDatabase
trên cơ sở dữ liệu admin
. Điều này sẽ cho phép người dùng quản trị tạo và sửa đổi người dùng và vai trò mới. Vì người dùng quản trị có vai trò này trong cơ sở dữ liệu admin
, điều này cũng sẽ cấp cho họ quyền truy cập superuser vào toàn bộ cluster.
Ngoài ra, ví dụ sau cũng cấp cho người dùng quản trị vai trò readWriteAnyDatabase
. Điều này cấp cho người dùng quản trị khả năng đọc và sửa đổi dữ liệu trên bất kỳ cơ sở dữ liệu nào trong cụm ngoại trừ cơ sở dữ liệu config
và local
, phần lớn được sử dụng nội bộ:
- roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
Sau đó, nhập dấu ngoặc nhọn để biểu thị phần cuối của tài liệu:
- }
Sau đó, nhập dấu ngoặc đơn đóng để đóng và thực thi phương thức db.createUser
:
- )
Tất cả cùng nhau, đây là phương thức db.createUser
của bạn sẽ trông như thế nào:
- db.createUser(
- ... {
- ... user: "AdminSammy",
- ... pwd: passwordPrompt(),
- ... roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
- ... }
- ... )
Nếu cú pháp của mỗi dòng là chính xác, phương thức sẽ thực thi đúng cách và bạn sẽ được nhắc nhập mật khẩu:
OutputEnter password:
Nhập một mật khẩu mạnh mà bạn chọn. Sau đó, bạn sẽ nhận được xác nhận rằng người dùng đã được thêm vào:
OutputSuccessfully added user: {
"user" : "AdminSammy",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
},
"readWriteAnyDatabase"
]
}
Sau đó, bạn có thể thoát ứng dụng khách MongoDB:
- exit
Tại thời điểm này, người dùng của bạn sẽ được phép nhập thông tin đăng nhập. Tuy nhiên, họ sẽ không bắt buộc phải làm như vậy cho đến khi bạn kích hoạt xác thực và khởi động lại MongoDB daemon.
Để bật xác thực, bạn phải chỉnh sửa mongod.conf
, tệp cấu hình của MongoDB. Khi bạn kích hoạt nó và khởi động lại dịch vụ Mongo, người dùng vẫn có thể kết nối với cơ sở dữ liệu mà không cần xác thực. Tuy nhiên, họ sẽ không thể đọc hoặc sửa đổi bất kỳ dữ liệu nào cho đến khi họ cung cấp tên người dùng và mật khẩu chính xác.
Mở tệp cấu hình bằng trình soạn thảo văn bản ưa thích của bạn. Ở đây, chúng tôi sẽ sử dụng nano
:
- sudo nano /etc/mongod.conf
Cuộn xuống để tìm phần security
đã nhận xét:
. . .
#security:
#operationProfiling:
. . .
Bỏ ghi chú dòng này bằng cách xóa dấu thăng (#
):
. . .
security:
#operationProfiling:
. . .
Sau đó, thêm tham số authorization
và đặt thành enabled
. Khi bạn hoàn thành, các dòng sẽ trông như thế này:
. . .
security:
authorization: enabled
. . .
Lưu ý rằng dòng security:
không có khoảng trắng ở đầu, trong khi dòng authorization:
được thụt vào với hai khoảng trắng.
Sau khi thêm những dòng này, hãy lưu và đóng tệp. Nếu bạn đã sử dụng nano
để mở tệp, hãy làm như vậy bằng cách nhấn CTRL + X
, Y
, rồi ENTER
.
Sau đó khởi động lại daemon để những thay đổi mới này có hiệu lực:
- sudo systemctl restart mongod
Tiếp theo, hãy kiểm tra trạng thái của dịch vụ để đảm bảo rằng dịch vụ đã khởi động lại đúng cách:
- sudo systemctl status mongod
Nếu lệnh restart
thành công, bạn sẽ nhận được đầu ra cho biết dịch vụ mongod
đang hoạt động và mới được bắt đầu:
Output● mongod.service - MongoDB Database Server
Loaded: loaded (/lib/systemd/system/mongod.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2020-06-09 22:06:20 UTC; 7s ago
Docs: https://docs.mongodb.org/manual
Main PID: 15370 (mongod)
Memory: 170.1M
CGroup: /system.slice/mongod.service
└─15370 /usr/bin/mongod --config /etc/mongod.conf
Jun 09 22:06:20 your_host systemd[1]: Started MongoDB Database Server.
Sau khi xác minh rằng daemon đã được sao lưu và chạy, bạn có thể kiểm tra xem cài đặt xác thực mà bạn đã thêm có hoạt động như mong đợi hay không.
Để bắt đầu kiểm tra xem các yêu cầu xác thực mà bạn đã thêm ở bước trước có hoạt động chính xác hay không, hãy bắt đầu bằng cách kết nối mà không chỉ định bất kỳ thông tin đăng nhập nào để xác minh rằng hành động của bạn thực sự bị hạn chế:
- mongo
Bây giờ bạn đã kích hoạt xác thực, không có cảnh báo nào bạn gặp phải trước đây sẽ xuất hiện:
OutputMongoDB shell version v4.4.0
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("5d50ed96-f7e1-493a-b4da-076067b2d898") }
MongoDB server version: 4.4.0
>
Xác nhận xem quyền truy cập của bạn có bị hạn chế hay không bằng cách chạy lại lệnh show dbs
:
- show dbs
Nhớ lại từ Bước 1 rằng có ít nhất một vài cơ sở dữ liệu mặc định trên máy chủ của bạn. Tuy nhiên, trong trường hợp này, lệnh sẽ không có bất kỳ đầu ra nào vì bạn chưa được xác thực là người dùng có đặc quyền.
Vì lệnh này không trả về bất kỳ thông tin nào nên có thể nói rằng cài đặt xác thực đang hoạt động như mong đợi. Bạn cũng sẽ không thể tạo người dùng hoặc thực hiện các tác vụ đặc quyền khác mà không cần xác thực trước.
Hãy tiếp tục và thoát khỏi MongoDB shell:
Lưu ý: Thay vì chạy lệnh exit
sau đây như bạn đã làm trước đó trong Bước 1, một cách khác để đóng shell là chỉ cần nhấn CTRL + C
.
- exit
Tiếp theo, hãy đảm bảo rằng người dùng quản trị của bạn có thể xác thực đúng cách bằng cách chạy lệnh mongo
sau để kết nối với tư cách là người dùng này. Lệnh này bao gồm cờ -u
, đứng trước tên của người dùng mà bạn muốn kết nối. Đảm bảo thay thế AdminSammy bằng tên người dùng của administrative user của riêng bạn. Nó cũng bao gồm cờ -p
, cờ này sẽ nhắc bạn nhập mật khẩu của người dùng và chỉ định admin
làm cơ sở dữ liệu xác thực nơi tên người dùng được chỉ định được tạo:
- mongo -u AdminSammy -p --authenticationDatabase admin
Nhập mật khẩu của người dùng khi được nhắc, sau đó bạn sẽ được đưa vào shell. Khi đó, hãy thử phát lại lệnh show dbs
:
- show dbs
Lần này, vì bạn đã xác thực đúng cách, lệnh sẽ trả về thành công danh sách tất cả các cơ sở dữ liệu hiện có trên máy chủ:
Outputadmin 0.000GB
config 0.000GB
local 0.000GB
Điều này xác nhận rằng xác thực đã được kích hoạt thành công.
Bằng cách hoàn thành hướng dẫn này, bạn đã thiết lập một administrative MongoDB user mà bạn có thể sử dụng để tạo và sửa đổi những người dùng và vai trò mới, đồng thời quản lý phiên bản MongoDB của bạn. Bạn cũng đã thiết lập cấu hình phiên bản MongoDB của mình để yêu cầu người dùng xác thực bằng tên người dùng và mật khẩu hợp lệ trước khi họ có thể tương tác với bất kỳ dữ liệu nào.
Để biết thêm thông tin về cách quản lý MongoDB users, hãy xem tài liệu chính thức về chủ đề này. Bạn cũng có thể muốn tìm hiểu thêm về cách xác thực hoạt động trên MongoDB.
Ngoài ra, nếu bạn dự định tương tác với phiên bản MongoDB của mình từ xa, bạn có thể làm theo hướng dẫn của chúng tôi về Cách thiết lập cấu hình quyền truy cập từ xa cho MongoDB trên Ubuntu 20.04.