Bảo mật cơ sở dữ liệu MySQL và MariaDB trên một VPS Linux

Nhiều phiên bản của ngôn ngữ cơ sở dữ liệu SQL có sẵn trên hệ thống Linux và Unix. MySQL và MariaDB là hai tùy chọn phổ biến để triển khai cơ sở dữ liệu quan hệ trong môi trường máy chủ. Tuy nhiên, giống như hầu hết phần mềm khác, các công cụ này có thể gây nguy hiểm bảo mật nếu được cấu hình sai. Hướng dẫn này sẽ chỉ bạn một số bước cơ bản để bảo mật cơ sở dữ liệu MariaDB hoặc MySQL nhằm đảm bảo rằng chúng không phải là cánh cửa mở vào VPS của bạn.

Vì đây là một minh họa đơn giản nên chúng ta sẽ sử dụng máy chủ MySQL trên một phiên bản VPS Ubuntu Tuy nhiên, các kỹ thuật này có thể được áp dụng cho các bản phân phối Linux khác và cũng có thể được sử dụng với MariaDB.

Các thiết lập ban đầu để bảo mật cơ sở dữ liệu MySQL và MariaDB

MySQL cung cấp cho bạn bước đầu tiên của việc bảo mật trong quá trình cài đặt. Nó sẽ yêu cầu bạn đặt một mật khẩu cho người dùng root.

sudo apt-get install mysql-server
?????????????????????????? Configuring mysql-server-5.5 ??????????????????????????? ? While not mandatory, it is highly recommended that you set a password for the ? ? MySQL administrative "root" user. ? ? ? ? If this field is left blank, the password will not be changed. ? ? ? ? New password for the MySQL "root" user: ? ? ? ? _______________________________________________________________________________ ? ? ? ? ? ? ? ???????????????????????????????????????????????????????????????????????????????????

Bạn luôn có thể đặt mật khẩu cho tài khoản root sau này, tuy vậy không có lý do gì để bỏ qua bước này, thế nên bạn nên bảo mật tài khoản quản trị từ đầu.

Sau khi quá trình cài đặt hoàn tất, bạn nên chạy một số kịch bản đi kèm. Đầu tiên, chúng ta sẽ sử dụng kịch bản "mysql_install_db" để tạo ra một cấu trúc thư mục cho cơ sở dữ liệu.

sudo mysql_install_db

Tiếp theo, chạy kịch bản có tên "mysql_secure_installation". Điều này sẽ hướng dẫn chúng ta qua một số thủ tục để loại bỏ một số giá trị mặc định gây nguy hiểm khi sử dụng trong môi trường sản xuất.

sudo mysql_secure_installation

Trước tiên, nó sẽ yêu cầu bạn nhập mật khẩu root mà bạn đã thiết lập trong quá trình cài đặt. Ngay sau đó, bạn sẽ được hỏi một loạt câu hỏi, bắt đầu bằng việc bạn có muốn thay đổi mật khẩu root hay không.

Đây là cơ hội khác để bạn thay đổi mật khẩu thành một mật khẩu an toàn nếu bạn chưa làm điều đó. Bạn nên trả lời "Y" (để đồng ý) cho tất cả các câu hỏi còn lại.

Điều này sẽ loại bỏ khả năng đăng nhập vào MySQL mặc định, vô hiệu hóa đăng nhập từ xa bằng tài khoản quản trị, xóa một số cơ sở dữ liệu kiểm tra không an toàn và cập nhật phiên bản MySQL đang chạy để phản ánh những thay đổi này.

Những yếu tố cần xem xét về bảo mật cơ sở dữ liệu

Chủ đề chung về việc bảo mật MySQL (và hầu hết các hệ thống khác) là chỉ cấp quyền truy cập khi thực sự cần thiết. An toàn dữ liệu của bạn đôi khi phải cân nhắc giữa tiện lợi và bảo mật.

Hướng dẫn này sẽ tập trung vào mặt bảo mật, mặc dù việc sử dụng cụ thể của phần mềm cơ sở dữ liệu có thể khiến bạn lựa chọn từ các tùy chọn này.

Bảo mật thông qua tập tin My.cnf

Tập tin cấu hình chính cho MySQL là tệp "my.cnf" nằm trong thư mục "/etc/mysql/" trên Ubuntu và thư mục "/etc/" trên một số VPS khác.

Chúng ta sẽ thay đổi một số cài đặt trong tệp này để khóa MySQL của chúng ta. Mở tệp với quyền root. Thay đổi đường dẫn thư mục nếu bạn đang làm theo hướng dẫn này trên một hệ thống khác.

sudo nano /etc/mysql/my.cnf

Thiết lập đầu tiên mà chúng ta nên kiểm tra là thiết lập "bind-address" trong phần "[mysqld]" của tệp cấu hình. Thiết lập này nên được đặt thành thiết bị mạng local loopback của bạn, tức là "127.0.0.1".

