SQL注入和简单绕过原理详解(由北辰老哥倾情制作)
·一.SQL注入
·1.什么是SQL
@结构化查询语言(Structured Query Language)简称SQL
@SQL使我们有能力访问数据库
·2.什么是SQL注入
@用户提交的数据可以被数据库解析执行
>>SQL注入漏洞的产生需要满足以下两个条件:
1.参数用户可控:前端传给后端的参数内容是用户可以控制的。
2.参数带入数据库查询:传入的参数拼接到SQL语句,并带入数据库查询。
>>SQL注入攻击的本质:
SQL注入攻击其实就是攻击语句全都是由前台传入后台,通过浏览器的网址传入到后台数据库进行查询,通过数据库返回的值来判断你所得到的数据,这个就是SQL注入的本质。
·3.了解SQL基本语句
>>基本语句:
> mysql -h host -u user -p pass; # 登录
>select version(); #查看版本
@基本操作:
1查看数据库:
show databases;
2新建数据库test:
create database test;
3使用数据库test:
use test;
4查看表:
show tables;
5查看admin表中的字段类型:
show full columns from admin;
6查看admin表中的数据
select * from admin;
7创建一个admin的表:
create table admin(id int not null auto_increment,username varchar(100) not null,password varchar(100) not null,primart key(id));
其中后面的含义是:创建一个id,这个字段名字叫id,类型是int型,not null表示不能是空,auto_increment就是自动增长等,username是第二个字段,在定义一个字符串类型的varchar长度为100,not null表示不能是空,后面同理,最后一个primary是主键是key,key(id)表示id是主键,主键:数据库主键,指的是一个列或多列的组合,其值能唯一地标识表中的每一行,通过它可强制表的实体完整性。
8在admin表中插入数据
insert into admin(username,password) values(“admin1”,”password1”);
其中具体是插入admin中的username和password,而username和password对应的是admin1和password1。
@联合查询:
1select * from student where id = 1 union select 1,2,3,4 from admin;
#联合查询,查student表数据的同时还使用了union操作符联合起来查admin表的数据,最后返回的就是含有student表和admin表中两个表里的数据。
注意:union内部的select语句必须是拥有相同数量的列,每个列必须拥有相似的数据类型,每条select语句中的列的顺序必须相同。上面的1,2,3,4则代表了列数,如果两个表的列数不相同则会报错,必须拥有的相同的列。
2select * from student where id = 1 and exists (select username from admin);
#也是联合查询,如果存在union过滤,则可以使用exists方法尝试。and后面如果是存在的话就会返回正确,不存在就会返回错误,与and 1=1 类似;而exists运算符用于判断查询子句是否有记录,如果有一条或多条记录存在返回 True,否则返回 False。
注意理解:id = 1只是一个尝试:表中的一个是否存在id字段=1,如果后面报错,则证明语句执行进入了。
@需要注意理解:
例如一个查询语句:select * from student where 1 = 1; ,其中的where 1 = 1,由于1 = 1是永远成立的,所以返回为True条件为真,那么这条语句就相当于select * from student,返回查询student表中的所有数据。
·MySQL查询语句
1在不知道任何条件下,语句如下所示:
> select 要查询的字段名 from 库名.表名
2在知道一条已知条件时,语句如下所示:
> select 要查询的字段名 from 库名.表名 where 已知条件的字段名=’已知条件的值’
3在知道两条已知条件时,语句如下所示:
> select 要查询的字段名 from 库名.表名 where 已知条件的字段名=’已知条件的值’ and 已知条件2的字段名=’已知条件2的值
SQL语句基本操作
·一、SQL语句基本操作
·1.建表
>>主键和外键的作用:
@主键:主键保证的是数据的唯一性,能够唯一的标识一组数据的数据元素;例如说:学号、姓名、年龄、性别、课程号课程中学号是唯一的,所以可以设置它为主键。
@外键:外键保证的是数据的完整性,一组数据的主键是另一组数据的元素;主键约束了外键所在标中不能存在主键类之外的值;外键用于与另一张表的关联。能确定另一张表记录的字段,用户保持数据的一致性。比如说:A表中的一个字段,是B表的主键,就可以说是A表的外键。
>>建表基本命令:
1新建数据库test:
create database test;
2使用数据库test: (就是新建之后进入这个test数据库)
use test;
3新建创建数据库中的表:
create table 表名称
(
列名称1 数据类型,
列名称2 数据类型,
......
)
>>例如:
create table major(
mno int ,
mname varchar(20) ,
primary key(mno)
)
create table stu(
sno int ,
sname varchar(30) ,
age smallint,
sex bit,
mno int,
primary key(sno),
foreign key(mno) references major(mno)
)
@解释:
在创建的第一个表major中:mno和mname为major表中的属性,其中mno的类型为int,mname的类型为varchar(20),这里的varchar代表了可变长度的字符串,20则代表了字符串的最大长度,primary key(mno)代表了mno是主键。
在创建的第二个表stu中:sno、sname、age、sex、nmo都为stu表中的属性, 其中sno的类型为int,sname的类型为varchar,30代表了字符串的最大长度,age的类型为smallint,sex的类型为bit,mno的类型为int,其中primary key(sno)代表了sno是主键,foreign key(mno) references major(mno)代表了mno是外键,根据了major表,其中foreign key(mno)中的mno代表了stu表中的mno,而references major(mno)中的mno代表了major中的mno。
4删除数据库中的表:
drop table 表名称;
5查找一个表中的数据:
select * from 表名称;
以及:select 列名称 from 表名称
这里的*号代表:语句为查询表或视图中的所有字段,* 表示所有字段
·2.增删改
1在表中添加列:
alter table stu add qq varchar(20);
在stu表中添加一个qq的列,其中可变长度的字符串最大长度为20。其中的varchar为datatype类型。
2在表中删除列:
alter table stu drop column qq;
在stu表中删除一个qq的列。
3在表中插入数据:
insert into 表名称 values (值1, 值2,....) ;
以及:insert into 表名称(列1, 列2,...) values (值1, 值2,....);
insert into admin(username,password) values(“admin1”,”password1”);
其中具体是插入admin中的username和password,而username和password对应的是admin1和password1。
4在表中删除数据:
delete from 表名称 where 条件;
delete from stu where sno = 1;
其中stu为表名,where后面接的是条件,当sno=1时候则删除这条数据。
@注意:在处理有外键删除时,需要先把别的表有外键的先置成null update。
>update stu set mno = null where mno = 1
5更新或者修改表中的数据:
update 表名称 set 列名称 = 新值 where 列名称 = 某值
·3.order by-聚集函数-group by
注意:where子句不能用聚集函数作为条件表达式
1默认升序/降序:
order by 列名
order by 列名 desc
order by语句用于根据指定的列队结果集进行排序;order by语句默认按照升序对记录进行排序。如果希望按照降序对记录进行排序,可以使用desc关键字。
@注意:order by 1或者order by 2中其实1表示第一个栏位,2表示第二个栏位。如果当表中只有2个栏位时,order by 3就会报错。
2count(*)函数:返回在给定的选择中被选的行数(一个表统计有多少行)
select count(*) from table
3group by函数:用于结合合计函数,根据一个或多个列对结果集进行分组。
·4.多表查询
1等值连接查询:
例如: select stu.*,sc.* from stu,sc where stu.sno = sc.sno
其中stu和sc为stu表和sc表,这两个表中有相同的字段,where子句中连接两个表的条件称为连接条件,比如stu表中有sno,sc表中sno,所以用sno来连接这两张表。
2左外连接查询:(left outer join)
例如: select stu.*,sc.* from stu left outer join sc on stu.sno = sc.sno
其中stu和sc为stu表和sc表,stu表中的sno和sc表中的sno是相同的字段,所以以stu.sno=sc.sno为连接条件,进行查询。查询结果:将stu表的记录都查询出来,sc表中sno等于stu表中的sno也都查询出来。
定义:是以左表为基础,根据ON后给出的两表的条件将两表连接起来。结果会将左表所有的查询信息列出,而右表只列出ON后条件与左表满足的部分。
3嵌套查询:一个查询语句(select-from-where)查询语句块可以嵌套在另外一个查询快where子句中,称为嵌套查询。其中外层查询也称为父查询,主查询。内层查询也被称子查询,从查询。
例如:找出至少一门课程的成绩在90分以上的女学生的姓名
select SName from Student where sex=’女’ and Sno not in(select Sno from Stduy where Grade<90)
已知的是分数大于90分这个条件,通过这个条件找出Study表中大于90分所对应的Sno,再通过连接查询Study表中对应的Sno的SName。
注意:前面的select语句是主查询,后面()中select是子查询。这里子查询返回的Sno可能有多个,所以要用到谓词“in”,如果用“=”,则报错,因为“=”表示子查询的返回值是唯一的。
>exists嵌套查询:
select * from 表名称 where exists 子查询
exists是sql中的逻辑运算符号。如果子查询有结果集返回,那么就为Ture。exists代表“存在”的意义,它只查找满足条件的那些记录。一旦找到第一个匹配的记录后,就马上停止查找。
其实子查询是一个首先的select语句,不允许有compute子句和intno关键字,exists的意思是:子查询是否有结果集返回。
例如:select sname from stu where exists(select * from sc where cno=’20201’ and stu.sno=sc.sno)
4集合查询:union、intersect的嵌套查询
>union查询:(union默认无重复,如果需要结果有重复的,则在union后加all)
select 列名称 from 表名称1 union select 列名称 from 表名称2
union可以对两个或多个结果集合进行连接,形成“并集”,其中并操作就是集合中并集的概念。子结果集所有的记录组合再一起形成新的结果集,例如:属于集合A或集合B的元素的总和就是并集。
@限定条件:要是用union来连接结果集,有4个限定条件。
a.子结果集要具有相同的结构。
b.子结果集的列数必须相同。
c.子结果集对应的数据类型必须可以兼容。
d.每个子结果集不能包含order by和compute子句。
>intersect查询:
select 列名称 from 表名称1 intersect select 列名称 from 表名称2
intersect可以对两个或者多个结果集合进行连接,形成“交集”,其中交操作就是集合中交集的概念。属于集合A且属于集合B的总和就是交集。
@注意:intersect和union的操作的嵌套查询要求属性具有相同的定义,包括类型和取值范围。
·5.视图
>>什么是视图?
在SQL中,视图是基于SQL语句的结果集的可视化的表。
视图包含行和列,就像一个真实的表。视图中的字段就是来自一个或多个数据中的真实的表中的字段。可以向视图添加SQL函数、where以及join语句,也可以提交数据,就像这些来自于某个单一的表。
@注释:数据库的设计和结构不会收到视图的函数、where或join语句的影响。
>创建视图:
create view view_name as
>查找视图:
select 列名称 from 表名称 where condition
>可以通过drop view命令来删除视图
drop view view_name
·SQLMAP工具命令:
@cookie注入:sqlmap.py -u 注入点 --cookie "参数" --tables --level 2
@POST登录框注入:
sqlmap.py -r 从文件读取数据 -p 指定的参数 --tables
sqlmap.py -u 登录的地址 --forms 自动判断注入
sqlmap.py -u 登录的地址 --data "指定参数"
–u #注入点
–columns #列出字段
–current-user #获取当前用户名称
–current-db #获取当前数据库名称
–users #列数据库所有用户
–passwords #数据库用户所有密码
–U #指定数据库用户
–dbs #列出所有数据库
–tables -D “” #列出指定数据库中的表
–columns -T “user” -D “mysql”
#列出mysql数据库中的user表的所有字段
–union-check #是否支持union 注入
–union-cols #union 查询表记录
–union-test #union 语句测试
–union-use #采用union 注入
–union-tech orderby #union配合order by