一:基础知识
1.注入分类
1.1根据注入点分
数值型注入(不需要考虑闭合)和字符型注入,搜索型注入(即文本框注入)。
1.2根据注入方式分
联合注入,报错注入,盲注,二次注入,堆叠注入,宽字节注入。
1.3根据请求方式注入分
GET型注入、POST型注入、HEADER型注入,Cookie注入。
注:时间盲注又有一种代替方式,叫带外注入。
2.注入产生的原理
攻击者通过浏览器或者其他客户端将恶意SQL语句插入到网站参数中,而网站应用程序未对其进行过滤,将恶意SQL语句带入数据库使恶意SQL语句得以执行,从而造成SQL注入。
2.1条件
用户能控制输入同时原本要执行的代码,会拼接用户输入的SQL语句。
2.2 SQL注入过程
首先将参数值等数据进行修改,然后将未经检查和过滤被修改的数据注入到sql语句命令中,再接着数据库执行被修改后的sql语句,最后服务器将注入的结果返回给客户端。
2.3注意点
任何能与数据库交互的地方都有可能产生SQL注入。
//注释符也可以用--空格,但在URL中输入时,如果在最后加上-- ,浏览器在发送请求的时候会把URL末尾的空格舍去,所以我们用--+代替-- ,原因是+在URL被URL编码后会变成空格。
3.漏洞危害
3.1危害一
通过SQL注入获取服务器的库名、表名、字段名、数据库版本、操作系统等。
3.2危害二
通过SQL注入获取数据库中数据信息,进行脱库操作。
3.3危害三
当通过SQL注入获取到写入权限后可以进行网页篡改、木马及后门植入等恶意操作。
4.SQL注入防范
4.1代码层
对输入进行严格的转义和过滤
4.2网络层
WAF防护
5.常用的系统函数
5.1version()--mysql版本
5.2user()--数据库用户名
5.3database()--数据库名
5.4@@datadir--数据路径
5.5@@version_compile_os--操作系统版本
5.6current_user()--返回当前用户名
5.7system_user()--返回系统用户名
6.信息收集
6.1网站路径信息
Burp或者SQLmap进行网站爬取。
6.2操作系统判断
Windows对大小写不敏感,Linux对大小写敏感。
6.3数据库类型判断
方法一:分析response里面的sever。
方法二:根据前端编写判断
aps:SQL Server,Access
.net:SQL Server
php:MySQL,PostgreSQL
Java:Orecle,MySQL
方法三:扫描端口判断(namp)
Orecle:默认端口1521
SQL Server:默认端口1433
MySQL:默认端口3306
Pointbase:默认端口9092
DB2:默认端口5000
Access:它属于文件型数据库,所以不需要端口号。
方法四:根据注释符判断
MySQl:/*、--、#。
Orale和SQL Server:--。
“;”:是子句查询标识符,Oracle不支持多行查询。
方法五:存在注入点的条件下,根据数据库特有数据表判断。
方法六:根据其返回的错误类型判断。
方法七:根据数据库特有的函数判断。
6.4数据库版本
方法一:查看数据头来查看数据库及其版本,response里面的sever。
注:但有可能屏蔽了看不见
方法二:根据不同版本数据库特点判断。
7.判断是否有注入点
7.1新方法一
SELECT * FROM users WHERE id=1 and 1=1 LIMIT 0,1 页面正常
SELECT * FROM users WHERE id=1 and 1=2 LIMIT 0,1 页面不正常
7.2老办法二
?id=1 and 1=1 页面正常
?id=1 and 1=2 页面不正常
7.3方法三
通过构造get、post、cookie请求再相应的http头信息等查找敏感。
7.4方法四
用数据库逻辑运算来判断(有传入参数的时候用)
如:and 1=1 页面正常访问 得出真且真为真
and 1=2 页面访问错误 得出真且假为假
说明我们的语句有写入进去,可能存在注入点。
如果以上都是正常显示页面,说明没有被写入进去。
7.5字段判断
数字型
and 1=2–+ |
字符型
'and 1=2–+ | "and 1=2–+ | )and 1=2–+ |
')and 1=2–+ | ")and 1=2–+ | "))and 1=2–+ |
注:判断上面类型的注入,–+可以用#替换,url 提交过程中 Url 编码后的#为%23,–+或#的作用是用于结束后面的语句执行。
注:判断字符型和数字型,数字and 1=2 是能够进行计算的所以1=2是不成立的返回错误,若返回正确则是字符型,具体字符型需要如何闭合,就需要进行测试。
7.6明确参数类型
干扰字符:'、"、%、)、}等,具体需要进行测试。
判断情况:
url后面是字符,那么里面可能就是字符型注入。
url后面是数字,可能是字符型或数字型,具体需要进行测试判断。
8.常用字符串连接函数
8.1concat(str1,str2,.......)
没有分隔符连接字符串(一般的我们都要用一个字符将各个项隔开,便于数据的查看)。
8.2concat_ws(分隔符,str1,str2,.......)
含有分隔符连接字符串。
8.3group_concat(str1,str2,........)
连接一个组的所有字符串,并以逗号分隔每一条数据。
- 一般用于尝试语句
or 1=1--+ | 'or 1=1--+ | "or 1=1--+ |
)or 1=1--+ | ')or 1=1--+ | ")or 1=1--+ |
"))or 1=1--+ |
解释:一般的代码为
$id=$_GET['id'];
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
此处考虑两个点,一个是闭合前面你的‘另一个是处理后面的‘,一般采用两种思路,闭合后面的引号或者注释掉,注释掉采用--+或者#。
注:--+可以用#替换,url提交过程中url编码后#为%23。
10.高权限注入及低权限注入
10.1MySQL权限分类
MySQL中分为:root(最高权限)、普通用户。
10.2普通用户权限
普通用户只能操作自己的数据库。
10.3root用户权限
root用户不仅可用操作自己用户,还可用跨库操作、文件读写、常规查询。
11.union操作符
11.1union介绍
union:操作符用于合并两个或者多个select语句的结果集。
注:union内部的select语句必须与前面的语句拥有相同数量的列,并且列对应的数据类型要相似,及顺序需要相同,所以一般要先判断字段数。
11.2union使用示列
如:select column_name(s) from table_name(1)
union
select column_name(s) from table_name(2)
注:默认地,union操作符选取不同的值。如果允许重复的值,请使用union all。
注:union结果集中的列名总是等于union中第一个select语句的列名。
12.order by的作用和语法
12.1Order by介绍
Order by作用:按一个或者多个字段排序查询结果,可以是升序也可以是降序,默认为升序。
12.2order by语法
SELECT * FROM score ORDER BY math ASC
13.sql中的运算
13.1优先级
优先级由高到低的顺序为:()、not、比较运算符、逻辑运算符、&的优先级大于=。
注:and比or先运算,如果同时出现并希望先算or,需要结合()使用。
14.手工注大概入流程
14.1判断注入类型
先找到注入点,确认目标是数值型还是字符型注入漏洞(可用尝试语句)。
14.2猜字段数
由于联合查询需要前后的查询字段相同,所有确定注入类型后需要确定前面语句的字段数。(用到order by()函数:用来判断字段数)
注:在查询中经常会添加and 1=2,否则,经过联合查询后,会返回多行数据。很多应用程序只返回查询到的第一天结果,显示的还是原来程序正常的数据,而联合查询结果集中的其他数据就不会显示出来,这样就无法判断是哪一列在前端显示数据。
如:index.php?id=1 and 1=2 union select 1,2,3
14.3判断回显位即可显示的字段
因为回显只能显示一组数据,所以一般把参数ID置空,根据得到的字段数使用union联合查询,判断回显位。(union select)
14.4获取数据库的基本信息
通过替换union select后面的参数来查询的信息,如version()、database()等。
14.5获取数据中的信息。
数据库名>表名>字段名>数据
14.6解密
二:读写文件相关操作
1.读写文件流程
先找到路径---再执行文件的读写操作
2.常见文件路径获取方法
2.1报错显示
单引号爆出路径;错误参数值爆出路径。
缺点:现在很多错了都没有回显了,所有概率很小。
2.2通过搜索引擎获取
如:百度inurl:iqiyi.com warning
inurl:iqiyi.com "error"(或者“fatal error”)
缺点:效率低。
2.3遗留文件
php常见遗留的测试文件:/test.php;/ceshi.php;/info.php;/phpinfo.php;/php_info.php;/1.php;/x.php。
方法:利用扫描工具扫描
2.4漏洞报错
知道网站是用什么cms或者框架进行搭建的,用搜索引擎去找到对应的爆路径方式,比如phpcms爆路径。
2.5通过扫描工具
通过burp、sqlmap等扫描工具扫描得到网站的map。
2.6爆破
无任何突破点,就可以运用一些常见固定的可能安装位置生成字典,对目标网站进行爆破。
eg:windows:d:/www/root/xxx/
linux:/var/www/xxx
注:知道路径后,再执行文件的读写操作。
3.文件读操作
注:防止转义可以将\改为\\或者/。
3.1load_file()函数
读取文件返回该文件的内容作为一个字符串。
语法:load_file(file_name)
file_name(必需。网站相关文件的完整路径)
3.2执行条件
(1)必须有读取权限并且文件必须完全可读。
查看是否有写入权限:show global variables like '%secure_file_priv%';
NULL 不允许导入或导出
/tmp 只允许在/tmp目录导入导出
空 不限制目录
(2)欲读文件必须在服务器上。
(3)必须指定文件完整路径即绝对路径。
(4)load_file()函数操作文文件目录是@@datadir(即数据库存储路径)
(5)欲读文件必须小于传送数据包的过程当中最大允许的数据包大小。
注:当文件不存在,或者不满足使用条件之一而不能读出,函数返回空。
3.3遇到null时的处理方式
在mysql配置文件修改为secure_file_priv=并再次查询,即可写入。
3.文件写入操作
3.1into outfile “想写的路径”
可以写入多行数据,并且字段和行终止符都可以作为格式输出。
3.2into dumpfile “想写的路径”
只能写一行,并且输出中不存在任何格式。
3.3load data infile
用于用于高速地从一个文本文件中读取行,并装入一个表中。文件名称必须为一个文字字符串。
4.常见问题
4.1魔术引号开关(常见的防注入手段)
(magic_quote_gpc=On):判断解析用户提交的数据,有post、get、cookie数据时会增加转义字符“\”。
php内置函数:Addslashes()函数返回在预定义字符之前添加反斜杠的字符串,预定义字符有:单引号、双引号、反斜杠(\)、NULL。
处理方法:可以使用编码(把路径进行编码然后替换编码后的)或宽字节绕过。
4.2没有权限
三:参数类型注入
1.数字型
1.1介绍
数字型不需要考虑单引号等进行闭合问题。
1.2判断数字型注入
输入单引号,不正常返回。
输入and 1=1,正常返回。
输入and 1=2,不正常返回。
当输入的返回结果与扫描相符,说明可能存在数字型注入。
2.字符型
2.1介绍
字符串本身前后自带引号进行闭合,一般需要加引号闭合前面引号,后面的引号通过加引号闭合或者直接注释掉。
2.2判断字符型注入
如用单引号闭合时
输入单引号,不正常返回。
输入’and ‘1’ = ’1,正常返回。
输入’and ’1’ =’2,不正常返回。
当输入的返回结果与扫描相符,说明可能存在数字型注入。
3.搜索型
3.1介绍
搜索处对于输入的字符串对于在sql语句中变为’%字符串%’了,所以为了能注入就要过滤引号(‘)和百分号(%).闭合前面的引号后加入注入语句,再注释掉后面的。
注:sql语句干扰符号: ',",s,),}等,具体需看写法。
4.JSON型注入
4.1介绍
JSON是存储和交换文本信息的语法,是轻量级的文本数据交换格式。类似XML,但JSON比XML更小、更快,更易解析。所以现在接口数据传输都采用JSON方式进行。JSON文本的MIME类型是"application/json"。
JSON可以将JavaScript中的对象转换为字符串,然后在函数、网络之间传递这个字符串。
4.2 JSON语法规则
数组(Array):用方括号(“[]”)表示。
对象(0bject):用大括号(“{}”)表示。
数据在名称/值对(name/value)中。
名称(name)置于双引号中,值(value)有字符串、数值、布尔值、null、对象和数组。
并列的数据之间用逗号(,)分隔。
4.3 JSON构建于两种结构
第一种:”名称/值”对的集合。它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。
如:使JSON最简单的Key-Value示例(名称-值对,键值对):
{"Username":"xsser"}
{"Username":"xsser","Password":"12345","Email":"1234@st.com"}
第二种:值的有序列表。在大部分语言中,它被理解为数组(array)
如:表示一个管理员表,在JSON中表示
{"Users":[
{"Username":"zhangsan","Password":"12345","Email":"12345@st.com"}
{"Username":"lisi","Password":"123123","Email":"123123@st.com"}
{"Username":"wangwu","Password":"321321","Email":"321321@st.com"}
] }
4.4 JSON型注入注意点
注意值的数据类型,如果是数字的注入时可以不加闭合符,如果是字符的话,注入时需要加上闭合符。并不是看json语法的”。
4.5 JSON注入方式
json={}在跨括号里面进行注入测试,是否需要闭合根据它对应sql语句的写法进行判断。
如:Post data:josn{"username":"admin'"} 报错
Post data:josn{"username":"admin' and 1=0%23"} 查询为空
Post data:josn{"username":"admin' and 1=1%23"}
Post data:josn{"username":"admin' and 1=2 union select database(),2%23"}
注:对影响json语句的要进行转义,如双引号、花括号等。
四:请求方法注入(HTTP头部注入)
1.基础知识
1.1常见请求方法
GET、POST请求方法。
1.2注意点
Cookie,Request,Http头等。
不同的请求方法对应的请求数据类型或者大小不同,要考虑开发人员设定的特定的过滤机制。
1.3查看数据包方法
可以在浏览器带的开发人员工具里的网络处查看数据包信息也可用burpsuite抓包。
2.GET和POST的区别
3.POST注入
3.1POST注入原理
POST方式提交通过对输入框进行传参,可以被带入数据库进行的查询。
3.2场景
登录框、更改密码、注册、查询框、各种和数据库有交互的框。
3.3注意点
GET请求中注释使用--+,POST请求中注释使用#或者--。
因为POST的情况下,最后一个空格,可以直接用空格,不用+来代替,因为POST参数空格会自动转成+,而GET不会。同时GET不用#注释,当请求时,“#”会被识别为锚链接,无法传递至SQL语句中。
3.4注入方式
第一步:判断是否存在注入点,如输入’显示错误,说明可能有,符号为’。
第二步:在工具上点击勾选post data,再进行尝试输入注入语句。
第三步:不断的执行正常的注入流程,进行获取数据。
注:在代码中,账号输入框和密码输入框是连着的在第一个代码框最后注释掉后面内容后,就不需要输入密码了。
如:sqli-labs-master less-11的题目。
注:GET方式提交就是直接在网址后面加上需要注入的语句。
3.5思路
使用配合bp抓包修改相关数据。
4.Cookie注入
4.1 cookie介绍
Cookie是在HTTP协议下,服务器或脚本可以维护客户工作站上信息的一种方式。通常被用来辨别用户身份、进行session跟踪,最典型的应用就是保存用户的账号和密码用来自动登录网站。
4.2 cookie注入条件
条件一:程序对GET和POST提交方式的数据进行了过滤,但未对cookie提交的进行过滤。
条件二:程序对提交数据获取方式是直接request("xxx")的方式,未指明使用request对象的具体方法进行获取。
4.3场景
服务器需要对cookie字段进行获取,以验证客户端的身份。
4.4注入方式
提交的参数以cookie的方式提交,通过工具抓包在cookie上判断是否有注入点,如果有则进行注入。
如:sqli-labs-master less-21的题目。
4.5 cookie加密解密注入
当cookie值被进行加密后,我们需要将注入语句以同样加密方式进行注入,如果以正常语句注入会报错。
4.6 Coookie与Session的区别
cookie存放在客户端,而session存放在服务器端。
cookie因为保存在客户端本地,因此存在被拦截或者修改的风险。
session因为存放在服务器端,更安全,但用户量越大,服务器压力也越大。
cookie的存储限制了数据量,只允许4KB,而session是无限量的。
5.HeaDer型注入
5.1 User-Agent注入
(1)Usre-Agent介绍
简称UA,是一种向访问网站提供你所使用的浏览器类型、操作系统及版本、CPU 类型、浏览器渲染引擎、浏览器语言、浏览器插件等信息的标识。
(2)条件
存在User-Agent参数的调用,未被过滤。
(3)注入方式
当提交的参数是以User-Agent的方式提交时,通过工具抓包在User-Agent上判断是否有注入点,如果有则进行注入。
5.2 Referer注入
(1)Referer介绍
Referer是指示一个请求是从哪里链接过来的。
(2)条件
存在Referer参数的调用,未被过滤。
(3)注入方式
Referer注入是提交的参数以referer的方式提交,通过工具抓包在User-Agent上寻找注入点,然后进行注入。
5.3 XFF注入
(1)XFF介绍
XFF全称x-forwarded-for,它代表了客户端的真实IP,通过修改它的值可以伪造客户端IP。
(2)条件
存在XFF参数的调用,未被过滤。
(3)注入方式
XFF注入是提交的参数以XFF的方式提交,通过工具抓包在XFF上,进行本地IP地址修改,为其带入的IP地址加入敏感字符查看是否存在注入点,然后进行注入。
五:报错注入
1.报错注入介绍
利用数据库的某些机制,人为的制造错误条件,使得查询结果能够出现在错误信息中。
2.报错注入条件
联合查询需要页面有回显,当某些不提供回显,只提供SQL报错信息的情况下,联合查询则无法查到需要的数据。
3.利用xpath语法错误
3.1 extractvalue()函数
用于对xml文档进行查询
语法:extractvalue(目标xml文档,xml路径)
注:第二个参数要求是符合xpath语法的字符串才能进行正常查询。
注入思路:因为xml文档名错误是不会进行报错的,所以当xml路径这个参数不是xml路径时或者xml路径语法有问题,则会报语法错误提示信息,但信息不完整的,需要在开头结尾拼接一个xpath无法处理的字符(如~对应十六进制的0x7e),即可显示完整信息。
如:select extractvalue(1,(select user())) from user;
---因为语法问题会报错,但错误提示信息不完整--
select extractvalue(1,concat(0x7e,(select user()))) from user;
--利用~字符即0x7e,并通过concat函数将~与select user()查询的结果进行拼接成字符串,使报错信息中携带完整的查询信息在后续只需将查询参数依次替换为想要查询的数据即可--
注:extractvalue()能查询字符串的最大长度为32,如果我们想要的结果超过32,就要用substring()函数截取或limit分页。
3.2 updatexml()函数
更新xml文档
语法:updatexml(目标xml文档,xml路径,更新内容)
注:第二个参数要求是符合xpath语法的字符串才能进行正常查询。
注入思路:updatexml函数报错注入的原理和extractvalue函数是相通的。受影响的只有xml路径。
3.3 floor()函数
floor(X)返回不大于x的最大整数值。
3.4 rand函数
rand()返回一个0~1的随机数。
3.5 count()函数
统计元组(列)的个数。
六:盲注
1.盲注介绍
盲注是注入的一种,指的是在不知道数据库返回值的情况下对数据中的内容进行猜测,实施SQL注入。
2.盲注分类
基于布尔盲注、基于时间的盲注、基于报错的盲注
3.基于布尔盲注
3.1原理
因为页面只返回true和false两种类型页面,利用页面返回不同,逐步猜解数据。
3.2常用函数
mid、substr、substring、left、right、ascii、ord、finull、like、regexp、length。
(1)mid()函数
从字符串中提取子字符串。
语法:mid(string,start,length)
string(必需。要从中提取的字符串)
start(必需。规定起始位置,起始值是 1。 可以是正数或负数。 如果是正数,则此函数从字符串的开头提。 如果是负数,此函数从字符串的末尾提取)
Length(必需。要提取的字符数)
注:string可以为自行构造的sql语句。
(2)substr()函数
从字符串中提取子字符串(从任意位置开始)。
语法:substr(string,start,length)
string(必需。要从中提取的字符串)
start(必需。规定起始位置,起始值是 1。 可以是正数或负数。 如果是正数,则此函数从字符串的开头提取。 如果是负数,此函数从字符串的末尾提取)
length(可选。要提取的字符数。如果省略,将返回整个字符串(从 start 位置开始))
注:string可以为自行构造的sql语句。
(3)substring()函数
从字符串中提取子字符串。
语法:substring(string,start,length)
string(必需。要从中提取的字符串)
start(必需。规定起始位置,起始值是 1。 可以是正数或负数。 如果是正数,则此函数从字符串的开头提取。 如果是负数,此函数从字符串的末尾提取)
length(可选。要提取的字符数。如果省略,将返回整个字符串(从 start 位置开始))
注:mid()和substr()函数等于substring()函数。 同时string可以为自行构造的sql语句。
(4)left()函数
得到字符串左部指定个数的字符。
语法:left(string,n)
string(必需。要截取的字符串)
n(必需。长度)
注:left(database(),1)>’a’,查看数据库名第一位,left(database(),2)>’ab’,查看数据库名前二位。string可以为自行构造的sql语句。
(5)right()函数
得到字符串右部指定个数的字符。
(6)ascii()函数
返回其中的第一个字符即最左边的 ASCII 值。
语法:ascii(character)
character(必需。要为其返回 ASCII 值的字符。 如果输入多个字符,则只返回第一个字符的值)
(7)ord()函数
同 ascii(),将字符转为 ascii 。
(8)finull()函数
根据第一个参数是否为null返回的具体值。
语法:ifnull(str1,str2)
finull(里面有两个数,如果第一个数不为null,返回str1,如果第一个数str1=null,返回str2)
(9)length()函数
返回字符串的长度。
语法:length(str)
用法:可用配合and使用length(str)>某数值值,来确认长度。
3.3通过like匹配注入
like操作符在where子句中用于搜索列中的指定模式。
一般配合:%(百分号表示零个、一个或多个字符)和_(下划线表示单个字符)
注:MS Access使用星号 (*) 代替百分号 (%),使用问号 (?) 代替下划线 (_)。
3.4通过regexp正则注入
regexp配合正则表达式进行查找。(与like类似)
3.5布尔盲注流程
(1)获取数据库名
利用left与length函数
第一步:通过left函数判断数据库版本号
第二步:通过length函数求当前数据库名的长度
第三步:通过用left函数猜数据库名从左第一位到右最后一位可能的字母,从而得出数据库名。
(2)获取表名
利用substr和ascii函数
ascii(substr())配合使用同时使用二分法进行测试。通过不断改变substr的参数测试出不同位置的字母。
(3)获取列名
利用regexp正则表达式
在获取到表名后使用regexp进行判断列名。
(4)获取数据内容
利用ord和mid函数,ord(mid)
第一步:得到数据库名然后改变相关参数去求数据库里面的表。
第二步:求当前数据库中其中一个表的长度及ASCII得出表名。
第三步:得到表名然后改变相关参数去求里面的字段名。
第四步:得出字段名再去求字段里面的数据。
4.基于时间盲注
4.1原理
时间盲注又称延迟注入,适用于页面不会返回错误信息,且只会回显一种界面,其主要特征是利用sleep函数,制造时间延迟,由回显时间来判断构造的条件是否正确。
4.2常用函数
lenght、substr、ascii、limit、sleep 、if条件。
(1)limit()函数
用于限制查询结果返回的数量。
语法:limit(i,n)
i(必需。为查询结果的索引值,默认0开始)
n(必需。为查询结果返回的数量)
(2)sleep()函数
执行延迟若干秒。
语法:sleep(seconds)
sconds(必需。毫秒)
(3)if(条件,A,B)
如果条件成立执行A 否则执行B。
注if也可用与mid、sleep等函数组合使用。If+sleep ;if+mid+sleep
(4)mysql<5.0使用benchmark()
4.3注入思路
第一步:确定是否为时间盲注,使用sleep。
第二步:如果是时间盲注,配合if语句进行查询各种信息。
5.带外注入
5.1原理
带外通道技术(OOB)让攻击者能够通过另一种方式来确认和利用没有直接回显的漏洞,攻击者无法通过恶意请求直接在响应包中看到漏洞的输出结果,带外通道技术通常需要利用漏洞来生成带外的TCP/ICMP请求,然后攻击者可用通过这个请求来提取数据。
5.2注意点
dnslog可以解决盲注不能回显问题,效率低问题,但需要最高权限。
七:堆叠注入
1.堆叠注入介绍
在解释一个SQL语句后继续构造下一条语句,使多条语句顺序执行,这就是堆叠注入。对比union或者union all,联合查询执行的语句类型使有限的,只能用执行查询语句,而堆叠注入可用执行任意的语句。
注:堆叠注入的可以运用于创建用户由于我们使用网站用户进行注入不能查看到数据库的密码但是我们可以创建用户来登录迂回的注入数据库,但是前提是网站的管理员必须是高权限才能完全创建用户。也可以使用update更新管理员用户密码。
2.堆叠注入局限性
堆叠注入的局限性在于并不是每一个环境下都可以执行,可能受到API或者数据库引擎不支持的限制,当然了权限不足也可以解释为什么攻击者无法修改数据或者调用一些程序。
八:宽字节注入
1.宽字节注入原理
1宽字节注入是利用MySql的一个特性。
2 PHP发送请求到mysql,mysql在使用GBK编码(GBK是宽字节,双字节)的时候,会认为两个字符是一个汉字(前一个ascii码要大于128,才到汉字的范围)。
3字符和转义的反斜杠组成了新的汉字,但是组成的新汉字又不是一个正常的汉字,就起到了注掉 \ 的作用。
4可以看出来是字符集不一致造成的宽字节注入。
注:宽字节注入一般用于符号被转义函数转义了,导致符号不起作用。
2.宽字节介绍
1.当某字符的大小为一个字节时,称为窄字节(ascii编码0-127);当某字符的大小为两个字节时,称为宽字节。
2.常见的GB2312、GBK、GB180303、BIG5、Shift_JIS等编码都是常说的宽字节。
3.英文默认占一个字节,汉字占两个字节。
3.常见的转义函数
3.1 addslashes()函数
对单引号(’)、双引号(")、反斜线()与x00 (NULL字符)。
3.2magic_quotes_gpc()函数
判断解析用户提交的数据,有post、get、cookie数据时增加转义字符“\”。
4.利用方式
4.1 %df
提交%df的数据会被加入\(编码为%5c),在后面加上后变为%df%5c(繁体字運),变成了一个宽字节的字符,避免了后面引号的转义。
4.2汉字
使用汉字绕过,一个汉字PHP接收后通过UTF-8编码(三字节),并和\两两配对组成两个汉字,避免了后面引号的转义。
如:sqli-labs-master less-32的题目。
5.漏洞出现条件
条件一:数据库使用了BGK等宽字节编码。
条件二:对传入的参数进行了转义。
九:二次注入
1.二次注入原理
攻击者恶意构造的数据并存储在数据库后,恶意数据被读取并进入到sql查询语句所导致的注入。
注:无法通过扫描工具或者手工测试出来,二次注入一般在审计代码过程中发现从前端或黑盒测试无法看到。
2.利用过程
2.1构造恶意语句
语句含有被转义字符的恶意查询语句。
2.2插入恶意数据
进行数据库插入数据时,对其中特殊字符进行了转义处理,在写入数据库时保留了原来的数据。
2.3二次构造语句,引用恶意数据
开发者默认存入数据库的数据都是安全的,在进行查询时,直接从数据库中取出构造的恶意数据,没有进行进一步的检验。
如:sqli-labs-master less-24的题目。
注:二次注入在没有源码的情况比较难发现,通常见于注册。
3.总结
二次注入就是由于将数据存储进数据库中时未做好过滤,先提交构造好的特殊字符请求存储进数据库,然后提交第二次请求时与第一次提交进数据库中的字符发生了作用,形成了一条新的sql语句导致被执行。
十:WAF绕过
1.WAF(Web Application Firewall)的功能
1.1审计设备
用来截取所有HTTP数据或者仅仅满足某些规则的会话。
1.2访问控制设备
用来控制对web'应用的访问,即包括主动安全模式也包括被动安全模式。
1.3架构/网络设计工具
当运行在反向代理模式,它们被用来分配职能,集中控制,虚拟基础结构等。
1.4 web应用加固工具
这些功能增强被保护web应用的安全性,它不仅能够屏蔽web应用固有弱点,而且能够保护web应用编程错误导致的安全隐患。
2.WAF特点
2.1异常检测协议
拒绝不符合http标准的请求。
2.2增强的输入验证
代理和服务的验证,而不只是限于客户端验证。
2.3白名单&黑名单
2.4基于规则和基于异常的保护
基于规则更多的依赖黑名单机制,基于异常更为灵活。
2.5状态管理
重点进行会话保护
3.常见的绕过WAF的方法
3.1大小写混合
大小写绕过只针对小写或者大写的关键字匹配技术,正则表达式大小写不敏感无法绕过。
3.2替换关键字
双关键字替换:如UNIunionON SELselectECT等。
同价词替换:如and替换为&&,or替换为||等。
特殊字符拼接:用+号拼接。
3.3不同编码
url编码
十六进制编码
Unicode编码
......................
3.4使用注释
普通注释:常见的//, -- , /**/, #, --+,-- -, ;,--a。
内联注释:/!**/只有MySQL能识别(/*!*/表示注释里面的语句会被执行)。
3.5参数污染
HPP又称重复参数污染
3.6缓冲区溢出
缓冲区溢出用于对付waf,因为有不少waf是通过c语言编写的,c语言没有缓冲区保护机制,但waf处理测试向量超出其缓冲区长度,会引发bug从而绕过。
3.7等价函数与命令
3.8特殊符号
3.9 http参数控制
3.10整合绕过
十一:SQL注入防护
1.使用预编译语句
在使用预编译语句后,SQL语句不会发生改变。
2.对输入进行严格的过滤
2.1检查数据的类型
在将变量代入到sql语句之前,先检查变量的数据类型是否正确。
2.2使用安全函数
如果用户提交的是字符串,那么检查数据类型的方法可能就不好用了,这个时候我们需要配合一些安全函数,对输入的字符串进行过滤。
3.最小权限原则
从数据库的角度来说,应该避免web直接使用root等最高权限直接连接数据库,Web应用使用的数据库账号,也不应该有创建自定义函数、操作本地文件的权限。