资讯动态

(SQL注入学习)联合查询注入(UNION-Based)

发布时间:2026/10/3 17:03:31 来源:尧图企业网站定制
摘要本题主要考查对联合查询注入的实战使用方法。目录一、题目详情二、解题思路及原理1、登录绕过2、判断注入类型1判断字符型还是数字型2判断回显位置3、有回显的联合查询注入Union-Based1获取当前数据库名和用户名2获取所有表名3获取指定表的所有列名4提取账号密码一、题目详情题目来源CTF²中的“[极客大挑战 2019]LoveSQL”靶机环境启动靶机进入靶机链接二、解题思路及原理1、登录绕过看到登录框或查询框先用万能密码测试看看。a、基础万能密码用户名1 or 11#或admin or 11#密码任意数字如123原理我们写的sql语句是直接插入到【where username万能密码】由于有引号闭合所以要写插入语句的时候要注意引号。php会自动补全其他sql语句然后放到数据库里执行故我们只需要写相应主要是sql语句来实现我们的目的。SELECT * FROM users WHERE username 1 OR 11# AND password 12311恒真#注释掉后面所有东西。因为11永远为真所以WHERE条件对整个表都成立查询会返回users表里的所有行。b、碰到过滤情况闭合引号并注释: 用户名admin-- 密码任意 原理-- 也是 SQL 注释符注意 MySQL 中 -- 后面必须跟一个空格。适用于 # 被过滤的情况。过滤了空格: 用 /**/ 代替空格1/**/or/**/11# 用 代替空格URL 编码中1or11# 用括号绕过1||11# 针对特定数据库括号闭合绕过针对 WHERE (usernamexxx) 结构: 用户名1) or (11 密码任意 原理WHERE (username1) or (11) AND password123输入万能密码结果如下2、判断注入类型适用情况不知道是数字型还是字符型不知道有没有回显。数字型你输入的东西直接就是 SQL 的一部分不用管引号。字符型你必须先补一个引号把前面的引号闭合掉才能继续注入。否则你的 payload 会被当成字符串内容不生效。1判断字符型还是数字型输入1页面正常--字符型注入存在单引号闭合问题。输入1页面正常--数字型注入不需要单引号闭合。PS看上面两个图片输入的万能密码带有引号看到页面正常可以判断是字符型注入。2判断回显位置通过上面得到的那个好像flag的数据但是测试了发现不对但可以判断是可以sql注入的而且输出的东西可以知道它会显示数据库查询结果回显你发出去的请求服务器处理完之后把结果“显示”回给你了。回显 你注入产生的结果能不能在网页上直接看到。有回显 → 用 UNION / 报错注入直接拿数据。无回显 → 只能盲注靠页面反应一点点猜。由于界面没有报错而是返回正确数据库查询结果因此采用UNION注入。但我们还得先确定回显位置。回显位置 页面上能显示注入结果的那个“坑”。先数清有几列再用 1,2,3 试出哪个坑能显示最后把要查的数据塞进那个坑。判断方式a判断有多少列输入1 order by 3#页面正常输入1 order by 4#页面报错 - 说明当前表有3 列注猜测当前查询结果集有多少列当数字超过实际列数时数据库会报错如Unknown column N in order by从而推断出列数。原理假设原始 SQL 是SELECT id, username, password FROM users WHERE id 1 ORDER BY id DESC把参数改成1 order by 3 #语句变成SELECT id, username, password FROM users WHERE id 1 order by 3 # DESC#把后面的DESC注释掉order by 3正常执行。如果order by 4报错就说明表里有 3 列。b判断回显位在哪输入1 union select 1,2,3#观察页面上哪个数字被替换成了回显位比如页面原本显示标题的地方变成了2这里的2不是数字本身有意义而是“第 2 列是回显位”的标志。你写进第 2 列的什么内容页面就会显示什么。后面把敏感函数/字段塞到第 2 列就能读到数据。传入1 union select 1,2,3#SELECT id, username, password FROM users WHERE id 1 union select 1,2,3#1闭合了原字符串union select 1,2,3追加了一个联合查询返回一行(1, 2, 3)#注释掉尾部测试如下a判断有多少列输入1 order by 3#页面正常输入1 order by 4#页面报错故判断为返回的是3列b判断回显位在哪由此可知回显位是第2位和第3位3、有回显的联合查询注入Union-Based根据上面的判断接下来我们就只需要让第2位和第3位上去使用函数或字段去获取数据了。1获取当前数据库名和用户名 union select 1,database(),user()#测试如下获取到数据库名为geek用户名为rootlocalhost2获取所有表名 union select 1,group_concat(table_name),3 from information_schema.tables where table_schemadatabase()# 注group_concat可以把多行结果拼成一行方便显示如果不使用的话那么只会出现第一张表。如果有多张表的话后面的表不显示出来说明如下片段作用闭合前面的字符串union select 1, ..., 3追加一行结果占满 3 列group_concat(table_name)把多行表名拼成一个字符串from information_schema.tables查系统表存所有表名的地方where table_schema database()只查当前数据库的表#注释掉尾部测试如下获得表名l0ve1ysq13获取指定表的所有列名 union select 1,group_concat(column_name),3 from information_schema.columns where table_namel0ve1ysq1#这里就不需要再做解释了上面已经解释过了。测试如下由此可以字段为3个为“id,username,password”4提取账号密码 union select 1,group_concat(username,0x3a,password),3 from l0ve1ysq1#注0x3a是十六进制的冒号用于分隔用户名和密码如admin:123不然账号和密码就在一起显示了如admin123。为什么不用:因为引号经常被过滤。如果不会过滤可以用“:”测试结果如下好了可以明确看到flag了终于拿到了

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