MySQL注入本地文件(LOAD_FILE) 原创 数据库 2021年2月28日 22:11 夏至未至 1503 当前内容 5701 字,在路上,马上到,马上到 ### 问题记录 本地测试中,想给数据库插入文件、图片,但是相应字段结果都是空(NULL)。如下为建表和插入语句: mysql> create table test(id int, pic BLOB); mysql> mysql> insert into test(id, pic) values(5, load_file("/mysql_load_file/picture.png")); Query OK, 1 row affected (0.01 sec) mysql> select * from test; +------+------+ | id | pic | +------+------+ | 5 | NULL | +------+------+ 1 row in set (0.00 sec) mysql> ### 问题原因 以下原因均为实际开发发现,解决方案真实有效,如果还有问题,欢迎文末留言讨论。 #### 数据库配置问题 MySQL 的新特性导致,MySQL 配置文件参出 `secure_file_priv` 是用来限制 LOAD DATA, SELECT ...OUTFILE, and LOAD_FILE()导入导出目录的。 1. `secure_file_priv` 的值为 null, 表示限制MySQL不允许导入/导出。 2. `secure_file_priv` 的值为 /mysql_load_file/,表示限制MySQL的导入|导出只能发生在/mysql_load_file/目录下。 3. `secure_file_priv` 的值没有具体值时,表示不对MySQL的导入|导出做限制。 #### 系统配置问题 系统开启了 `SELinux` ,[关于SELinux,详见此处](https://www.codecomeon.com/posts/122/ "关于SELinux,详见此处"),这里不细说,如下为 SELinux 查看开启情况: [root@localhost /]# cat /etc/selinux/config # This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. SELINUX=enforcing # SELINUXTYPE= can take one of three values: # targeted - Targeted processes are protected, # minimum - Modification of targeted policy. Only selected processes are protected. # mls - Multi Level Security protection. SELINUXTYPE=targeted [root@localhost /]# 如果这里开启了,默认安装 mysql 后,mysql 对其访问的目录设定了安全上下文类型,只有符合这个安全上下文类型的目录,mysql 才认,如果设置了 `secure_file_priv`,但`load_file`还是读取不到文件,那就可能是你设置的`目录安全上下文类型不对,mysqld 没权限访问`。 ### 解决办法 #### 数据库配置问题解决 ##### 创建导入导出目录 创建目录,拷贝待插入文件,给定属主属组 [root@test1 /]# mkdir mysql_load_file [root@test1 /]# cp /picture.png /mysql_load_file [root@test1 /]# chown mysql:mysql /mysql_load_file -R [root@test1 /]# chmod 777 /mysql_load_file -R [root@test1 /]# ll drwxr-xr-x. 2 mysql mysql 25 Oct 1 22:32 mysql_load_file [root@test1 /]# cd /mysql_load_file [root@test1 /]# ll total 24 -rw-r--r--. 1 mysql mysql 21918 Oct 1 22:32 picture.png ##### 改MySQL配置文件 在[mysqld]小节下加入: secure_file_priv=/mysql_load_file/ ##### 重启实例使配置生效 mysql> show global variables like '%secure%'; +--------------------------+-------------------+ | Variable_name | Value | +--------------------------+-------------------+ | require_secure_transport | OFF | | secure_auth | ON | | secure_file_priv | /mysql_load_file/ | +--------------------------+-------------------+ 3 rows in set (0.00 sec) mysql> ##### 插入语句验证问题 mysql> insert into test(id, pic) values(5, load_file("/mysql_load_file/picture.png")); Query OK, 1 row affected (0.01 sec) mysql> mysql> mysql> select * from test; +------+---------------- #### 系统配置问题解决 在 `数据库配置文件解决`后,就来处理目录权限问题,有如下两种办法。 ##### 关闭目录安全配置 关闭 SELinux ,此种方法可靠有效,一劳永逸,xx都会: 1. 临时关闭(不用重启机器): setenforce 0 2. 修改配置文件(需要重启机器): vim /etc/selinux/config SELINUX=disabled ##### 修改目录安全上下文类型 此种方法复杂点,但是安全,不影响系统其他文件或目录,推荐使用,同样的,具体SELinux,[详见SELinux](https://www.codecomeon.com/posts/122/ "详见SELinux"),这里只解决当前问题: 首先确认 mysql 数据库文件安全上下文类型是什么: [root@localhost mysql]# ll -Z ... drwxr-x---. mysql mysql system_u:object_r:mysqld_db_t:s0 codedb_1001 drwxr-x---. mysql mysql system_u:object_r:mysqld_db_t:s0 codedb_1002 ... [root@localhost mysql]# 得到安全上下文类型为 `mysqld_db_t`,再看看 `secure_file_priv` 指定的目录 `mysql_load_file` 的安全上下文类型: [root@localhost /]# ll -Z ... drwxrwxrwx. root root unconfined_u:object_r:default_t:s0 mysql_load_file ... [root@localhost /]# 得到安全上下文类型为 `default_t`, 接下来,将 `secure_file_priv` 指定的目录 `mysql_load_file`,安全上下文类型改成和mysql数据目录安全上下文类型一样 [root@localhost /]# semanage fcontext -a -t mysqld_db_t "/mysql_load_file(/.*)?" [root@localhost /]# [root@localhost /]# restorecon -Rv /mysql_load_file restorecon reset /mysql_load_file context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:mysqld_db_t:s0 [root@localhost /]# 检查,类型已纠正: [root@localhost /]# ll -Z ... drwxrwxrwx. root root unconfined_u:object_r:mysqld_db_t:s0 mysql_load_file ... [root@localhost /]# cd [root@localhost mysql_load_file]# ll -Z -rwxrwxrwx. root root unconfined_u:object_r:mysqld_db_t:s0 picture.png [root@localhost mysql_load_file]# 再次使用 load_file 验证配置是否生效: mysql> insert into test(id, pic) values(5, load_file("/mysql_load_file/picture.png")); Query OK, 1 row affected (0.03 sec) mysql> mysql> select concat(round(sum(DATA_LENGTH/1024/1024),2),'M') from information_schema.tables where table_schema='test' AND table_name='test'; +-------------------------------------------------+ | concat(round(sum(DATA_LENGTH/1024/1024),2),'M') | +-------------------------------------------------+ | 0.02M | +-------------------------------------------------+ 1 row in set (0.09 sec) mysql> 至此,成功使用 LOAD_FILE 获取文件并插如表中。如果最后这种方法,你没设置成功,那就果断关闭 SELinux ,重启机器解决把。以上均为实际工作遇到的问题,两次整理后的结果,亲测有效,尤其是后边的解决方法,这种解决模式不仅仅对当前问题有效,举一反三,其他地方也可以套用。 ### 问题扩展 `LOAD_FILE` 函数读取文件并将文件内容作为字符串返回,文件必须位于服务器主机上,必须指定文件的完整路径名。该文件必须可供所有人读取,并且其大小小于 `max_allowed_packet` 字节。如果`secure_file_priv`系统变量设置为非空目录名,则要加载的文件必须位于该目录中。如果文件不存在或由于不满足上述条件之一而无法读取,则函数返回NULL。 本文标题: MySQL注入本地文件(LOAD_FILE) 本文作者: 夏至未至 发布时间: 2021年2月28日 22:11 最近更新: 2022年12月24日 15:28 原文链接: 许可协议: 署名-非商业性-禁止演绎 4.0 国际(CC BY-NC-ND 4.0) 请按协议转载并保留原文链接及作者 MySQL(28) LODA_FILE(1) 请可爱的你登录后回复 评论列表 (1条) 东方不败者 2022-03-09 21:17 · IP未知 哎呀,这个问题,我也遇到过,今天试了下,确实是系统开着 SELinux,我直接暴力关闭,然后重启,果然,没有问题了,牛逼 回复 发表 查看更多评论
评论列表 (1条)
东方不败者
2022-03-09 21:17 · IP未知哎呀,这个问题,我也遇到过,今天试了下,确实是系统开着 SELinux,我直接暴力关闭,然后重启,果然,没有问题了,牛逼