第一章:SQL注入基础——你必须要搞懂的核心概念
大家好,我是老周。做渗透测试这些年,SQL注入一直是我最常碰到的漏洞类型。说实话,它虽然经典,但很多新手一上来就急着用工具,反而忽略了最基础的东西。今天咱们就把这块地基打牢。
1.1 什么是SQL注入?
SQL注入,说白了就是攻击者把恶意的SQL代码塞进输入框,骗过数据库去执行。我见过太多人把它想复杂了——其实原理很简单:你的程序没有对用户输入做严格过滤,导致数据库把输入当成了代码来执行。
核心定义:SQL注入是一种将恶意SQL语句插入到应用程序输入参数中,并在后端数据库服务器上执行的安全漏洞。
举个例子,一个登录页面让你输入用户名和密码。后台的SQL可能是这样的:
SELECT * FROM users WHERE username = '用户输入' AND password = '用户输入'
如果我在用户名里输入 admin' OR '1'='1,那SQL就变成了:
SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = '随便输'
你看,OR '1'='1' 永远为真,整个查询就绕过了密码验证。我在项目中遇到过好几次,有些开发人员觉得「谁会这么输入啊」,结果就被打了脸。
1.2 SQL注入的危害有多大?
很多人觉得SQL注入就是「拖个库」而已。嗯,这只是冰山一角。我整理了一下实际危害:
- 数据泄露:用户密码、身份证、银行卡号全被拿走。2017年Equifax数据泄露,影响1.4亿人,就是SQL注入干的。
- 数据篡改:攻击者可以改你的订单金额、改你的账户余额。
- 权限提升:从普通用户变成管理员,想干嘛干嘛。
- 服务器沦陷:某些数据库支持执行系统命令,比如MySQL的
INTO OUTFILE可以写webshell。
⚠️ 我曾经见过一个案例:某电商平台因为一个搜索框的SQL注入,导致整个服务器被拿下,黑客在服务器上挖了三个月矿才被发现。所以别小看任何一个输入点。
1.3 SQL注入的分类——GET/POST/Cookie注入
按数据提交方式,SQL注入主要分三类。我习惯用「数据从哪里来」来区分:
| 注入类型 | 数据来源 | 常见场景 | 检测方法 |
|---|---|---|---|
| GET注入 | URL参数 | 商品详情页?id=1 | 直接在浏览器地址栏改参数 |
| POST注入 | 请求体 | 登录表单、搜索框 | 用Burp Suite抓包改数据 |
| Cookie注入 | HTTP请求头 | 记住登录状态、购物车 | 修改Cookie值再发包 |
你想想看,为什么要把Cookie单独列出来?因为很多开发人员只过滤了GET和POST参数,却忘了Cookie也能被篡改。我早期做渗透时就吃过这个亏——一个站怎么测都没漏洞,后来发现注入点在Cookie里。
1.4 SQL注入原理——数据库是怎么被「骗」的
原理其实就一句话:用户输入被拼接到SQL语句中,改变了原语句的语义。
正常的流程是这样的:
- 用户输入数据(比如商品ID)
- 程序把数据拼接到SQL模板里
- 数据库执行拼接后的完整SQL
- 返回结果给用户
问题出在第2步。如果用户输入的不是普通数据,而是SQL代码片段,那拼接后的SQL就「变味」了。
💡 我的理解方式:把SQL语句想象成一句话,用户输入是填空的词。如果填的是「苹果」,句子是「我吃了一个苹果」。但如果填的是「苹果;删除所有数据」,句子就变成了「我吃了一个苹果;删除所有数据」——数据库会执行两个语句。
1.5 常见数据库的差异——MySQL vs MSSQL vs Oracle
做SQL注入,不同数据库的「脾气」不一样。我整理了一张对比表,建议你收藏:
| 特性 | MySQL | MSSQL (SQL Server) | Oracle |
|---|---|---|---|
| 注释符 | -- 、# |
-- |
-- |
| 字符串连接 | CONCAT()、|| |
+ |
||、CONCAT() |
| 查询版本 | @@version、VERSION() |
@@VERSION |
SELECT banner FROM v$version |
| 获取表名 | information_schema.tables |
sysobjects |
all_tables |
| 报错注入 | extractvalue()、updatexml() |
convert()、cast() |
ctxsys.drithsx.sn() |
| 堆叠查询 | 支持(需PHP等支持多语句) | 默认支持 | 不支持(默认) |
这里有几个坑,我踩过:
- MySQL的注释符:
#是MySQL独有的,MSSQL和Oracle不认识。所以用SQLMap时,如果目标数据库是MySQL,它会自动用#注释,但换到MSSQL就会报错。 - Oracle的dual表:Oracle查询必须带
FROM,所以测试时要用SELECT 1 FROM dual。我第一次测Oracle时,直接写SELECT 1,结果报错半天没反应过来。 - MSSQL的堆叠查询:默认支持多条语句用分号隔开,比如
SELECT * FROM users; DROP TABLE orders。MySQL需要看驱动是否支持,PHP的mysql扩展就不支持多语句。
实战建议:拿到一个注入点,第一步不是急着跑数据,而是先判断数据库类型。我一般用三个方法:看报错信息、看注释符是否生效、看 version() 函数的返回。SQLMap虽然能自动识别,但手动确认更靠谱。
1.6 本章知识体系图
下面这张图是我自己画的,把本章的核心知识点串起来了。你可以把它当成一张「地图」,以后遇到SQL注入问题,先看这张图定位:
💡 怎么用这张图?每次做SQL注入测试前,先看一遍这张图。从「定义」出发,确认自己理解原理;再看「分类」,判断当前测试点属于哪一类;最后看「数据库差异」,选对payload。我自己的习惯是把它打印出来贴在工位上。
1.7 本章小结
这一章我们聊了SQL注入的四个核心问题:它是什么、有什么危害、分哪几类、不同数据库有什么区别。说实话,这些基础概念决定了你后面能不能用好SQLMap。我见过太多人一上来就 sqlmap -u url,结果连报错信息都看不懂——就是因为没搞懂数据库差异。
下一章我们会开始动手,用SQLMap做第一次注入测试。但在此之前,我建议你把本章的数据库差异表背下来,尤其是注释符和系统表的区别。嗯,这是基本功,绕不过去的。
公众号:蓝海资料掘金营,微信 deep3321