bind-address = 127.0.0.1

Điều này đảm bảo rằng MySQL không chấp nhận kết nối từ bất kỳ nơi nào ngoại trừ máy cục bộ.

Nếu bạn cần truy cập cơ sở dữ liệu này từ máy khác, hãy xem xét kết nối thông qua SSH để thực hiện truy vấn và quản lý cơ sở dữ liệu cục bộ, gửi kết quả qua đường hầm SSH.

Lỗ hổng tiếp theo chúng ta sẽ khắc phục là một chức năng cho phép truy cập vào hệ thống tệp hệ điều hành từ bên trong MySQL. Điều này có thể có những tác động bảo mật nghiêm trọng và nên được tắt nếu không cần thiết.

Trong cùng phần của tệp, chúng ta sẽ thêm một chỉ thị để vô hiệu hóa khả năng tải tệp cục bộ này.

local-infile=0

Điều này sẽ vô hiệu hóa việc tải tệp từ hệ thống tệp cho người dùng không có quyền cấp độ tệp đối với cơ sở dữ liệu.

Nếu chúng ta có đủ không gian và không vận hành một cơ sở dữ liệu lớn, có thể hữu ích để ghi thông tin bổ sung theo dõi hoạt động đáng ngờ.

Việc ghi quá nhiều thông tin có thể ảnh hưởng đến hiệu suất, vì vậy điều này là điều bạn cần cân nhắc cẩn thận. Bạn có thể đặt biến ghi nhật ký trong cùng phần "[mysqld]" mà chúng ta đã thêm vào.

log=/var/log/mysql-logfile

Hãy đảm bảo rằng nhật ký MySQL, nhật ký lỗi và thư mục nhật ký MySQL không có quyền đọc cho toàn bộ người dùng:

sudo ls -l /var/log/mysql*
-rw-r----- 1 mysql adm 0 Jul 23 18:06 /var/log/mysql.err -rw-r----- 1 mysql adm 0 Jul 23 18:06 /var/log/mysql.log /var/log/mysql: total 28 -rw-rw---- 1 mysql adm 20694 Jul 23 19:17 error.log

Bảo mật MySQL từ bên trong

Có một số bước bạn có thể thực hiện khi sử dụng MySQL để nâng cao bảo mật cơ sở dữ liệu. Chúng ta sẽ nhập các lệnh trong phần này vào giao diện dòng lệnh MySQL, vì vậy chúng ta cần đăng nhập.

mysql -u root -p

Bạn sẽ được yêu cầu nhập mật khẩu root mà bạn đã thiết lập trước đó.

  • Bảo mật mật khẩu và liên kết máy chủ

Đầu tiên, hãy đảm bảo không có người dùng nào có được mật khẩu hoặc liên kết máy chủ trong MySQL:

SELECT User,Host,Password FROM mysql.user;
+------------------+-----------+-------------------------------------------+ | user | host | password | +------------------+-----------+-------------------------------------------+ | root | localhost | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | demo-user | % | | | root | 127.0.0.1 | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | root | ::1 | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | debian-sys-maint | localhost | *ECE81E38F064E50419F3074004A8352B6A683390 | +------------------+-----------+-------------------------------------------+ 5 rows in set (0.00 sec)

Như bạn có thể thấy, trong ví dụ thiết lập của chúng ta, người dùng "demo-user" không có mật khẩu và hợp lệ bất kể cả anh ta đang ở máy chủ nào. Điều này rất không an toàn.

Chúng ta có thể thiết lập mật khẩu cho người dùng bằng lệnh này. Thay đổi "newPassWord" để phản ánh mật khẩu mà bạn muốn gán.

UPDATE mysql.user SET Password=PASSWORD('newPassWord') WHERE User="demo-user";

Nếu chúng ta kiểm tra lại bảng User, chúng ta sẽ thấy rằng người dùng demo giờ đây đã có mật khẩu:

SELECT User,Host,Password FROM mysql.user;
+------------------+-----------+-------------------------------------------+ | user | host | password | +------------------+-----------+-------------------------------------------+ | root | localhost | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | demo-user | % | *D8DECEC305209EEFEC43008E1D420E1AA06B19E0 | | root | 127.0.0.1 | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | root | ::1 | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | debian-sys-maint | localhost | *ECE81E38F064E50419F3074004A8352B6A683390 | +------------------+-----------+-------------------------------------------+ 5 rows in set (0.00 sec)

Nếu bạn nhìn vào trường "Host", bạn sẽ thấy rằng chúng ta vẫn có một "%", đây là một ký tự đại diện có nghĩa là bất kỳ máy chủ nào. Điều này không phải là điều chúng ta muốn. Hãy thay đổi nó thành "localhost":

UPDATE mysql.user SET Host='localhost' WHERE User="demo-user";

Nếu chúng ta kiểm tra lại, chúng ta sẽ thấy rằng bảng User giờ đây có các trường hợp lý.

