SQL注入
原理
注入攻击的本质是把用户输入的数据当做代码执行
判断注入点
- and 1=1页面正常,and 1=2 页面不正常【此法可能会被拦截】
为什么用and 1=1正常 and 1=2报错来判断是否存在SQL注入?
因为如果存在SQL注入,那么and就是和的意思,1=1是一个恒等式,然后因为原本能够查出数据,那么两个真就是True,但是1=2肯定是不可能的,这里就会返回一个False,然后因为和必须两个真才返回True,所以这里拼接就不成立返回False
- url后面加
'
,看是否报错
闭合,不一定都是单引号,也可能是双引号,括号
- 如果是数字型传参,尝试-1,
?id=2-1
显示id=1的页面 - or sleep(5)
Mysql5.0以上版本特征
有information_schema这个系统自带库,保存着关于MySQL服务器所维护的所有其他数据库的信息,如数据库名、数据库表等等
information_schema.tables 存放表名和库名的对应
information_schema.columns 存放字段名和表名的对应
报错注入(联合查询)
- 判断当前页面字段总数:
and 1=1 order by 1,2,3,4,5
order by 用于判断显示位,order by 原有的作用是对字段进行一个排序,在sql注入中用order by 来判断排序,order by 1就是对一个字段进行排序,如果一共四个字段,你order by 5 数据库不知道怎么排序,于是乎就错误了无返回值
- 判断显示位:
and 1=2 union select 1,2,3
两张表联合查询的字段数必须相同
- 查当前数据库:
and 1=2 union select 1,2,database()
- 查表名:and 1=2 union select 1,2,table_name from information_schema.tables where table_schema=database() limit 0,1`
limit 在注入中用于排序然后输出,limit a,b a代表了从哪个位置(从0开始) b代表从那位开始显示几条数据。limit n,m : 从n+1条数据取m条
- 查列名:
and 1=2 union select 1,2,column_name from information_schema.columns where table_name=表名 and table_schema=database() limit 0,1
- 查字段:
and 1=2 union select 1,字段名,字段名 from 表名 limit 0,1
group_concat
:将多行数据整合在一行输出
注释:--
,#
,/*
POST注入
高危点:登录框,查询框,各种与数据库有交互的框
经典万能密码:'or 1=1#
原理:select username,password from users where username='admin' and password = ' 'or 1=1%23' limit 0,1
where后面是条件,username和password之间是and连接,所以两个有一个为否返回就是否,但是or 1=1,这个返回真,否 or 真=真。用一个单引号使前面的语句报错,后面的or表示或者 句子为或1=1,为真,所以登陆正确
sqlmap如何对POST注入进行注入
HEAD注入
利用php的全局变量$_server获取用户的相关信息且将数据存入数据库,利用updatexml函数输入sql语句,返回信息
PHP超全局变量
常用的:$_SERVER
updatexml()
:更新xml文档的函数
语法:updatexml(目标xml内容,xml文档路径,更新的内容)
payload:updatexml(1,concat(0x7e,(select database()),0x7e),1)
0x7e为~为拼接作用,有了这个拼接的特殊符号才会报错
updatexml实际上是一个报错注入,因为路径不存在所以报错了。但是因为数据库先执行子查询,所以报错的信息中有查询出来的信息会被报错处理
head注入的利用点:user-agent,ip,Referer ,X-Forwarded-For等等
盲注
即服务器没有错误回显的时候完成注入攻击
布尔盲注:根据输入信息返回TRUE或者FALSE。根据返回页面的正确与否,通过判断对应字符的ascii码值是否对应,来判断字符串具体的数值
时间盲注: 界面只会返回TRUE,加入特定的时间函数,通过查看web页面返回的时间差来判断注入的语句是否正确
函数:
substr(字符串内容,从哪切,切多长)
延时注入和布尔盲注没什么区别,操作上多一个if来延时
宽字节注入
数据库使用GBK编码可能存在宽字节注入。PHP发送请求到MySQL时使用了语句set names 'gbk' 或者 set character_set_client =gbk进行了一次编码,但是由于一些不经意的字符集转换导致了宽字节注入
gbk编码:占用两个字节
utf-8编码:占用三个字节
PHP防御函数:magic_quotes_gpc
,给post,get,cookie过来的数据增加转义字符\
做一定的过滤
为了绕过这个反斜杠,想到传参一个字符凑成一个gbk字符,\
的编码是%5c,比如凑一个%df%5c
过滤原理:PHP发送请求到mysql时经过一次gbk编码,PHP会将获取到的数据进行魔术引号的处理,因为GBK是双字节编码,所以我们提交的%df这个字符和转译的反斜杠组成了新的汉字,然后数据库处理的时候是根据GBK去处理的,然后单引号就逃逸了出来。已知我们的提交数据会被加入\,\的编码为%5c,我们在后面加上%df后变为了%df%5c,变成一个繁体汉字運,变成了一个有多个字节的字符。因为用了gbk编码,使这个为一个两字节,绕过了单引号闭合,逃逸了转义
小tips:有时候可以采用hex来代替字符串
当程序员设置数据库和php编码相同不会有宽字节注入。宽字节要基于这两个不同才能实现,PHP utf-8编码 数据库GBK编码(编码方式可以不止是gbk这些)
开启魔术引号:找到php.ini配置文件,magic_quotes_gpc=on
,低版本默认开启,高版本被废除了