[代码审计基础 15]phpmcs_v9.6 rce
PHP:5.4.5
设置调试:https://blog.csdn.net/m0_46641521/article/details/120107786
版本:phpcms_v9.6.0_UTF8
0x01:路由分析
和前一篇一样的路由,但是对输入的关键字都有了防护;
0x02:漏洞分析
01 慢慢调试
目前是代审的基础,就没有太注重逻辑,就直接给了漏洞利用点在哪;
是在phpcms/modules/member/index.php的register模块
,也就是上一篇用来触发连接那里;
PHPstorm开启调试,这里点击提交注册,burp抓包一下;
然后在调试器能够看到调试信息:
然后向后慢慢走:
这里是配置信息,不用管;
主要是下面这个isset($_POST['dosubmit']
地方;
显然是进行了提交的,所以这里能够进入:
这个验证码是没得的,在注册的时候也没看见验证码;
然后注意这个$userinfo['modelid'] = isset($_POST['modelid']) ? intval($_POST['modelid']) : 10;
;现在先不管这个是什么,知道这个是可以通过我们控制的就好;
然后下面能够看见一个ip()
,跟进看看:
ip()
最后进行了一个正则匹配,只有数字匹配上了才能够返回一个ip,否则就是空;
然后回到原来的register
:一直走,直到走到这里:
然后跟进看看:
一般来说,model
是和数据库有关的;
在这里:
db是连接的数据库对象;
$this->db_pre是数据库的前缀,前缀是:v9_
要查的表是v9_model_field这个表;
为什么是查看v9_model_field
这个表呢?跟进load_modle
调试一下:这里指定了路径
再跟进,就是返回的这个:
打开数据库,看看数据库v9_model_field
表中有什么:
由于是才重装CMS的,没有对这个表有什么修改,所以这里是什么样,原始数据就是什么样子;
接着调试往下走:
这里给member_input
对象加了一个attachement
属性,先不管是什么;
接着F8往下走:
array_map('new_html_special_chars',$_POST['info']);
# 让$_POST['info']执行new_html_special_chars()函数
大概是想起一个编码的作用,不用管;
然后注意到箭头指向的地方,是取值$_POST['info'];
,也就是说,这也是可控的;
接下来F7步入:
又走到了member_input
这个地方;
02 整理输入-1
现在已知的是:
$_POST['info']
可控,并且在member_input->get()
会将其调用
所以现在重点关注get()
能够做什么,这里是预先知道有洞的,不是现审的;这是还在学基础;
现在就要看,输入的可控的东西经历了哪些东西;
F7步入trim_script($data)
函数
转义js代码的,用来防御XSS;替换了<>
和javascript
;
回到原先的地方再F8;
之后就是对此做操作;
F8走几步:
已知:
$modelid 是可控的;
$data已经是可控的了:
foreach之后,field和value就是可控的了
$field = birthday
$value = 2023-02-03
safe_replace():
进行了过滤,例如:%20,%2527,%27,',",*,'',<,>,{,}等字符
$func = $this->fields[$field]['formtype'];
这里的$this->fields是不可控的,它是在构造函数中已经定义了;
但是$field是可控的;
于是$func
被从$this->fields[$field]['formtype'];
中取出来的值赋值为datetime
然后再检测这个类中有没有datetime
这个方法,有就执行;并且执行的参数也是可控的;
这里能执行的方法只有这个类中的方法:
但是同样要求这个方法存在于$this->fields
中;
因为$func
同样是从$this->fields
中取出来的;
所以需要知道$this->fields
是怎么来的;
然后重新调试,为了知道$this->fields
是怎么来的:
然后步入:
数据是存在数据库的
缓存从数据库中取出来,存在内存,存在redis中;
这个地方是缓存数据之类的,看的意义不大,由于数据都是存在数据库中,所以进入数据库中查看modelid=10
的;
所以会把这个birthday
取出来,然后这里又有formtype=datetime
;
由于modelid
也是可控的,所以可以通过控制modelid
来控制fields
的数据;假如将modelid
改成3
,那么会将modelid=3
的所有取出来;
这里重新调试一下,将modelid
修改成3:
可以看到,相较于前两幅图中的modelid=10,fields[1]
这里的fields[23]
多了很多东西;
随后可以通过$_POST['info']
来控制选择什么;
不过实际上,也需要看$this
中的方法有哪些;所以目标就缩小到了原来那几个函数中,即:
将函数都看一下之后,定位到editor
函数中;
1 $this->textarea()
作用:剥离HTML标签
2 box
作用:裁剪元素组成字符串
3 images
作用:传图片,返回字符串
剩下的就没意思了
4 editor
注意到了$this->attachment->download
,然后查看download
函数:
editor
是一个附件下载的函数;
03 整理输入-2
所以考虑能不能向服务器中下载(写入)PHP文件;
所以现在修改modelid
等参数,发包
让其进入download
函数:
new_stripslashes
函数是一个去掉反斜线的函数;
然后这里是一个正则,如果匹配不上,就没了;显然目前是匹配不上的;
然后进一个网站匹配匹配:https://regex101.com/
匹配正则之后,通过一个foreach
然后在里面的fillurl
拼接出一个url
,应该叫通过fillurl
判断传入的参数是一个什么协议,然后根据什么协议返回什么链接;
最后将返回的url填充到$remotefileurls
数组中,并通过array_unique
函数去重;
然后接着跟:
看到之类有一个getname
函数,跟进去看看或者点进去都行:
这里对名字进行了一个拼接,返回了日期随机数.后缀
样式的文件名;
在171行有$upload_func = $this->upload_func;
,这里将$upload_func
赋值为了copy()
;因为原来的定义也是这样
现在找找copy()
函数作用:
https://www.php.net/manual/zh/function.copy
并且它支持url链接;
同时,可以在调试信息中看到file
和newfile
两个路径;
copy函数
一执行就会被上传上去,所以现在去看看上传的文件:
但是会传入http://www.baidu.com/1.png
失败了,原因是
既然是not found
,那么考虑一下found
的;
尝试一下其他的:http://www.taobao.com/1.png
然后上传了过来:
看看请求的网页:
所以,只要不是not found
就行,哪怕是页面不存在
文件上传成功了,接着再跟一跟后续函数:
在上传文件成功的if
判断操作中,有一个add
函数,进入add
函数查看信息:
发现这里是将文件信息传入数据库的一个操作,先记下来;
随后F8走几步,就完结了;
所以最后得到结论:
- 修改modelid和info[content]可以指定执行
editor()
函数- 在
editor()
中的download()
,跟进download()
发现使用了copy
赋值文件- 由于
copy()
支持从url中下载文件,且url可控,但是需要满足正则匹配,在满足的情况下,能够下载任意满足正则匹配的文件- 最后,新文件名是随机的,文件信息会被存入数据库
0x03 输入流转
01 上传PHP文件
目前是能够上传一个文件了,于是考虑上传一个php文件
现在整理一遍输入:
info[content] = url
url可控,并且会解析且过正则
正则:(href|src)=([\"|']?)([^ \"'>]+\.(gif|jpg|jpeg|bmp|png))\2
正则保证了后缀是图片类型
服务器对传入的url进行请求
希望服务器下载一个php后缀的文件
但是注意到这个正则,它相当于只进行了后缀的识别。
那么考虑能不能在通过正则之后,通过处理,将后缀去掉,保留前面的一部分;
所以现在就比较关注传入的url
在哪里进行的拼接;
在editor
中直接调用了download
并且传入了content
,但是并没有进行什么处理,于是跟进download
;
download()
前部分都是进行的赋值和正则(只检测了后缀,所以这个也能过:<a href=http://www.taobao.com/1.php/1.png>
),唯一的操作就是去掉反斜线;
然后注意到到了fillurl()
函数;
跟进调试一下,或者直接看也行:
$surl
是传入的地址,ctrl f
一下,发现,就截图部分进行了裁剪和截取,其它的都是整段拼接,所以看截图部分;
然后看到这里:
$pos = strpos($surl,'#');
if($pos>0) $surl = substr($surl,0,$pos);
# 返回#第一次出现的位置,并且将$surl截取到#出现之前
# 所以考虑<a href=http://url#1.png>
所以试试:http://www.taobao.com/1.php#1.png
;
显然是满足png
的后缀,然后这里进入这个拼接就行,不需要执行后面的copy
;现在的目的是为了拼出来php
后缀,拼出来了之后在指定一下服务器,自然是可以的;
然后这里拼接出来了php
后缀;
现在请求一下其他地方的文件,就本地的吧,都一样了;
能够看到这里是能够请求的;
现在在这里写一个<?php phpinfo();?>
到1.php
中,在请求一下;
现在有返回了,能拉进去;
现在就只需要解决最后的问题了,就是不知道这个文件路径的;
02 路径报错
之前有提到一件事,就是说是已知漏洞的;
在index.php
后有一个数据库插入信息的操作,这里的信息插入是在文件上传之后插入的,并且插入信息,是插入的用户模型的信息;
由于已经改info[birthday]
成了info[content]
,所以这里跟进:
burp中发包,需要将username
和email
改成数据库中没有的,不然$status
过不了判断:
执行的SQL语句成为了
INSERT INTO `phpcmsv9`.`v9_member_detail`(`content`,`userid`) VALUES ('<a href=http://127.0.0.1:81/uploadfile/2023/0223/20230223114555862.php>','2')
但是显然member
模型是没有content
字段的,所以之类会报错;
于是burp中就能够看到报错的数据:
最后获取到了文件名;
因为这里是先进行了文件的上传,再进行的数据库插入操作,所以能够访问对应的文件;
最后访问对应文件;发现文件能够上传;
所以可以上传其它的马,这里只是上传了phpinfo
,没做其它的事情;
0x04 总结
注册模块,改modelid,进下载
最后还是试了很多次,那时候不知道usernaem
和email
会影响$status
:
任重道远
[代码审计基础 15]phpmcs_v9.6 rce的更多相关文章
- [.net 面向对象编程基础] (15) 抽象类
[.net 面向对象编程基础] (15) 抽象类 前面我们已经使用到了虚方法(使用 Virtual修饰符)和抽象类及抽象方法(使用abstract修饰符)我们在多态一节中说到要实现类成员的重写必须定义 ...
- php代码审计基础笔记
出处: 九零SEC连接:http://forum.90sec.org/forum.php?mod=viewthread&tid=8059 --------------------------- ...
- 十五. Python基础(15)--内置函数-1
十五. Python基础(15)--内置函数-1 1 ● eval(), exec(), compile() 执行字符串数据类型的python代码 检测#import os 'import' in c ...
- Java基础15:深入剖析Java枚举类
更多内容请关注微信公众号[Java技术江湖] 这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux ...
- Pandas 基础(15) - date_range 和 asfreq
这一节是承接上一节的内容, 依然是基于时间的数据分析, 接下来带大家理解关于 date_range 的相关用法. 首先, 引入数据文件: import pandas as pd df = pd.rea ...
- JavaScript基础15——js的DOM对象
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- OC基础15:内存管理和自动引用计数
"OC基础"这个分类的文章是我在自学Stephen G.Kochan的<Objective-C程序设计第6版>过程中的笔记. 1.什么是ARC? (1).ARC全名为A ...
- python基础15下_迭代器_生成器
print(dir([])) #告诉我列表拥有的所有方法 # 双下方法 # print([1].__add__([2])) print([1]+[2]) ret = set(dir([]))& ...
- Python之路,第十五篇:Python入门与基础15
python3 异常 异常(基础) 什么是错误? 错误是指由于逻辑或语法错误等,导致一个程序已无法正常执行的问题. 什么是异常? 异常是程序出错时标识的一种状态,当异常发生时,程序不会再向下执行, ...
- C++语言基础(15)-友元函数和友元类
一个类中可以有 public.protected.private 三种属性的成员,通过对象可以访问 public 成员,只有本类中的函数可以访问本类的 private 成员.现在,我们来介绍一种例外情 ...
随机推荐
- Go 的windows安装与环境配置
1.请前往go的官网下载安装包:https://golang.org/dl/ 安装你如果C盘够大比较土豪就一路next即可,在这里小编穷就安装到了D:\Program Files\Go 2.环境变量配 ...
- kubernetes数据持久化StorageClass动态供给(二)
存储类的好处之一便是支持PV的动态供给,它甚至可以直接被视作为PV的创建模版,用户用到持久性存储时,需要通过创建PVC来绑定匹配的PV,此类操作需求较大,或者当管理员手动创建的PV无法满足PVC的所有 ...
- 【接口测试】Postman(一)--接口测试知识准备
1.0 前言 应用程序编程接口(Application Programming Interface, API)是这些年来最流行的技术之一,强大的Web应用程序和领先的移动应用程序都离不开后端强大的 ...
- 云原生架构(二)环境搭建(Mac上安装Docker+Kubernetes+Istio一条龙)
一.背景 Istio 项目由 Google 和 IBM 的团队与 Lyft 的 Envoy 团队合作启动.它已经完全在 GitHub 上公开开发.目前已经是"Service Mesh服务网格 ...
- week_8
Andrew Ng 机器学习笔记 ---By Orangestar Week_7_Unsupervised Learning While supervised learning algorithms ...
- 第一章 --------------------WPF基础概述
1.在使用WPF之前我一直在思考为什么要使用WPF? 主要原因在于我已经受够了MFC和Winform 和QT的界面设计.尤其是MFC的界面设计,使用一个界面库十分的复杂,并且我的绝大多数时间都是用在这 ...
- Java开发学习(四十九)----MyBatisPlus更新语句之乐观锁
1.概念 在讲解乐观锁之前,我们还是先来分析下问题: 业务并发现象带来的问题:秒杀 假如有100个商品或者票在出售,为了能保证每个商品或者票只能被一个人购买,如何保证不会出现超买或者重复卖 对于这一类 ...
- .gitignore文件配置以及gitee提交报Push rejected...错误解决
.gitignore文件配置 .gitignore 文件可以用来忽略被指定的文件或文件夹的改动.记录在.gitignore文件里的文件或文件夹是不会被 git 跟踪到,也就是被忽略的文件是不会被上传到 ...
- 探究SQL SERVER 更改跟踪
1.介绍 SQL SERVER在2008以上的版本提供两个用于数据库中跟踪数据更改的功能:变更数据捕获(CDC)与更改跟踪(CT).这两个功能使应用程序能够确定对数据库中的用户表所做的 DML 更改( ...
- @Transactional事务回滚异常:Transaction rolled back because it has been marked as rollback-only
问题描述 事务设置手动回滚:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly() 代码需要返回比较友好的提示,但t ...