问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
上ORM也没用!手注击穿ORM到后台
有点标题党我先说了,别喷先看完。 本来也没想到能整出这么复杂的活,在这还是要稍微感谢一下甲方:没有你们离谱的要求整不出今天的大活。
有点标题党我先说了,别喷先看完。 本来也没想到能整出这么复杂的活,在这还是要稍微感谢一下甲方:没有你们离谱的要求整不出今天的大活。  简单的开始 ----- 还是一样为保密不上截图,入口用户名注入(记住这个,后面要考):  都爆出语句了,由于客户要求证明危害,文艺地注了个当前用户首字母:  一个星期之后客户那边反馈说不认可危害性,需要能看数据。由于1.已经过了一个星期漏洞详情都快忘了2.这个客户b事很多=>SQLmap启动。 本来是打算简简单单跑一波吧,但是没想到怎么样都跑不出(跑不出的过程就略了)。迫不得已只能再次手注。 确定数据库类型 ------- 先简单确认下数据库类型,使用user、substr两板斧,user()不行substring不行,怀疑是mssql。 然后尝试waitfordelay,报错:  unexpected token,那看来不是mssql,抱着总不可能是达梦的想法试下oracle:  `nls_initcap`是一个oracle特有的i18n函数——确定数据库类型为oracle。 巧遇Hibernate ----------- 既然数据库类型都能确定,中间也没遇到什么WAF,怎么会跑不出来呢?百思不得其解之下我决定先试试访问下系统表,比如`all_users`。 结果是报错,怎么说呢,意料之外,情理之中?毕竟要是咋拼接都行的话就不会跑不出来了。  仔细看看报错,显示`all_users is not mapped`。讲道理在之前的注入里我真没见过这个报错,比起oracle这更像是java报错。 再往下看,这是一个hibernate下的报错:  ### 简单讲一下Hibernate是啥 **首先我不是一个开发,并且我也没有用过Hibernate,所以我得提前说明一下——以下所有言论都是我个人理解,很可能有问题,请选择性查看。** Hibernate,理论上是一个ORM框架,一般也会被当作ORM来使用。 它有自己的一套语法,可以叫做HQL。它拥有类似MVC里类的Model-View功能,也就是将数据库里的具体数据记录绑定到一个Java变量 OR Java类 OR 我们说的JavaBean上。也就是说,hibernate会建立一种从数据库到对象的映射。 这里宽着讲内容就很多了,不做展开,简单了解下。 在我短暂的从业生涯中,基于HQL的注入出现次数比较少但并非没有。总而言之它是一个罕见但并非无解的漏洞,只要开发够大意,还是能够找到解法的。 映射限制突破 ------ 现在平心静气,来梳理一下已知情况。 1.从上文我们可以得知all\_users不在hibernate的映射范围内 2.这个注入一定程度上属于盲注(报错不报数据) 基于1,我们下一步的行动应该是找到一个可以利用且在hibernate映射范围内的类,但事实上基于开发的“最小原则”,系统表理论上不会被映射进来,因为这属于画蛇添足之举。基于2,爆破表名应该可以说完全不可能,因为①我们不能访问到存储表名的那个系统表②也没法通过报错注入获得提示。 那么下一步怎么做呢?回头重新查看报错信息,我们能知道的是当前语句:  虽然被写成了类的形式,但我们很快能发现:**当前语句里不就有个表名?** 虽然不知道用户表是怎么沾上Community(**这也揭示了两点,一是表命名使用驼峰,二是臭开发黔驴技穷取名水平很糟糕**),但好歹也是提供了一个可用的表和一些可用的爆破提示。 在需要急速下班(其实每篇文章里我都在急速下班,但结果都是下不了- -)时自然优先想办法利用已经存在的表。 爆破用户名 ----- 虽然,我们知道当前注入所在点的语句,也就是下文这个: `from com.abc.pojos.PersonCommunity where personNumber='*' and personType=0 and meetingID='11111111111111111111111'` 但使用万能密码式闭合之后我发现登录操作中还进行了其它校验,会显示非XX系统用户登录失败:  这就说明我们需要弄出一个真正的用户名来。回顾注入语句,我们知道用户名的字段为personNumber,那么直接盲注: `...' or 1/(case when (substr((select personNmber from personCommunity where rownum=1),1,1)='A' then 1 else 0 end))=1 or 1='...` 构造一个OR从句使语句一定会走这里,然后构造一个除零报错直接从状态码看结果。 但是我发现:即使确认过这个语句没问题,单个从句拎出来也没问题,这个payload仍然会报错。 也许hibernate里的某个特性不允许这样的语句? 转半天,想起还有另一个类似的语句可以用: `...' or 1/(case when ((select personNmber from personCommunity where rownum=1) like 'A%' then 1 else 0 end))=1 or 1='...` 是的,用like不就行了? 单个字符爆破,很快得到了一个用户名'E132654'。**这又给了一个模糊的信息:这个用户名是否是可枚举的**(后面试了一下这个系统用户名貌似是一段一段的,一些可以枚举一些不可以)。 然后就是根据用户名爆破密码了。 密码密文到明文 ------- 这一步算是这次渗透中我运气最好的部分了。根据用户名爆破密码的语句很简单,从句里再加一段就行: `...' or 1/(case when ((select personNmber from personCommunity where rownum=1 and personNumber='E132654' ) like 'A%' then 1 else 0 end))=1 or 1='...` 但在爆破密码之前,我们还需要捋一下目标顺序: 首先,我们不知道密码所属列名,这需要爆破; 其次,我们需要知道密码是不是密文,是不是哈希:是密文的话可以直接下班了,是哈希的话要确定是否有盐(这很难知道,但也可以爆破); 最后,我们可以尽可能找到一个初始密码(如果有的话),这是我运气最好的部分——我爆破的第一个密码就是初始密码。 ### 猜解列名 我们先拿出已知的列名:`personNumber` `personType` `meetingId` ,可以看出基本都是驼峰两个词,那么理论上密码字段应该会类似personPassword、personPwd,或者是通用列名比如password、pwd、Password。 构造一下跑出来是password。 ### 爆破密码 首先先不要浪费爆出来的用户名,根据用户名爆破此用户名对应的密码:  一位一位爆破了五六位,根据开头感觉是哈希。这里又犯了个傻,先入为主认为哈希算法是MD5,于是把常用口令MD5一下跑一遍:  emmm。。。没有。就怕其实是加密,或者强制性设置为强口令。 不过这都不是定论,还可以平心静气,再推断一下: 1.实际上,爆破不出只能说明密码不是常见弱口令,或密码不是MD5格式。 2.我们可以回到之前爆破的密码,把它继续爆破出来。我相信这个密码大概率会是个特殊的密码,因为我爆破的是第一行账户的密码,理论上会是第一个被创建的账号的密码。**第一个账号通常会是超管或测试账号,如果有所谓的初始密码,这个账号上出现的概率会更高。** 3.**我们不需要爆破出完整的字符串,在有前几位的情况下已经可以将其与常见哈希字典进行比对。** 那么直接将爆出的这几位字符串与哈希字典比较,没有哈希字典不要慌,百度一下你就知道:  只能说运气来了真是挡也挡不住,这个888888是初始密码的可能性非常大! 要确定它是否真是初始密码也很简单,改一下语句: `...' or password='1f82...' and 1/(case when ( personNumber like '§§%') ...` 看一下一次爆破能命中几个字母就行了,间接性判断了数量。  看爆破结果也是很乐观,基本板上钉钉是大量使用的密码。 取得账号密码 ------ 用户名找到了,密码也找到了,理论上已经可以登录了,但输入正确的用户名密码登录居然还是显示非XX系统用户登录失败。登录语句是能看到的,这之中肯定出现了什么问题。 再次再次折回来看登陆语句:  看来还需要后面的条件满足,这个也简单,从句里多加上限制条件和限制密码,再爆破一个账号即可。这次爆出来的账号是一个纯数字字符串`134*****`,输入密码!登陆!成功!跳转?另一个登陆口??? 东方不亮西方亮 ------- 是的没错,登录之后跳到了另一个登陆口,这真是我万万没想到的:  这下更没法说服客户漏洞有危害了,万万没想到是这个结果- -。不过这也是实战的魅力所在——你是真不知道开发还能给你写出个啥来。 总之虽然血压飙升气得快上天了还是得平心静气,毕竟现实是不以人的意志而转移的,简单来说气也没有用。 那么坐下来,思考一下我们还能如何破局? 首先我们从登陆中能拿到的信息主要有哪些?初步来看应该是一个页面(入口)和一个登陆跳转过程,过程里有一些路由。 ### 页面分析v1 最重要的应该是新的页面,还是个入口。这个入口也会有SQL注入嘛?很遗憾,经过测试是没有的,并且当前用户名也不可用。 那么之前登陆的Cookie有用吗?用原始登陆后的Cookie尝试刷新页面,还是无效。删除Cookie访问新入口,可以访问。 看上去是跳到了一个完全不需要鉴权的地方。\*\*这应该吗?\*\*这么异常的情况提示我还是需要返回路由看看。 ### 路由分析 看看路由。  可以看到一个POST之后跳转到上一页面,然后跳转到index,再跳转回另一个入口(login)。 也就是到open\_index这个页面的权限不足,它的权限应该由open\_login来授予——那最开始的login页面要给谁授权呢?从路由命名上来看,这几个系统并不像是分支和sso(其实从前端长相看也不像,这里不能放出),而更像是各自分立的关系,毕竟它们的命名方式就各不相同。 **那么是否还存在另一个index,是由原始的d**Login来授权呢?\*\* 就像猜测列名一样,按照现有的路由信息对d\*\*的index进行猜测:`d**Index` `d**_index` `d**_Index`都走一遍,很可惜这次没有这么走运,都是404。 不过还是没事,虽然爆破是失败的,但我相信思路是对的。 ### 页面分析v2 既然生猜猜不出,也许可以从页面中找到新的线索。 返回第二个系统前端页面,看看js。前端一堆js,先挑个看上去最有可能露出马脚的看起,比如这个08年的老兵:  向下翻翻翻:  这是什么好难猜啊,这个全是index的玩意是不是各个系统的跳转路径好难猜啊^ ^。果然上文中的猜测是对的,存在很多个系统。 那么拿起之前的Cookie爆破一下路径:  Yes,it is!下班成功~  后续 -- 向客户讨封了,客户决定封我为真神  希望下次拷打我的时候他能记住这两个字
发表于 2025-03-28 09:00:00
阅读 ( 1562 )
分类:
渗透测试
4 推荐
收藏
4 条评论
XYFAE
2025-03-28 15:51
牛的
请先
登录
后评论
c铃儿响叮当
2025-03-28 17:52
真神真圣亦真仙
请先
登录
后评论
Mortalbeings
2025-03-30 17:16
小保有点强
请先
登录
后评论
厉飞宇
2025-03-31 18:44
看跪了
请先
登录
后评论
请先
登录
后评论
阿斯特
AugustTheodor di CatXicure
7 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!