MySQL is an ubiquitous open source database but do you know how make it secure? This talk is from the 2022 Texas Cyber Summit on how to do just that. Make sure you data and database are secure.
2. Open Source Advocate
MySQL Community Team 11 years
Author of MySQL & JSON - A Practical Programming Guide
About me
2
Bonus: More slides on this topic at
https://slideshare.net/davidmstokes
deck than be covered in this time slot
5. Learning How To Learn
● Interpreting error messages
● ‘What the *#%& does that mean?’ moments
○ What is the computer trying to tell me?
○ How do you solve that?!?
○ One of the few cases where extensive exposure
to toddlers is beneficial
● Comprehension
○ ‘Seat time’ versus ‘learning curve’
● Action or active inaction
● Is that good or bad? That depends!
○ Sadly very few rules where x is always bad
5
7. 7
Need to handled properly
to secure your MySQL
server - at the same time!
Many levels
8. 8
Some Basics!
1. Never have database server directly accessible from the Internet.
2. You will software updated.
3. Keep database network traffic isolated.
4. Not everyone needs the root password.
5. Isolate schemas/databases by project/function, do not let them mix &
match
6. Practice recovery from backups
7. Make useful backups.
8. Monitor you instances.
9. Reject bad queries, projects ‘tossed over the wall’.
10.Know your company rules on data privacy, data retention, and security -
AND FOLLOW THEM!
9. 9
Do NOT use the root account for
any and everything!
Passwords
10. 1. Do not have anonymous accounts
without passwords
2. Use complex passwords - UC, LC,
special characters
3. Expire passwords
Password
Complexity
10
11. 11
Complexity
The LOW policy tests password length only. Passwords must be at least 8 characters long. To
change this length, modify validate_password.length.
The MEDIUM policy adds the conditions that passwords must contain at least 1 numeric
character, 1 lowercase character, 1 uppercase character, and 1 special (nonalphanumeric)
character. To change these values, modify validate_password.number_count,
validate_password.mixed_case_count, and validate_password.special_char_count.
The STRONG policy adds the condition that password substrings of length 4 or longer must not
match words in the dictionary file, if one has been specified. To specify the dictionary file, modify
validate_password.dictionary_file.
Use a dictionary file to keep out passwords like ‘password’, ‘thebossisajerk’, ‘Passw()rd’, or
‘incorrect’
12. 12
Example
SQL > create user 'Foo'@'%' IDENTIFIED BY RANDOM PASSWORD;
+------+------+----------------------+
| user | host | generated password |
+------+------+----------------------+
| Foo | % | Ld]5/Fkn[Kk29/g/M;>n |
+------+------+----------------------+
1 row in set (0.0090 sec)
Another Example
SQL > ALTER USER 'Foo'@'%' IDENTIFIED BY RANDOM PASSWORD;
+------+------+----------------------+
| user | host | generated password |
+------+------+----------------------+
| Foo | % | !rN<NCxjE5ncC6mB*2:@ |
+------+------+----------------------+
Let server generate password
13. 13
Secondary Passwords
ALTER USER 'dave'@'deardave.xyz' IDENTIFIED BY 'deardave2' RETAIN CURRENT PASSWORD;
In the mysql.user table there is now a User_attribute column:
{"additional_password": "$A$005$;H7u001bu001bu0006<`qFRUtNRxT
Zu0003Ya/iej8Az8LoXGTv.dtf9K3RdJuaLFtXZHBs3/DntG2"}
ALTER USER 'dave'@'deardave'xyz' DISCARD OLD PASSWORD
16. 16
Personnel will not advise you of staff changes
and the DBA.SRE needs to check that those who
have access to schemas really need that access!
Know who needs
access!
18. 18
MySQL will authenticate users at the first match
Which may not be the right match
bob@yourcompany.com != bob@192.168.%.%
These two accounts are seen as two separate accounts
(with possibly different privileges)
Promiscuity
19. 19
Login process
1. Is your system allowed to connect to server?
2. Is your account allowed to connect to server?
3. Is your account restricted from server?
4. Does account have privileges to connect?
5. Does your account have privileges to connect to
columns/tables/schemas?
20. 20
Identify accounts
CREATE USER 'dstokes'@'localhost'
IDENTIFIED by 'S3cr3t!'
COMMENT '{ "user" : "Dave" }';
And the information is stored in a column named User_attributes.
select User_attributes from user WHERE User='dstokes'G
*************************** 1. row ***************************
User_attributes: {"metadata": {"comment": "{ "user" : "Dave"
}"}}
alter user 'jack'@'localhost'
ATTRIBUTE '{ "foo" : "Example" }';
SELECT User_attributes from user where User='jack';
+-------------------------------------------------+
| User_attributes |
+-------------------------------------------------+
| {"metadata": {"foo": "Example", "test": "yes"}} |
+-------------------------------------------------+
24. 24
Use your privileges wisely
Do not give out SUPER or GRANT privs unless you have to!
Do not use the same accounts for separate projects
Consider separate account/password for read versus
write
Use ROLES, do not copy someone else’s account
25. 25
CREATE ROLE 'app_developer', 'app_read', 'app_write';
GRANT ALL ON app_db.* TO 'app_developer';
GRANT SELECT ON app_db.* TO 'app_read';
GRANT INSERT, UPDATE, DELETE ON app_db.* TO 'app_write';
Create accounts
GRANT 'app_developer' TO 'dev1'@'localhost';
GRANT 'app_read' TO 'read_user1'@'localhost',
'read_user2'@'localhost';
GRANT 'app_read', 'app_write' TO 'rw_user1'@'localhost';
27. 27
A handful of options:
Data security is a concern for institutions and organizations.
Transparent Data Encryption (TDE) or Data at Rest Encryption encrypts data
files.
Data at rest is any data which is not accessed or changed frequently, stored
on different types of storage devices.
Encryption ensures that if an unauthorized user accesses the data files from
the file system, the user cannot read contents.
28. 28
If you encrypt your data
on disk, you should also
make your logs save too!
Do not forget the logs!
30. 1. Yes, you need to make backups
2. Yes, you need to be able to restore a) server, b)
schema, c) table, & d) row
3. Offsite storage
4. Cross training staff
5. What is your retention time
6. How much can you lose?
Backups/Recover
30
31. 31
● Snapshots
● MySQL Dump / MySQL Pump
● MySQL Shell Utilities
● Percona XtraBackup
● MySQL Enterprise Backup ($$$$)
32. 1. Use UTF8MB4 Universally — Double check!
Character Sets &
Collations
32
33. 33
MySQL localhost:33060+ ssl test SQL > show create table testG
*************************** 1. row ***************************
Table: test
Create Table: CREATE TABLE `test` (
`ID` int NOT NULL AUTO_INCREMENT,
`Name` char(35) NOT NULL DEFAULT '',
`CountryCode` char(3) NOT NULL DEFAULT '',
PRIMARY KEY (`ID`),
KEY `Name` (`Name`),
KEY `Name_CountryCode` (`Name`,`CountryCode`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.0070 sec)
34. 34
MySQL localhost:33060+ ssl test SQL > show create table testG
*************************** 1. row ***************************
Table: test
Create Table: CREATE TABLE `test` (
`ID` int NOT NULL AUTO_INCREMENT,
`Name` char(35) NOT NULL DEFAULT '',
`CountryCode` char(3) NOT NULL DEFAULT '',
PRIMARY KEY (`ID`),
KEY `Name` (`Name`),
KEY `Name_CountryCode` (`Name`,`CountryCode`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.0070 sec)
35. 35
Please pay attention to character sets
and collations when performing
upgrades. With MySQL 8.0 the old UTF8
was not the new UTF8MB4.
Character Sets /
Collations
36. 36
Use the upgrade checker in
the MySQL Shell
mysqlsh> util.checkForServerUpgrade()
37. Cheaper to keep bad data out than have to fix it later
Keep out bad data
37
38. 38
CREATE TABLE c1 (id INT NOT NULL,
CONSTRAINT id_gt_100 CHECK (('id' > 100))
);
A simple test with a value in range runs perfectly fine.
INSERT INTO c1 (id) VALUES (10000);
Query OK, 1 row affected (0.0037 sec)
But you will receive an error if the value of 'is' is less than 100.
INSERT INTO c1 (id) VALUES (10);
ERROR: 3819: Check constraint 'id_gt_100' is
violated.
39. 39
CREATE TABLE c1 (id INT NOT NULL,
CONSTRAINT id_gt_100 CHECK (('id' > 100))
);
A simple test with a value in range runs perfectly fine.
INSERT INTO c1 (id) VALUES (10000);
Query OK, 1 row affected (0.0037 sec)
But you will receive an error if the value of 'is' is less than 100.
INSERT INTO c1 (id) VALUES (10);
ERROR: 3819: Check constraint 'id_gt_100' is
violated.
Hint - name your
constraints to be able
to track them down
quickly.
47. 47
1. Use for backup
2. Use for HA – Group Replication, Replica
Sets, XtraDB Cluster
3. Copy data between data centers
4. You do not need to replicate everything –
be selective
53. You need to know how
to read a query plan.
Learn to use
EXPLAIN
53
54. ORMs are optimized for developers and not for
databases. They write bad queries, make
mistakes, and can introduce their own set of
overhead problems.
Learn to write good SQL!
ORMs are a NO-NO!
54
55. Plan to review your servers on a regular basis to assure that
‘mission creep’ is not interfering with the safety of your
data.
Audit Your Work!
55