Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >实战|记一次前台getshell组合拳审计的完整过程

实战|记一次前台getshell组合拳审计的完整过程

作者头像
亿人安全
发布于 2023-12-28 07:30:47
发布于 2023-12-28 07:30:47
29800
代码可运行
举报
文章被收录于专栏:红蓝对抗红蓝对抗
运行总次数:0
代码可运行

免责声明

由于传播、利用本公众号亿人安全所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,公众号亿人安全及作者不为此承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除并致歉。谢谢!

朋友们现在只对常读和星标的公众号才展示大图推送,建议大家把“亿人安全设为星标”,否则可能就看不到了啦

本文内容仅限学习所用,请不要利用文中消息进行危害性测试。为保护此源码使用者的安全,本文中的源码系统名将做打码处理。 初学者学习中的小小收获,各位大佬轻喷。 1 整体审计 拿到源码,先做...

本文内容仅限学习所用,请不要利用文中消息进行危害性测试。为保护此源码使用者的安全,本文中的源码系统名将做打码处理。

初学者学习中的小小收获,各位大佬轻喷。

1 整体审计

拿到源码,先做一次整体审计,看一看整个代码的处理逻辑、是否有过滤控制器、是否有权限校验控制器等。

先看目录:

很明显有控制器,是模仿MVC形式的CMS。

1.1 权限控制

一共有两个入口index.php admin/index.php (感觉这样写的CMS很常见)。

查看两个文件,发现它们没有什么不同之处,定义了ROOT,然后进入APP:run()。除了admin文件夹下的index文件中定义了一个常量ADMINDIR。

跟进APP:run(),这里是整个CMS的核心。

很常见的路径转方法(伪静态?),如/index.php/[controller]/[action]/[arag1]/[arg2]。但由于其控制器分别在controllers和admin/controllers下,而访问控制脚本的函数使用的是不可控变量,所以不能通过普通控制器入口访问管理员的控制器。

这里还存在一个问题:它引入的时候貌似没有校验权限,是否普通用户可以越权调用admin的controller?

后面看了一下,其中一个类的构造函数处会进行鉴权。那就是看哪些控制器的构造函数没有鉴权 就能造成绕过。总而言之鉴权的地方不是统一的。

又看了一眼 发现是控制器的父类。那就是哪个父类不是这个(这样写的话可能性就会小很多)。后面看了一眼这个类包括了大部分后台HTML元素,那理论上所有控制器(除了API控制器)都会走这个类。

后面又发现,SAdmin虽然会检测session,但在session无效的时候并不会拦截,而只是会在session有效的情况下给SAdmin->data赋值。也就是说,具体的权限校验还是要在函数中实现。这给越权提供了空间。

然后发现后面校验权限是按照类似“校验权限字符是否在权限字符串中”的途径。

通过CheckAccess、CheckAction实现(这两个校验过程相同):

同时,admin的data只赋值一次:

除了改数据库之外没办法混淆鉴权了。(也就是说,如果存在注入,有造成后台管理员登陆的可能)

1.2 过滤控制

进一步查看控制器文件夹,查看是否有负责整体过滤参数的控制器(SQL、XSS、文件上传等的过滤文件)。

这里的过滤文件为functions.globals.php。不过这里的过滤函数都不是主动调用的(有些CMS会包括此文件 然后此文件中会先一步处理所有参数,这里完全就是写了函数等待调用)

过滤函数这边先实体编码然后加斜杠,应该是绕不了。

引用过滤函数的则是这三个,如果其他地方都是由此处获取请求参数,那就无法造成SQL注入。

当然,在HTTP交互中会被后端接受的参数远不止GET、POST和Cookie(这里是大多数CMS的误区,又不喜欢过滤其他头又喜欢用其他头)。如果其他的头也会在交互中被获取并且没有经过这三个函数,或者某处的GET、POST参数没有经过这些过滤,即可造成注入。

2 审计漏洞列表

2.1 后台文件上传(可shell)

目录穿越的后台模版文件上传造成的getshell 完全没有过滤相对路径+需要造成的模版文件后缀白名单造成的getshell(本来这个目录穿越还有点意义,结果我发现它根本没有限制入口为根目录文件夹- -,白穿越了)

2.2 后台注入(很鸡肋)

后台数据库管理中的功能。由于被输入的参数使用反引号包裹,而此CMS的过滤函数本身不过滤反引号,所以造成注入。 POC为http://localhost/admin/index.php/database/operate?dbaction=emptytable&tablename=hong\_acat`+where+cat_id=2+and+sleep(2);--%20)# 注入形式如下,用#号作为注释符即可。实际上,全database.php都存在这个漏洞(只要带有`$database`)

