CTFWeb篇10-MySQL注入

如何发现SQL注入漏洞

使用注释符

  • 在注入时使用注释符,主要是为了消除原始查询中剩余的部分,防止语法错误。MySQL中使用-- (注意末尾空格)或#
  • 若应用过滤空格,可用/**/注释符替代

单引号测试

  • 在输入框的输入点添加一个'(单引号),观察页面是否报错。
  • 预期结果:
    • 存在漏洞:页面返回数据库错误(如MySQL、SQL Server的报错信息)。
    • 无漏洞:页面正常或显示通用错误(如“参数错误”)
  • 示例:URL/?id=1'
  • 报错原因:SQL语句中单引号未闭合
  • 为什么存在漏洞:如果应用直接将数据库的报错信息显示给用户,说明输入没有被过滤或转义,可能存在注入漏洞,数据库报错说明用户输入直接影响到了SQL语句的结构,导致语法错误
  • 注意:并非所有返回错误的情况都是SQL注入漏洞
    • 例如,应用可能自己检测到非法输入并返回错误页面,这时候的错误信息并不是来自数据库,而是应用层控制的
    • 因此,关键要看错误信息的内容是否是数据库特定的,比如MySQL的错误信息会有“You have an error in your SQL syntax”这样的提示

布尔测试(真/假条件判断)

  • 原理:构造一个恒真或恒假的条件,观察页面响应差异
  • 恒真条件:' AND 1=1 --
    • 如果页面正常显示,说明条件被接受
  • 恒假条件:' AND 1=2 --
    • 如果页面无数据或异常,说明条件生效
  • 两者结果一致 → 可能无漏洞或需进一步测试
  • 为什么存在漏洞:如果应用程序没有正确过滤输入,攻击者的条件会被拼接到SQL语句中,从而改变查询的原始逻辑。例如,永真条件会让WHERE子句始终成立,而永假条件则让查询结果为空。攻击者注入的AND 1=1或AND 1=2会被拼接到SQL语句中,直接影响查询逻辑
  • 考虑到盲注的情况,即页面没有明显回显,但通过真假的响应差异(如页面内容的不同、HTTP状态码的变化,或者响应时间的差异)来判断。这时候布尔测试尤为重要,因为它不依赖错误信息或数据回显
  • 适用场景:
    • 页面无显式回显:无法通过UNION SELECT直接显示数据
    • 无数据库报错信息:错误信息被屏蔽,无法触发Error-Based注入
    • 盲注环境:仅能通过页面内容、HTTP状态码或响应时间差异间接推断结果
  • 局限性:
    • 依赖响应差异:若真/假条件响应无区别,无法判断漏洞
    • 效率较低:盲注需逐字符猜测,耗时较长
    • 过滤绕过:若关键词(如AND、OR)被过滤,需使用替代方案(如&&、||)

联合查询测试(Union-Based)

  • 尝试通过 UNION SELECT 联合查询获取数据
  • 适用场景:页面会回显数据库查询结果(如文章详情页)
  • 步骤:
    • 确定字段数:order by
    • 联合查询测试回显位:union select 1,2,3
  • 为什么要联合查询测试回显位:回显位指的是网页上显示数据库查询结果的位置。当进行联合查询时,攻击者需要确定他们的注入查询结果会显示在网页的哪个位置,这样才能有效地提取数据
    • 通过测试不同的列数,并观察页面变化,攻击者可以确定哪些列的数据会被回显到页面上,从而在这些位置插入恶意查询以提取信息
  • 为什么必须测试回显位?
    • 数据可见性:只有通过回显位才能直接看到注入的查询结果
    • 若注入的数据未显示在页面上,攻击者需依赖盲注(Boolean/Time-Based),效率大幅降低
    • 精准提取信息:回显位允许攻击者直接插入数据库函数或查询语句,快速获取敏感数据
  • SELECT 1在SQL中的基本含义是什么?其实这是一个简单的查询,返回数字1
  • 当攻击者使用UNION SELECT 1,2,3时,这里的1、2、3是为了匹配原始查询的列数,从而让联合查询生效。这时候,数字1、2、3本身并没有实际的数据意义,只是用来占位,方便后续替换成实际的函数或数据,比如database()或者version()
  • 在注入过程中如何确定需要多少个SELECT 1,2,3中的数字。这需要先通过ORDER BY子句来确定原始查询的列数,然后确保联合查询的列数相同,否则会引发错误。所以这里的数字个数是根据ORDER BY测试得到的列数来决定的
  • 将显示的数字位置替换为数据库函数以提取数据
  • 若原始查询的字段类型不兼容(如某列需字符串类型),可使用 NULL 或字符串占位

