当前位置: 首页 > news >正文

SQL注入常见攻击点与防御详解

SQL注入是一种非常常见且危险的Web安全漏洞。攻击者通过将恶意的SQL代码插入到应用程序的输入参数中,欺骗后端数据库执行这些非预期的命令,从而可能窃取、篡改、删除数据或获得更高的系统权限。

以下是详细、准确的SQL注入点分类、说明及举例:

一、 按注入点位置分类

1. GET 参数注入
  • 描述: 通过URL中的查询字符串(即?后面的参数)进行注入。这些参数通常用于GET请求,如过滤、搜索、分页等。

  • 原理: 参数值被直接拼接到SQL查询中,未经过滤或转义。

  • 举例

    • 正常URL: https://example.com/products.php?id=1

    • 对应SQL: SELECT * FROM products WHERE id = 1

    • 攻击URL: https://example.com/products.php?id=-1' UNION SELECT username, password FROM users -- -

    • 最终SQL: SELECT * FROM products WHERE id = -1' UNION SELECT username, password FROM users -- -

    • 解释: id=-1确保原查询不返回结果,UNION SELECT用于窃取用户表数据,-- -用于注释掉原查询的剩余部分。

2. POST 参数注入
  • 描述: 通过POST请求的正文(Body)进行注入。常见于登录表单、搜索框、注册等任何用户提交数据的场景。

  • 原理: 与GET注入类似,只是数据通过请求体传输,不在URL中显示。

  • 举例(登录表单):

    • 正常输入: 用户名 admin,密码 secret

    • 对应SQL: SELECT * FROM users WHERE username = 'admin' AND password = 'secret'

    • 恶意输入: 用户名 admin' --,密码 任意值

    • 最终SQL: SELECT * FROM users WHERE username = 'admin' -- ' AND password = '任意值'

    • 解释: --注释掉了密码验证部分,使攻击者能以admin身份登录,无需知道密码。

3. Cookie 注入
  • 描述: 应用程序将Cookie值(如user_idsession_id)直接用于数据库查询而未经验证。

  • 原理: 攻击者通过修改自己的Cookie值为恶意Payload来实现注入。

  • 举例

    • 正常Cookie: user_id=5

    • 对应SQL: SELECT * FROM users WHERE user_id = 5

    • 恶意Cookie: user_id=5 UNION SELECT @@version

    • 最终SQL: SELECT * FROM users WHERE user_id = 5 UNION SELECT @@version

    • 解释: 攻击者通过修改Cookie,联合查询了数据库的版本信息。

4. HTTP 头部注入
  • 描述: 应用程序将HTTP请求头部的值(如User-AgentX-Forwarded-ForReferer)记录到数据库或用于查询。

  • 原理: 攻击者在这些头部字段中构造恶意Payload。

  • 举例(记录User-Agent到数据库):

    • 正常User-Agent: Mozilla/5.0 ...

    • 对应SQL: INSERT INTO access_log (user_agent) VALUES ('Mozilla/5.0 ...')

    • 恶意User-Agent: Mozilla/5.0 ...', (SELECT @@version)) --

    • 最终SQL: INSERT INTO access_log (user_agent) VALUES ('Mozilla/5.0 ...', (SELECT @@version)) -- ')

    • 解释: 攻击者将数据库版本信息注入到了access_log表中。

二、 按注入技术(漏洞成因)分类

1. 基于联合查询(UNION-based)
  • 描述: 利用UNIONUNION ALL操作符将恶意查询结果附加到原始查询之后,从而在应用程序响应中直接显示数据。

  • 前提: 需要知道原始查询的列数(通过ORDER BYUNION SELECT NULL试探)以及各列的数据类型。

  • 举例: 如上文GET参数注入的例子。

2. 基于错误(Error-based)
  • 描述: 故意构造Payload使数据库报错,并从错误信息中提取敏感数据(如数据库结构、数据内容)。即使页面不回显查询结果,但会回显错误信息时,此方法有效。

  • 举例(MySQL):

    • Payload: id=1' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT((SELECT @@version),0x3a,FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a) --

    • 解释: 此Payload利用MySQL的RAND()GROUP BY子句制造一个重复键错误,并将@@version信息包含在错误信息中返回。