SELECT User,Host,Password FROM mysql.user;

Nếu bảng của chúng ta chứa bất kỳ người dùng trống nào (dù ở thời điểm này không nên có vì chúng ta đã chạy "mysql_secure_installation") thì nên xóa chúng.

Để làm điều này, bạn có thể sử dụng lệnh sau để xóa người dùng trống từ bảng truy cập:

DELETE FROM mysql.user WHERE User="";

Sau khi hoàn thành việc chỉnh sửa bảng User, chúng ta cần nhập lệnh sau để thực hiện các quyền truy cập mới:

FLUSH PRIVILEGES;

Triển khai người dùng đặc thù ứng dụng

Tương tự như việc chạy quy trình trong Linux với một người dùng cô lập, MySQL cũng có lợi từ loại cô lập tương tự.

Mỗi ứng dụng sử dụng MySQL nên có một người dùng riêng có đặc quyền giới hạn và chỉ có quyền truy cập vào các cơ sở dữ liệu mà nó cần để chạy.

Khi chúng ta cấu hình một ứng dụng mới sử dụng MySQL, chúng ta nên tạo các cơ sở dữ liệu cần thiết cho ứng dụng đó:

create database testDB;
Query OK, 1 row affected (0.00 sec)

Tiếp theo, chúng ta nên tạo một người dùng để quản lý cơ sở dữ liệu đó và chỉ gán cho nó các quyền cần thiết. Điều này sẽ khác nhau tùy theo ứng dụng và một số ứng dụng cần có các quyền mở hơn so với các ứng dụng khác.

Để tạo một người dùng mới, sử dụng lệnh sau:

CREATE USER 'demo-user'@'localhost' IDENTIFIED BY 'password';

Chúng ta có thể cấp quyền cho người dùng mới trên bảng mới bằng lệnh sau:

GRANT SELECT,UPDATE,DELETE ON testDB.* TO 'demo-user'@'localhost';

Ví dụ, nếu sau này bạn cần thu hồi quyền cập nhật từ tài khoản, bạn có thể sử dụng lệnh sau:

REVOKE UPDATE ON testDB.* FROM 'demo-user'@'localhost';

Nếu bạn cần tất cả các quyền trên một cơ sở dữ liệu cụ thể, bạn có thể chỉ định điều đó bằng cách sử dụng lệnh sau:

GRANT ALL ON testDB.* TO 'demo-user'@'localhost';

Để hiển thị các quyền hiện tại của một người dùng, trước tiên chúng ta phải thực hiện các quyền mà chúng ta đã chỉ định bằng lệnh "flush privileges". Sau đó, bạn có thể truy vấn các quyền được cấp cho người dùng bằng cách sử dụng lệnh sau:

FLUSH PRIVILEGES; show grants for 'demo-user'@'localhost';
+------------------------------------------------------------------------------------------------------------------+ | Grants for demo-user@localhost | +------------------------------------------------------------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'demo-user'@'localhost' IDENTIFIED BY PASSWORD '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19' | | GRANT SELECT, UPDATE, DELETE ON `testDB`.* TO 'demo-user'@'localhost' | +------------------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec)

Luôn luôn thực hiện lệnh "flush privileges" khi bạn hoàn thành việc thay đổi.

  • Thay đổi người dùng Root: 

Một bước bổ sung mà bạn có thể muốn thực hiện là thay đổi tên đăng nhập root. Nếu kẻ tấn công đang cố gắng truy cập vào đăng nhập root MySQL, họ sẽ cần thực hiện bước bổ sung là tìm tên người dùng.

Đăng nhập root có thể được thay đổi bằng lệnh sau:

rename user 'root'@'localhost' to 'newAdminUser'@'localhost';

Chúng ta có thể nhìn thấy sự thay đổi bằng cách sử dụng cùng truy vấn mà chúng ta đã sử dụng cho cơ sở dữ liệu User:

select user,host,password from mysql.user;

Một lần nữa, bạn phải thực hiện lệnh "flush privileges" để những thay đổi này có hiệu lực:

FLUSH PRIVILEGES;

Hãy nhớ rằng từ nay trở đi, bạn sẽ phải đăng nhập vào MySQL với tên người dùng mới được tạo khi bạn muốn thực hiện các tác vụ quản trị:

mysql -u newAdminUser -p

Mặc dù đây không phải là một danh sách toàn diện về các phương pháp bảo mật cơ sở dữ liệu MySQL và MariaDB, nhưng nó sẽ giúp bạn hiểu cơ bản về những quyết định bạn phải đưa ra khi bảo vệ cơ sở dữ liệu của mình.

Thông tin chi tiết về cấu hình và bảo mật có thể được tìm thấy trên các trang web của MySQL và MariaDB cũng như trong các trang man tương ứng của chúng. Các ứng dụng mà bạn chọn sử dụng cũng có thể cung cấp lời khuyên về bảo mật.