为什么要判断闭合方式

  • 特别是字符型,必须先判断闭合方式
  • 在SQL注入中,用户输入被拼接到查询语句里,如果没有正确闭合原有的引号或括号,整个SQL语句就会语法错误,导致注入失败。
    • 比如,如果原始查询是用单引号包裹字符串,而攻击者没有闭合它,后面就会有多余的引号,引发错误
  • 字符型闭合(单引号/双引号)
    • 测试方法:输入单引号'或双引号",观察是否报错
  • 括号闭合
    • 场景:参数被包裹在括号中(常见于复杂查询或框架生成的SQL)
    • 示例:SELECT * FROM users WHERE (username='[输入]');
    • 闭合方法:') OR 1=1 --
    • 混合闭合(引号+括号)
  • 如何快速判断闭合方式?
    • 触发语法错误
      • 输入'、"、),观察是否报错
      • 若输入'报错,可能是单引号闭合
      • 若输入)报错,可能需要闭合括号
    • 布尔测试验证
      • 单引号闭合:
        • ' AND '1'='1 → 正常
        • ' AND '1'='2 → 异常
    • 括号闭合:
      • ') AND ('1'='1 → 正常

判断注入类型

数字型

  • 数字型注入发生在参数不需要引号包裹的情况下
  • 常见场景:URL中的ID参数、分页参数等
  • 检测方法
    • 输入数字运算:id=1+1 -- 正常应返回id=2的结果
    • 布尔测试:id=1 AND 1=1 -- 正常显示 id=1 AND 1=2 -- 无数据

字符型

  • 字符型注入则涉及用引号包裹的参数,如 username='admin'
  • 检测方法
    • 闭合引号测试:username='' OR '1'='1' -- 若绕过登录,说明存在注入,在测试时输入单引号后,如果报错,说明可能存在字符型注入,需要闭合单引号并注释掉后续代码
    • 布尔测试:
      • username='admin' AND '1'='1' -- → 正常显示
      • username='admin' AND '1'='2' -- → 无数据

万能密码

  • 什么是万能密码?
    • 万能密码是通过 SQL 注入构造的特殊字符串,使登录验证的 SQL 查询条件恒为真,从而绕过用户名和密码校验
    • 示例:' or '1'='1 --
  • 适用阶段
    • 阶段 1:漏洞探测(初步测试)
      • 目标:快速判断是否存在 SQL 注入漏洞。
      • 操作:
      • 在登录框的用户名或密码字段输入万能密码。
      • 观察是否成功绕过登录验证
    • 阶段 2:漏洞验证(确认闭合方式)
      • 目标:明确参数的闭合方式(单引号、双引号、括号等)。
      • 操作:
      • 尝试不同闭合方式的万能密码
      • 根据是否登录成功,确定闭合符号类型
  • 场景限制
    • 密码哈希存储:若密码经过哈希处理,即使绕过验证也无法直接获取明文密码。
    • 二次验证:部分系统登录后还需二次验证(如 OTP、IP 白名单)。
    • 权限限制:若数据库用户权限不足,无法访问敏感表(如 users)

过滤空格

  • /**/%0A(换行符)代替

过滤引号

  • 用 CHAR() 函数或十六进制编码
  • 示例:' OR CHAR(49)=CHAR(49) --
posted @ 2025-03-01 19:44  micryfotctf  阅读(167)  评论(0)    收藏  举报