关于mysql注入天书中 Background-3 导入导出相关操作的讲解 一文的一些疑惑

之前转载了一篇博文:<Background-3 导入导出相关操作的讲解>,文中,我提出了我的质疑(下文红色部分):"
Load_file(file_name):读取文件并返回该文件的内容作为一个字符串。
使用条件:
A、必须有权限读取并且文件必须完全可读
     and (select count(*) from mysql.user)>0/* 如果结果返回正常,说明具有读写权限。
     and (select count(*) from mysql.user)>0/* 返回错误,应该是管理员给数据库帐户降权 
(注,上面两段话有争议,具体请看另一篇博客)

B、欲读取文件必须在服务器上 "
当时为了保证转载的完整性,仅仅标注了质疑,这次借用这篇博客,同时在查阅大量资料的情况下阐述自己的观点。
原作者写到Load_file需要文件操作的权限,这没错,但是通过
and (select count(*) from mysql.user)>0

它的返回值来判断是否有读写文件的权限有失全面。原因有两点:

1.mysql.user本身是一张保存用户权限的表,里面包含了登入mysql数据库的各个账号的权限,其结构如下:

mysql> desc mysql.user;
+------------------------+-----------------------------------+------+-----+-----                                                                                        ----+-------+
| Field                  | Type                              | Null | Key | Defa                                                                                        ult | Extra |
+------------------------+-----------------------------------+------+-----+-----                                                                                        ----+-------+
| Host                   | char(60)                          | NO   | PRI |                                                                                                 |       |
| User                   | char(16)                          | NO   | PRI |                                                                                                 |       |
| Password               | char(41)                          | NO   |     |                                                                                                 |       |
| Select_priv            | enum('N','Y')                     | NO   |     | N                                                                                               |       |
| Insert_priv            | enum('N','Y')                     | NO   |     | N                                                                                               |       |
...                                                                                                                                                              
| File_priv              | enum('N','Y')                     | NO   |     | N                                                                                               |       |

+------------------------+-----------------------------------+------+-----+-----    

其中包含了用户名/密码/执行增删改查的权限,同时也包括了文件权限。执行(select count(*) from mysql.user)>0,并返回TRUE,个人觉得仅仅说明当前登入mysql的用户有访问mysql.user这张表的权限,同时表中内容非空。

2.想确定某一用户是否有操作文件的权限,可能需要执行下列语句:

2.1.获得当前登入mysql的用户:

mysql> select user();
+--------+
| user() |
+--------+
| root@  |
+--------+
1 row in set (0.00 sec)

2.2.获得该用户的文件权限:

mysql> select ((select file_priv from mysql.user where user='root' limit 0,1)='Y')as priv;
+------+
| priv |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

进入主题,Sqli-labs练习7后台获取id的PHP语句如下:

$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";

$result=mysql_query($sql);

如果URL中输入有效的ID,页面如下:


否则,页面呈现这样的结果:


在执行Load_file前需要准备3种payload:

1.mysql.user的访问权限:

1')) and (select count(*) from mysql.user)>0 -- 

当前用户可以访问mysql.user表

2.获取用户:

目前获取用户只能通过盲注,盲注的结果显示当前用户是:root

3.判断用户有文件权限:

1')) and (select (select file_priv from mysql.user where user='root' limit 0,1)='Y') -- 

经历以上步骤后,可以确定root用户具有操作文件的权限,接下来才能执行Load_file注入。

参考资料:MySQL Injection - Simple Load File and Into OutFile

=======================================

后记:

对于新版本的MySQL,即使当前用户拥有操作文件的权限,调用load_file以后仍有可能会返回NULL。我曾尝试在/var/www/html目录下创建一个文本文件:

执行load_file的结果如下:

mysql> select user, file_priv from mysql.user;
+------------------+-----------+
| user             | file_priv |
+------------------+-----------+
| root             | Y         |
| root             | Y         |
| root             | Y         |
| root             | Y         |
| debian-sys-maint | Y         |
+------------------+-----------+
5 rows in set (0.00 sec)

mysql> select load_file('/var/www/html/flag.txt');
+-------------------------------------+
| load_file('/var/www/html/flag.txt') |
+-------------------------------------+
| NULL                                |
+-------------------------------------+
1 row in set (0.00 sec)

查找了很多页面才了解到,高版本的mysql引入了secure-file-priv特性。secure-file-priv参数是用来限制LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE()传到哪个指定目录的。
1.当ure_file_priv的值为null ,表示限制mysqld 不允许导入|导出;
2.当secure_file_priv的值为/tmp/ ,表示限制mysqld 的导入|导出只能发生在/tmp/目录下;
3.当secure_file_priv的值没有具体值时,表示不对mysqld 的导入|导出做限制。

此开关默认为NULL,即不允许导入导出。查看secure-file-priv参数的值:

mysql> show global variables like '%secure%';
+------------------+-----------------------+
| Variable_name    | Value                 |
+------------------+-----------------------+
| secure_auth      | OFF                   |
| secure_file_priv | /var/lib/mysql-files/ |
+------------------+-----------------------+
2 rows in set (0.00 sec)

解决方案:

windows下:修改my.ini 在[mysqld]内加入secure_file_priv =
linux下:修改my.cnf 在[mysqld]内加入secure_file_priv =
然后重启mysql,再查询secure_file_priv

mysql> show global variables like '%secure%';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| secure_auth      | OFF   |
| secure_file_priv |       |
+------------------+-------+
2 rows in set (0.00 sec)

mysql> select load_file('/var/www/html/flag.txt');
+-------------------------------------+
| load_file('/var/www/html/flag.txt') |
+-------------------------------------+
| flag!
                              |
+-------------------------------------+
1 row in set (0.00 sec)
除了mysql的这个配置项,ubuntu的一项安全策略也可能导致load_file返回NULL,它就是AppArmor安全模块。使用apparmor_status命令检查AppArmor的安全策略:
$ sudo apparmor_status
apparmor module is loaded.
6 profiles are loaded.
6 profiles are in enforce mode.
   /sbin/dhclient
   /usr/lib/NetworkManager/nm-dhcp-client.action
   /usr/lib/connman/scripts/dhclient-script
   /usr/sbin/mysqld
   /usr/sbin/ntpd
   /usr/sbin/tcpdump
0 profiles are in complain mode.
2 processes have profiles defined.
2 processes are in enforce mode.
   /usr/sbin/mysqld (27816) 
   /usr/sbin/ntpd (31952) 
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.
当前AppArmor设置都保存在  /etc/apparmor.d/目录下。关闭AppArmor的某项设置的命令形如:
sudo ln -s /etc/apparmor.d/{profile.name-here} /etc/apparmor.d/disable/
sudo apparmor_parser -R /etc/apparmor.d/{profile.name-name-here}
关闭AppArmor对mysql的保护:
sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/
sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld
再次检测AppArmor的状态:
sudo aa-status
apparmor module is loaded.
5 profiles are loaded.
5 profiles are in enforce mode.
   /sbin/dhclient
   /usr/lib/NetworkManager/nm-dhcp-client.action
   /usr/lib/connman/scripts/dhclient-script
   /usr/sbin/ntpd
   /usr/sbin/tcpdump
0 profiles are in complain mode.
1 processes have profiles defined.
1 processes are in enforce mode.
   /usr/sbin/ntpd (31952) 
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.
如果想要打开AppArmor对mysql的保护作用,运行下列命令:
sudo rm /etc/apparmor.d/disable/usr.sbin.mysqld
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.mysqld




猜你喜欢

转载自blog.csdn.net/lixiangminghate/article/details/80549068