3. 基于布尔盲注(Boolean Blind)
  • 描述: 当页面没有数据回显和错误回显,但会根据SQL查询结果为真或为假返回不同的页面状态(如“存在”/“不存在”、“正常”/“404”)时使用。

  • 原理: 通过构造逻辑判断(如AND 1=1AND 1=2)观察页面差异,逐位(bit)猜测数据。

  • 举例(猜测数据库名长度):

    • id=1' AND (SELECT LENGTH(database())) = 8 --

    • 如果页面返回正常,说明当前数据库名长度为8;如果返回异常(或无结果),则不是8。然后继续猜测每个字符是什么。

4. 基于时间盲注(Time Blind)
  • 描述: 当页面没有任何回显(包括错误和布尔差异)时使用。通过构造Payload,根据查询条件的真假让数据库执行延时操作,通过观察页面响应时间来判断条件真假。

  • 原理: 利用数据库的延时函数(如MySQL的SLEEP()BENCHMARK(),PostgreSQL的pg_sleep())。

  • 举例(MySQL,猜测数据库名首字母):

    • id=1' AND IF(SUBSTRING(database(),1,1)='a', SLEEP(5), 0) --

    • 如果页面响应延迟了5秒,说明数据库名的第一个字母是'a';否则不是。

5. 堆叠查询(Stacked Queries)
  • 描述: 利用分号;在一次数据库调用中执行多条SQL语句。这允许执行任意SQL命令,而不仅仅是查询。

  • 前提: 后端数据库驱动需要支持多语句执行(如PHP中的mysqli_multi_query(),而mysql_query()不支持)。

  • 举例

    • id=1'; DROP TABLE users; --

    • 解释: 此Payload会先执行原始查询,然后立即执行DROP TABLE users语句删除用户表。

6. 二次注入(Second-Order)
  • 描述: 一种更隐蔽的注入。恶意Payload首先被存储到数据库中(例如,在注册用户名时注入),当时并未触发。之后,当应用程序从数据库取出该数据并用于另一个SQL查询时,注入才被触发。

  • 原理: 输入在第一次插入时可能被转义,但存储后被认为是“干净”的数据,第二次使用时未经过滤。

  • 举例

    1. 注册阶段: 攻击者注册一个用户,用户名为 admin' --

      • 插入SQL: INSERT INTO users (username) VALUES ('admin'' -- ') (经过转义,安全)

    2. 后续操作: 管理员在后台查看用户列表,程序执行: SELECT * FROM users WHERE username = 'admin' -- '

      • 解释: 从数据库取出的用户名admin' --被直接拼接进新的查询,注释掉了后续条件,可能导致列出所有用户或其他敏感操作。

三、 其他特定场景的注入点

1. 搜索功能(LIKE子句)
  • 描述: 搜索框通常使用LIKE '%keyword%',这里的引号和百分号是常见的注入点。

  • 举例

    • 正常输入: apple

    • SQL: SELECT * FROM products WHERE name LIKE '%apple%'

    • 恶意输入: %' UNION SELECT 1,2,3 --

    • 最终SQL: SELECT * FROM products WHERE name LIKE '%%' UNION SELECT 1,2,3 -- %'

2. ORDER BY 子句注入
  • 描述: ORDER BY后面通常接列名或列索引,不能直接使用UNION。但可以利用IF语句或 CASE WHEN 进行盲注。

  • 举例(盲注):

    • https://example.com/products?sort=IF(1=1, name, price)

    • https://example.com/products?sort=IF((SELECT SUBSTRING(@@version,1,1))='5', name, price)

    • 解释: 通过IF条件控制排序依据的列,观察排序结果的不同来判断条件真假。