2.3 后台目录穿越

大家都爱的没用垃圾洞,甚至不需要后台代码。

3 柳暗花明的前台注入

找了这么多后台的洞,总而言之还是没什么用的。毕竟对于小CMS而言我们都希望使用前台漏洞,高效快速还不用苦苦猜一个管理员口令。于是我开始找前台漏洞。越权我们之前已经看过了是越不了的,RCE没有条件,信息泄露也没有条件,上传在前台已经测试过了没有绕过可能。那么能找的高危漏洞只剩下注入一个了。

在第一节中我们已经找到了CMS的过滤函数并且确定了此过滤无法绕过。现在需要找到的就是那些没有被过滤函数保护且会涉及数据库查询的参数。

接下来则是无聊的看参数时间,由于此CMS没有统一过滤,可以直接在控制器的action函数中查看输入参数是否经过过滤函数。

3.1 代码分析

终于,在注册的地方找到了一个不经过过滤函数的参数:

这个GetIP()是没有经过过滤函数的。虽然大多数CMS中这个IP是不可控的,但笔者属于不是很信邪的那一款。于是跟进GetIP函数:

这里写成了:先去X-FORWARDED-FOR、CLIENT-IP或者getenv('REMOTE_ADDR')(这个不可控是环境变量)取IP,如果这个IP不符合格式就返回gethostbyname($_SERVER['HTTP_HOST']),否则是正则表达式过滤之后的IP。问题就在于gethostbyname()并不能取到过滤的作用,于是我们就能将任意字符插入查询参数中,造成注入。

造成注入的条件则是: 1.存在X-FORWARDED-FOR或CLIENT-IP,且其值不为IP形式 2.HOST置为payload

以此格式传入包,果然触发了数据库报错:

3.2 使用注入进入后台

此查询语句的原貌是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
"INSERT INTO " . TABLE_PREFIX . "user (groupid, activated, username, password, verifycode, joindate, joinip, lang, nickname, email) VALUES ($groupid, $activated, '$username', '".md5($password)."', '$verifycode', '".time()."', '".GetIP()."', $lang, '$nickname', '$email')"

这里的groupid就是鉴权的ID(用户组ID)。由于这里就是注册点,这个注入可以被改造成这个形式,从而在注册时另外创建一个管理员账号,以此进入后台:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
INSERT INTO ***_user (groupid, activated, username, password, verifycode, joindate, joinip, lang, nickname, email) VALUES (2, -1, '111111111', '593c9b4a9390551d53e5cacf28ebd638', '96fbTjrp', '1697167889', '', 1, '111111111', '222@222.22');INSERT INTO ***_session (sessionid, userid, ipaddress, useragent, created, admin) VALUES ('aaa','1','','','','1')#', 1, '111111111', '222@222.22')

后面插入的帐号即为管理员账号。则POC为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
', 1, '123', '222@222.22'),(1, 1, '111111111', '593c9b4a9390551d53e5cacf28ebd638', '96fbTjrp', '1697167889', '', 1, '111111111', '222@222.22')#

这将额外添加一个用户名为111111111密码为111111111111的帐号。

使用此账密登陆,成功:

然后利用之前提到的后台文件上传漏洞,就能够getshell愉快玩耍啦~