3. 宽字节注入
  • 描述: 主要针对使用GBK、BIG5等宽字符集的PHP应用程序。由于转义函数(如addslashesmagic_quotes_gpc)和字符集编码配合不当,导致转义符\%5C)被“吃掉”,从而使得单引号逃逸。

  • 原理: 攻击者输入一个特殊字符(如%bf%27),%bf与转义符%5c组合成一个合法的宽字符(如),从而使后面的单引号%27成功逃逸。

  • 举例

    • 输入: id=%bf%27

    • 转义后: %bf%5c%27 (PHP的addslashes'转义为\'%5c%27)

    • 数据库以GBK解码: %bf%5c 被解码为汉字“縗”,剩下的 %27(单引号)则留在原地,成功闭合了查询。

总结与防御

防御原则(永远不要信任用户输入)

  1. 使用参数化查询(预编译语句): 这是最有效、根本的防御手段。将SQL代码与数据完全分离,用户输入永远被视为数据,而非代码。几乎所有编程语言和框架(如Java的PreparedStatement, PHP的PDO, Python的sqlite3)都支持。

  2. 使用ORM框架: 如Hibernate, Entity Framework,它们通常内置了参数化查询。

  3. 最小权限原则: 数据库账户不应拥有过高权限(如DROP, FILE权限)。

  4. 输入验证和过滤: 对输入进行严格的白名单验证(如只允许字母数字)。但绝不能仅依赖此方法。

  5. 转义: 如果万不得已必须拼接SQL,必须使用数据库特定的转义函数(如mysql_real_escape_string),但要注意字符集问题(宽字节注入)。

  6. 错误处理: 向用户展示友好的错误页面,而不是详细的数据库错误信息。

通过了解这些常见的注入点和攻击技术,开发者和安全人员可以更有针对性地进行代码审计和安全防护。


文章转载自:

http://a63zJq68.jtkfm.cn
http://9qwzpqEV.jtkfm.cn
http://vj6I41RP.jtkfm.cn
http://TkEWh0xu.jtkfm.cn
http://bXzXizTI.jtkfm.cn
http://IvSSwQE5.jtkfm.cn
http://YGYxDoyd.jtkfm.cn
http://Xt0wCwTK.jtkfm.cn
http://0DwXyXhd.jtkfm.cn
http://6m7xc3Kl.jtkfm.cn
http://V1Jfz3zA.jtkfm.cn
http://jdY69xn6.jtkfm.cn
http://3seb5zTD.jtkfm.cn
http://WRjjE8Th.jtkfm.cn
http://5WUC8ZRt.jtkfm.cn
http://UROkz0Z4.jtkfm.cn
http://zxKsmxU7.jtkfm.cn
http://UpUB9g7F.jtkfm.cn
http://liMZWKUg.jtkfm.cn
http://nfYhTsjS.jtkfm.cn
http://T4HRE4VJ.jtkfm.cn
http://UgXrJ8L2.jtkfm.cn
http://gJqgjxCt.jtkfm.cn
http://ag1m5CRU.jtkfm.cn
http://aaMwRIph.jtkfm.cn
http://gs02Puse.jtkfm.cn
http://e7ENojjS.jtkfm.cn
http://9JomN28q.jtkfm.cn
http://QdazlBd6.jtkfm.cn
http://xvVVMw0l.jtkfm.cn
http://www.dtcms.com/a/381879.html

相关文章:

  • 后端(FastAPI)学习笔记(CLASS 3):Tortoise ORM
  • C++-STL
  • Java 大视界 -- Java 大数据在智能家居场景联动与用户行为模式挖掘中的应用
  • XCKU15P-2FFVA1760I AMD 赛灵思 Xilinx Kintex UltraScale+ FPGA
  • 图论基础知识
  • DMA硬件架构解析:总线矩阵与核心组件
  • 从军用到掌心:固态硬盘(SSD)的演进与革命
  • 通俗解释redis高级:redis持久化(RDB持久化、AOF持久化)、redis主从、redis哨兵、redis分片集群
  • 【C++】类和对象——(上)
  • 解决Windows系统“‘php‘ 不是内部或外部命令”报错的完整指南
  • 用 Go 打造一个服务器资源指标采集器:结合 Prometheus Exporter 实战
  • Unity学习----【进阶】TextMeshPro学习(二)--进阶知识点(样式表,颜色渐变预设,精灵图片资源)
  • 从理论到落地:神经网络稀疏化设计构架中网络剪枝的深度实践与创新
  • ARM、AArch64、amd64、x86_64、x86有什么区别?
  • 机器学习项目-南方电网电力负荷预测
  • python标准库有哪些模块,简单总结下。
  • 文献阅读·MCformer:基于混合通道变换的多变量时间序列预测
  • 【软件操作】飞牛nas系统:笔记本息屏、合盖均不关机
  • 【SPI】【二】SPI控制器驱动代码详解
  • pandas读取复合列名列头及数据和处理
  • jenkins触发部署
  • 【pure-admin】项目登录验证码实现分析
  • Docker快速入门手册
  • 【C++设计模式】第五篇:装饰器模式
  • linux C 语言开发 (十) 进程间通讯--信号
  • 绿色环保活动平台(AI问答、WebSocket即时通讯、协同过滤算法、Echarts图形化分析)
  • 飞算JavaAI实战高效构建电商系统核心功能模块全解析
  • CSS 技巧使页脚始终位于网页的底部
  • Vue3》》eslint Prettier husky
  • 基因组多组学(第七篇空间HD文章)--基于蛋白质组学的分类揭示IDH突变型星形细胞瘤中存在免疫热亚型且预后较差