原文链接:https://forum.butian.net/share/2399

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-12-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 亿人安全 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Leetcode-Easy 575. Distribute Candies
728. Self Dividing Numbers 描述: 有偶数个糖,需要分给弟弟和妹妹,要求最终两个人分到的糖数目一样,返回妹妹获得糖的种类数目最大值 思路: 如果糖的种类数小于
致Great
2018/04/11
5920
Leetcode-Easy  575. Distribute Candies
天池在线编程 2020国庆八天乐 - 8. 分糖果
https://tianchi.aliyun.com/oj/118289365933779217/122647324212270016 描述: 给定长度为偶数的整数数组,该数组中不同的数字代表不同种类的糖果, 每个数字表示一种糖果。 您需要将这些糖果平均分配给弟弟和妹妹。 返回妹妹可以获得的糖果种类的最大数量。
Michael阿明
2021/02/19
2100
​LeetCode刷题实战575:分糖果
算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !
程序员小猿
2022/04/12
2580
leetcode-575-Distribute Candies(计算一个数组中元素的种类的快速方法)
题目描述: Given an integer array with even length, where different numbers in this array represent different kinds of candies. Each number means one candy of the corresponding kind. You need to distribute these candies equally in number to brother and sister.
chenjx85
2018/05/22
5770
Golang Leetcode 575. Distribute Candies.go
当糖果的种类数目大于妹妹应分得的糖果数目时,妹妹所能分得的最大糖果种类数为妹妹应分得的糖果数,反之,则为糖果的种类数。
anakinsun
2019/04/22
3210
【leetcode刷题】T51-分糖果
Given an integer array with even length, where different numbers in this array represent different kinds of candies. Each number means one candy of the corresponding kind. You need to distribute these candies equally in number to brother and sister. Return the maximum number of kinds of candies the sister could gain.
木又AI帮
2019/07/17
5470
575. 分糖果
数组的长度为[2, 10,000],并且确定为偶数。 数组中数字的大小在范围[-100,000, 100,000]内。
编程张无忌
2021/06/10
2990
三分钟看完「分糖果」算法问题
给定一个偶数长度的数组,其中不同的数字代表着不同种类的糖果,每一个数字代表一个糖果。你需要把这些糖果平均分给一个弟弟和一个妹妹。返回妹妹可以获得的最大糖果的种类数。
五分钟学算法
2019/05/15
9150
LeetCode Weekly Contest 31解题思路
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014688145/article/details/71204570
用户1147447
2019/05/26
3860
LeetCode 575. 分糖果(set集合去重)
给定一个偶数长度的数组,其中不同的数字代表着不同种类的糖果,每一个数字代表一个糖果。你需要把这些糖果平均分给一个弟弟和一个妹妹。返回妹妹可以获得的最大糖果的种类数。
Michael阿明
2020/07/13
3750
LeetCode 575. 分糖果(set集合去重)
575. 分糖果
给定一个偶数长度的数组,其中不同的数字代表着不同种类的糖果,每一个数字代表一个糖果。你需要把这些糖果平均分给一个弟弟和一个妹妹。返回妹妹可以获得的最大糖果的种类数。
lucifer210
2019/09/10
3860
575. 分糖果
LeetCode 第 25 场双周赛(718/1832,前39.2%)
全国排名:718 / 1832,39.2%;全球排名:2951 / 7699,38.3%
Michael阿明
2020/07/13
3860
LeetCode 第 25 场双周赛(718/1832,前39.2%)
力扣题目汇总(二进制表示中质素个数,分糖果,有序数组平方)
给定两个整数 L 和 R ,找到闭区间 [L, R] 范围内,计算置位位数为质数的整数个数。
小小咸鱼YwY
2019/07/24
4460
LeetCode笔记:Weekly Contest 287
这一题的思路其实也是比较直接的,分两步走就行了,首先求出时间差,然后用贪心算法获取变换所需的最小操作数即可。
codename_cys
2022/04/13
1750
LeetCode-575. 分糖果(Golang)
Alice 有 n 枚糖,其中第 i 枚糖的类型为 candyType[i] 。Alice 注意到她的体重正在增长,所以前去拜访了一位医生。
bug菌
2023/08/24
1290
LeetCode-575. 分糖果(Golang)
Leetcode - 剑指offer 面试题29:数组中出现次数超过一半的数字及其变形(腾讯2015秋招 编程题4)
剑指offer 面试题29:数组中出现次数超过一半的数字 提交网址: http://www.nowcoder.com/practice/e8a1b01a2df14cb2b228b30ee6a92163
Enjoy233
2019/03/05
6510
Leetcode 575. Distribute Candies
文章作者:Tyan 博客:noahsnail.com  |  CSDN  |  简书
Tyan
2022/08/11
2110
Leetcode 575. Distribute Candies
力扣题目汇总(位1的个数,有效的字母异位词,检测大写字母)
否则,我们定义这个单词没有正确使用大写字母。 示例 1: 输入: "USA" 输出: True 示例 2: 输入: "FlaG" 输出: False 注意: 输入是由大写和小写拉丁字母组成的非空单词。
小小咸鱼YwY
2019/07/24
5050
【算法千题案例】每日一练LeetCode打卡——109.分糖果
Alice 有n 枚糖,其中第 i 枚糖的类型为 candyType[i] 。Alice 注意到她的体重正在增长,所以前去拜访了一位医生。
呆呆敲代码的小Y
2022/01/25
3360
【算法千题案例】每日一练LeetCode打卡——109.分糖果
【Leetcode -575.分糖果 -594.最长和谐子序列】
题目:Alice 有 n 枚糖,其中第 i 枚糖的类型为 candyType[i] 。Alice 注意到她的体重正在增长,所以前去拜访了一位医生。
YoungMLet
2024/03/01
920
推荐阅读
相关推荐
Leetcode-Easy 575. Distribute Candies
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验