~~ssh~~ https auto update
This commit is contained in:
commit
9b4282aae9
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
/*.bat
|
||||
/*.sh
|
||||
/ssh-*
|
||||
|
||||
/phplib/teaminfo_cache_*
|
||||
|
||||
libvar_gsec.php
|
||||
libvar_tid2proj.php
|
109
api.php
Normal file
109
api.php
Normal file
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
set_time_limit(0);
|
||||
ob_implicit_flush();
|
||||
ignore_user_abort(true);
|
||||
@ini_set("expose_php", "off");
|
||||
header_remove();
|
||||
date_default_timezone_set("Asia/Shanghai");
|
||||
header("Access-Control-Allow-Origin: *");
|
||||
header("Content-type: text/plain; charset=utf-8");
|
||||
header("Cache-Control: no-store, max-age=0, must-revalidate");
|
||||
|
||||
error_reporting(0);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
|
||||
require_once(__DIR__."/phplib/libutil.php");
|
||||
require_once(__DIR__."/phplib/libcustomerrorgen.php");
|
||||
require_once(__DIR__."/phplib/libteamtokenverifier.php");
|
||||
require_once(__DIR__."/phplib/libteaminfo.php");
|
||||
require_once(__DIR__."/phplib/libteamhashgen.php");
|
||||
require_once(__DIR__."/phplib/libchallengelist.php");
|
||||
require_once(__DIR__."/phplib/libattachmentmaker.php");
|
||||
require_once(__DIR__."/phplib/libtemplate_replace_anchor.php");
|
||||
|
||||
|
||||
$query=query2param();
|
||||
|
||||
if($query===false) {
|
||||
gen_error_400("query string not found.");
|
||||
exit;
|
||||
}
|
||||
|
||||
if(!array_key_exists("game", $query)||gettype($query["game"])!="string"||strlen($query["game"])<=0) {
|
||||
gen_error_400("key \"game\" not found or is empty, or has an invalid type.");
|
||||
exit;
|
||||
}
|
||||
|
||||
if(!array_key_exists("action", $query)||gettype($query["action"])!="string") {
|
||||
gen_error_400("key \"action\" not found or has an invalid type. use 'help' to view help");
|
||||
exit;
|
||||
}
|
||||
|
||||
if(!array_key_exists("ttoken", $query)||gettype($query["ttoken"])!="string"||strlen($query["ttoken"])<=0) {
|
||||
gen_error_400("key \"ttoken\" not found or is empty, or has an invalid type.");
|
||||
exit;
|
||||
}
|
||||
|
||||
$action=$query["action"];
|
||||
$action=explode(",", $action);
|
||||
|
||||
//verify the [game, team-hash] pair
|
||||
|
||||
require(__DIR__."/phplib/libvar_gsec.php");
|
||||
|
||||
$game=$query["game"];
|
||||
$team_token=$query["ttoken"];
|
||||
|
||||
if(!array_key_exists($game, $gsecret_l)) {
|
||||
gen_error_400("game '".$game."' is not found in config file.");
|
||||
exit;
|
||||
}
|
||||
|
||||
$ginfo=$gsecret_l[$game];
|
||||
unset($gsecret_l);
|
||||
|
||||
if(!verify_team_token($ginfo["gpub"], $team_token)) {
|
||||
gen_error_400("the team token provided is not valid: ".$team_token);
|
||||
exit;
|
||||
}
|
||||
|
||||
$team_id=explode(":", $team_token)[0];
|
||||
$team_id="team_".$team_id;
|
||||
|
||||
//require files depends on the request
|
||||
//$action, $game, $ginfo, $team_id, $team_token is set
|
||||
|
||||
if($action[0]=="user-panel") {
|
||||
require(__DIR__."/incl_user_panel.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
if($action[0]=="team-info") {
|
||||
require(__DIR__."/incl_get_team_info.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
if($action[0]=="challenge-list") {
|
||||
require(__DIR__."/incl_challenge_list.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
if($action[0]=="attachment-dl") {
|
||||
require(__DIR__."/incl_attachment_dl.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
if($action[0]=="help") {
|
||||
echo "notice: use comma(',') to split args\n";
|
||||
echo "all available commands:\n";
|
||||
echo " user-panel: display a interactive content for user\n";
|
||||
echo " team-info: show your team info as json\n";
|
||||
echo " challenge-list: list all challenges as json which are defined internally\n";
|
||||
echo " attachment-dl <cid>: download attachment for challenge <cid>, or interact with it\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
gen_error_400("unknown action '".$action[0]."'. use 'help' to view help");
|
||||
exit;
|
BIN
assets/Ubuntu Mono derivative Powerline.ttf
Normal file
BIN
assets/Ubuntu Mono derivative Powerline.ttf
Normal file
Binary file not shown.
BIN
assets/favicon.ico
Normal file
BIN
assets/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 264 KiB |
BIN
assets/favicon.png
Normal file
BIN
assets/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 321 KiB |
BIN
assets/team_token_tip.png
Normal file
BIN
assets/team_token_tip.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 101 KiB |
96
assets/ubuntu-font-licence-1.0.txt
Normal file
96
assets/ubuntu-font-licence-1.0.txt
Normal file
@ -0,0 +1,96 @@
|
||||
-------------------------------
|
||||
UBUNTU FONT LICENCE Version 1.0
|
||||
-------------------------------
|
||||
|
||||
PREAMBLE
|
||||
This licence allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely. The fonts, including any derivative works, can be
|
||||
bundled, embedded, and redistributed provided the terms of this licence
|
||||
are met. The fonts and derivatives, however, cannot be released under
|
||||
any other licence. The requirement for fonts to remain under this
|
||||
licence does not require any document created using the fonts or their
|
||||
derivatives to be published under this licence, as long as the primary
|
||||
purpose of the document is not to be a vehicle for the distribution of
|
||||
the fonts.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this licence and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Original Version" refers to the collection of Font Software components
|
||||
as received under this licence.
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to
|
||||
a new environment.
|
||||
|
||||
"Copyright Holder(s)" refers to all individuals and companies who have a
|
||||
copyright ownership of the Font Software.
|
||||
|
||||
"Substantially Changed" refers to Modified Versions which can be easily
|
||||
identified as dissimilar to the Font Software by users of the Font
|
||||
Software comparing the Original Version with the Modified Version.
|
||||
|
||||
To "Propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification and with or without charging
|
||||
a redistribution fee), making available to the public, and in some
|
||||
countries other activities as well.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
This licence does not grant any rights under trademark law and all such
|
||||
rights are reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of the Font Software, to propagate the Font Software, subject to
|
||||
the below conditions:
|
||||
|
||||
1) Each copy of the Font Software must contain the above copyright
|
||||
notice and this licence. These can be included either as stand-alone
|
||||
text files, human-readable headers or in the appropriate machine-
|
||||
readable metadata fields within text or binary files as long as those
|
||||
fields can be easily viewed by the user.
|
||||
|
||||
2) The font name complies with the following:
|
||||
(a) The Original Version must retain its name, unmodified.
|
||||
(b) Modified Versions which are Substantially Changed must be renamed to
|
||||
avoid use of the name of the Original Version or similar names entirely.
|
||||
(c) Modified Versions which are not Substantially Changed must be
|
||||
renamed to both (i) retain the name of the Original Version and (ii) add
|
||||
additional naming elements to distinguish the Modified Version from the
|
||||
Original Version. The name of such Modified Versions must be the name of
|
||||
the Original Version, with "derivative X" where X represents the name of
|
||||
the new work, appended to that name.
|
||||
|
||||
3) The name(s) of the Copyright Holder(s) and any contributor to the
|
||||
Font Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except (i) as required by this licence, (ii) to
|
||||
acknowledge the contribution(s) of the Copyright Holder(s) or (iii) with
|
||||
their explicit written permission.
|
||||
|
||||
4) The Font Software, modified or unmodified, in part or in whole, must
|
||||
be distributed entirely under this licence, and must not be distributed
|
||||
under any other licence. The requirement for fonts to remain under this
|
||||
licence does not affect any document created using the Font Software,
|
||||
except any version of the Font Software extracted from a document
|
||||
created using the Font Software may only be distributed under this
|
||||
licence.
|
||||
|
||||
TERMINATION
|
||||
This licence becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
|
||||
DEALINGS IN THE FONT SOFTWARE.
|
32
assets/user_index_template.html
Normal file
32
assets/user_index_template.html
Normal file
@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html><html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<meta name="referrer" content="no-referrer">
|
||||
<link href="./assets/favicon.png" rel="icon" type="image/png">
|
||||
<link href="./assets/favicon.ico" rel="icon" type="image/x-icon">
|
||||
<title>用户页面 - 附件分发 - woodpecker2024</title>
|
||||
|
||||
<style>
|
||||
a {
|
||||
display: inline-block;
|
||||
margin: 3px 0 3px 0;
|
||||
}
|
||||
a:hover {
|
||||
outline: 2px dashed #0000dd;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head><body>
|
||||
|
||||
<h2>欢迎来到woodpecker2024::ctf</h2>
|
||||
<h2>您当前作为队伍 [#REPLACE-ANCHOR-0#](id=#REPLACE-ANCHOR-1#) 登录</h2>
|
||||
<br>
|
||||
<pre style="margin:0;font-size:1.2rem">
|
||||
<strong>由本服务提供的题目列表(点击下载附件或进行交互,在新窗口打开)</strong><hr>
|
||||
#REPLACE-ANCHOR-2#
|
||||
</pre>
|
||||
|
||||
<footer><hr><small>附件分发系统 for Woodpecker CTF 2024, created by ly65.</small></footer>
|
||||
</body>
|
||||
</html>
|
3
docker_container/Dockerfile
Normal file
3
docker_container/Dockerfile
Normal file
@ -0,0 +1,3 @@
|
||||
FROM debian:11-slim
|
||||
|
||||
RUN sh "./docker_container/script-onboot.sh"
|
72
docker_container/nginx-0.conf
Normal file
72
docker_container/nginx-0.conf
Normal file
@ -0,0 +1,72 @@
|
||||
#it's already in the http directive
|
||||
|
||||
server {
|
||||
listen 2250;
|
||||
listen [::]:2250;
|
||||
listen 2260 ssl;
|
||||
listen [::]:2260 ssl;
|
||||
|
||||
root /root/www;
|
||||
|
||||
add_header Access-Control-Allow-Origin * always;
|
||||
|
||||
index null;
|
||||
|
||||
autoindex on;
|
||||
autoindex_localtime on;
|
||||
charset utf-8,gbk;
|
||||
|
||||
location / {
|
||||
# First attempt to serve request as file, then
|
||||
# as directory, then fall back to displaying a 404.
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
|
||||
location ^~ /ldb/ {
|
||||
proxy_pass http://127.0.0.1:2251/;
|
||||
proxy_connect_timeout 50ms;
|
||||
proxy_set_header Host "$http_host";
|
||||
proxy_buffering off;
|
||||
error_page 502 =200 @error_default;
|
||||
}
|
||||
|
||||
location ~ /internal/ {
|
||||
allow 127.0.0.1;
|
||||
allow 192.168.1.14;
|
||||
deny 192.168.1.0/24;
|
||||
deny all;
|
||||
location ~* (\.php|\.bat)$ {
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass 127.0.0.1:9000;
|
||||
}
|
||||
}
|
||||
|
||||
location ~* \.src$ {
|
||||
try_files $uri $uri/ @try_use_src;
|
||||
}
|
||||
|
||||
location @try_use_src {
|
||||
rewrite (.+)\.src$ $1 break;
|
||||
error_page 404 @error_default;
|
||||
add_header X-Source-File $uri always;
|
||||
add_header Content-Type "text/plain; charset=utf-8" always;
|
||||
}
|
||||
|
||||
location @error_default {}
|
||||
|
||||
location ~* (\.php\.*|\.bat\.*)$ {
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass 127.0.0.1:9000;
|
||||
}
|
||||
|
||||
error_page 405 =200 $uri;
|
||||
|
||||
|
||||
ssl_certificate /root/ly65.top_ecc/pub_chain1.pem;
|
||||
ssl_certificate_key /root/ly65.top_ecc/pri.pem;
|
||||
|
||||
ssl_session_timeout 5m;
|
||||
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
|
||||
ssl_prefer_server_ciphers on;
|
||||
}
|
3
docker_container/script-onboot.sh
Normal file
3
docker_container/script-onboot.sh
Normal file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
tail -f /dev/null
|
1
docker_container/start.sh
Normal file
1
docker_container/start.sh
Normal file
@ -0,0 +1 @@
|
||||
docker run --memory 1GB --user root --volume /media/sf_woodpecker2024/attachment_server/:/root/www/ --volume /media/sf_woodpecker2024/attachment_server/log/:/root/log/ --workdir /root/ --expose 80 --publish 12345:80 --attach stdin --attach stdout --attach stderr --interactive --tty debian:11-slim bash
|
51
incl_attachment_dl.php
Normal file
51
incl_attachment_dl.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
if(count($action)<2) {
|
||||
gen_error_400("missing argument action[1]");
|
||||
exit;
|
||||
}
|
||||
|
||||
$cid=$action[1];
|
||||
|
||||
require(__DIR__."/phplib/libvar_cid2tid.php");
|
||||
|
||||
if(!array_key_exists($game, $cid2tid_l)) {
|
||||
gen_error_404("the game ".$game." does not exist");
|
||||
exit;
|
||||
}
|
||||
$gtid_l=$cid2tid_l[$game];
|
||||
unset($cid2tid_l);
|
||||
|
||||
if(!array_key_exists($cid, $gtid_l)) {
|
||||
gen_error_404("the cid ".$cid." in game ".$game." does not exist");
|
||||
exit;
|
||||
}
|
||||
|
||||
$tid=$gtid_l[$cid];
|
||||
|
||||
require(__DIR__."/phplib/libvar_tid2proj.php");
|
||||
|
||||
if(!array_key_exists($tid, $tid2proj_l)) {
|
||||
gen_error_500("the tid ".$tid." does not exist");
|
||||
exit;
|
||||
}
|
||||
|
||||
$proj=$tid2proj_l[$tid];
|
||||
|
||||
$thash=gen_team_hash($ginfo["gsalt"], substr($cid, strlen("cid_")), $team_token);
|
||||
|
||||
$GLOBALS["game"]=$game;
|
||||
$GLOBALS["team_id"]=$team_id;
|
||||
$GLOBALS["action"]=$action;
|
||||
$GLOBALS["cid"]=$cid;
|
||||
$GLOBALS["tid"]=$tid;
|
||||
$GLOBALS["proj"]=$proj;
|
||||
|
||||
$fn=make_attachment($thash);
|
||||
|
||||
header("Cache-Control: public, max-age=600");
|
||||
header("Content-Type: application/octet-stream");
|
||||
header("Content-Disposition: attachment; filename=\"".$fn[0]."\"");
|
||||
header("Content-Length: ".strlen($fn[1]));
|
||||
|
||||
echo $fn[1];
|
6
incl_challenge_list.php
Normal file
6
incl_challenge_list.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
|
||||
header("Content-type: application/json; charset=utf-8");
|
||||
|
||||
echo json_encode(get_challenge_list($game), JSON_UNESCAPED_UNICODE);
|
5
incl_get_team_info.php
Normal file
5
incl_get_team_info.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
header("Content-type: application/json; charset=utf-8");
|
||||
|
||||
echo json_encode(get_team_info($game, $team_id), JSON_UNESCAPED_UNICODE);
|
30
incl_user_panel.php
Normal file
30
incl_user_panel.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
header("Content-type: text/html; charset=utf-8");
|
||||
|
||||
$li=[];
|
||||
|
||||
//example list
|
||||
$li[0]="team_name";
|
||||
$li[1]="team_id";
|
||||
$li[2]="<a target=\"_blank\" href=\"./api.php?action=attachment-dl,cid_0&game=test-1&ttoken=\">misc::hash-test</a>\n";
|
||||
|
||||
$team_info=get_team_info($game, $team_id);
|
||||
$cid_list=get_challenge_list($game);
|
||||
|
||||
$li[0]=$team_info["name"];
|
||||
$li[1]=$team_info["id"];
|
||||
|
||||
$li[2]="";
|
||||
for($a=0; $a<count($cid_list); $a++) {
|
||||
$li[2].="<a target=\"_blank\" href=";
|
||||
$li[2].=json_encode("./api.php?action=attachment-dl,".rawurlencode($cid_list[$a]["cid"])."&game=".rawurlencode($game)."&ttoken=".rawurlencode($team_token));
|
||||
$li[2].=">".htmlspecialchars($cid_list[$a]["name"])."</a>";
|
||||
$li[2].="\n";
|
||||
}
|
||||
unset($a);
|
||||
|
||||
$str=file_get_contents_with_lock(__DIR__."/assets/user_index_template.html");
|
||||
$str=template_replace_anchor($str, $li);
|
||||
|
||||
echo $str;
|
67
index.html
Normal file
67
index.html
Normal file
@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html><html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<meta name="referrer" content="no-referrer">
|
||||
<link href="./assets/favicon.png" rel="icon" type="image/png">
|
||||
<link href="./assets/favicon.ico" rel="icon" type="image/x-icon">
|
||||
|
||||
<title>ly65的附件分发站 - woodpecker2024</title>
|
||||
|
||||
</head><body>
|
||||
|
||||
<h1>欢迎来到 woodpecker::ctf 2024 !</h1>
|
||||
|
||||
<pre style="margin:0;font-size:1.2rem">
|
||||
这里是 ly65 的一个小站,用于分发本次比赛的部分附件,并提供一些共用容器服务
|
||||
|
||||
在继续之前,请仔细阅读以下说明和约定
|
||||
|
||||
- 本服务使用 <strong><a target="_blank" href="./assets/team_token_tip.png">team_token</a></strong> 验证身份,<strong>请勿泄露</strong>给非本队成员。
|
||||
|
||||
- 除非另有说明,否则本附件分发服务提供的附件对每个用户都是固定的,不会因时间或请求次数而改变。
|
||||
|
||||
- 为了确保有足够的辨识度,若 flag 需要从图形中读出,此类 flag 统一使用 <strong><a target="_blank" href="./assets/Ubuntu%20Mono%20derivative%20Powerline.ttf">Ubuntu Mono derivative Powerline</a></strong> 字体绘制(<strong><a target="_blank" href="./assets/ubuntu-font-licence-1.0.txt">字体licence</a></strong>)
|
||||
|
||||
- <strong>本服务器并非靶机</strong>,未进行安全防护,且可用资源有限。在比赛期间,它是一个<strong>共用容器</strong>,因此:
|
||||
|
||||
- 所有交互题目都被设计能够在 30 次 HTTP 请求之内完成。请<strong>避免频繁或重复请求</strong>,以免过度占用服务器资源。
|
||||
|
||||
- <strong>请勿</strong>进行<strong>渗透、注入、端口扫描等攻击</strong>。但<strong>允许</strong>对本附件分发服务(<strong>仅 /api.php</strong>)发送任意 HTTP 请求,只要不频繁发送或携带大量数据。
|
||||
|
||||
- 对于可能与其他队伍产生信息交流的特殊题目,<strong>请勿泄露任何比赛相关内容,包括但不限于 flag、team_token、解题思路等</strong>。
|
||||
|
||||
我们会记录比赛期间的服务器日志等信息,以检测违规行为,并视情况对违规者进行警告、禁赛等处罚。
|
||||
|
||||
请共同维护公平、友好的比赛环境。
|
||||
|
||||
|
||||
<strong>继续操作即视为您同意遵守上述约定</strong>
|
||||
|
||||
|
||||
</pre>
|
||||
|
||||
<form method="get" action="./api.php" style="display:inline">
|
||||
|
||||
<input type="text" name="action" value="user-panel" style="display:none" required>
|
||||
|
||||
<span style="display:block">
|
||||
比赛id
|
||||
<select name="game" required>
|
||||
<option value="test-1">localhost内测</option>
|
||||
<option value="wood-1">woodpecker内测</option>
|
||||
<option value="wood-2" selected>woodpecker正式比赛</option>
|
||||
</select>
|
||||
</span>
|
||||
|
||||
请输入您的team_token
|
||||
<input type="text" name="ttoken" pattern="[0-9]+:[0-9a-zA-Z\/\+]{86}={0,2}" style="width:50%" placeholder="example: 1:4RJpuP0QRAXNIGVwymjAK3+1FKB/VRZ+Ah5LfGLZXQrZLxxcQ4lt32bdQ1vv+r0C9OQXDDvXaq8cEGuDD9/8e8==" required>
|
||||
|
||||
<input type="submit" value="点击这个按钮继续">
|
||||
</form>
|
||||
|
||||
<br>
|
||||
<br>
|
||||
<footer><hr><small>附件分发系统 for Woodpecker CTF 2024, created by ly65.</small></footer>
|
||||
</body>
|
||||
</html>
|
86
phplib/libattachmentmaker.php
Normal file
86
phplib/libattachmentmaker.php
Normal file
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
require_once(__DIR__."/libfilelist2zip.php");
|
||||
|
||||
function make_attachment($thash) {
|
||||
global $proj;
|
||||
|
||||
$pf=realpath(__DIR__."/../".$proj["path"]."/automake_attachment.php");
|
||||
|
||||
if(!is_readable($pf)) {
|
||||
gen_error_500("challange ".$proj["name"]." has been found, but the entry automake_attachment.php does not exist.");
|
||||
exit;
|
||||
}
|
||||
|
||||
require($pf);
|
||||
|
||||
if(!function_exists("make_attachment_impl")) {
|
||||
gen_error_500("challange ".$proj["name"]." has been found, but the entry automake_attachment.php doesn't implement the function make_attachment_impl(\$team_hash).");
|
||||
exit;
|
||||
}
|
||||
|
||||
$font_path=getenv("GDFONTPATH");
|
||||
|
||||
if($font_path===false) {
|
||||
$font_path="";
|
||||
} else {
|
||||
$font_path.=";";
|
||||
}
|
||||
|
||||
//init GDFONTPATH to generate images containing text
|
||||
|
||||
$font_path.=realpath(__DIR__).";";
|
||||
$font_path.=realpath(__DIR__."/../").";";
|
||||
$font_path.=realpath(__DIR__."/../assets/").";";
|
||||
$font_path.=dirname($pf).";";
|
||||
|
||||
putenv("GDFONTPATH=".$font_path);
|
||||
|
||||
$GLOBALS["c_random_int_seed"]=hash("sha512", hash("md5", hash("sha256", $thash, true)), true);
|
||||
|
||||
$GLOBALS["c_random_int"]=function($min, $max) {
|
||||
if(!is_int($min) || !is_int($max)) {
|
||||
gen_error_500("\$c_random_int(): invalid arguments: \$min or \$max is not integer");
|
||||
exit;
|
||||
}
|
||||
if($min==$max) {
|
||||
return $min;
|
||||
}
|
||||
if($min>$max) {
|
||||
list($min, $max)=[$max, $min];
|
||||
}
|
||||
$delta=$max-$min;
|
||||
if($delta<0||$delta>PHP_INT_MAX) {
|
||||
gen_error_500("\$c_random_int(): \$delta is not between 0 and PHP_INT_MAX(".(string)PHP_INT_MAX.")");
|
||||
exit;
|
||||
}
|
||||
$t=$delta;
|
||||
$res=0;
|
||||
for($a=0; $t>0; $a++) {
|
||||
$res<<=8;
|
||||
$res|=unpack("C", $GLOBALS["c_random_int_seed"][$a&63])[1]; //&63 is equal to %64
|
||||
$t>>=8;
|
||||
}
|
||||
unset($a);
|
||||
$res&=$delta; //avoid mod(%) operator, as it makes the result not evenly distributed
|
||||
$GLOBALS["c_random_int_seed"]=hash("sha512", $GLOBALS["c_random_int_seed"], true);
|
||||
return $min+$res;
|
||||
};
|
||||
|
||||
//the function make_attachment_impl($team_hash) should return an array [(string)filename, (string)file_content] on success, or boolean false if it failed to generate.
|
||||
|
||||
$fn=make_attachment_impl($thash);
|
||||
if($fn===false||!is_array($fn)||count($fn)!=2||gettype($fn[0])!="string"||gettype($fn[1])!="string") {
|
||||
$out="failed to make attachment for challange ".$proj["name"].": function call to make_attachment_impl(\$team_hash) failed or the returned value is invalid.";
|
||||
if(gettype($fn)=="string") {
|
||||
$out.="\nThe generator returned the following error:\n";
|
||||
$out.=$fn;
|
||||
}
|
||||
gen_error_500($out);
|
||||
exit;
|
||||
}
|
||||
if(strlen($fn[0])<=0) {
|
||||
$fn[0]="attachment.bin";
|
||||
}
|
||||
return $fn;
|
||||
}
|
36
phplib/libchallengelist.php
Normal file
36
phplib/libchallengelist.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
function get_challenge_list($game) {
|
||||
|
||||
require(__DIR__."/libvar_cid2tid.php");
|
||||
|
||||
if(!array_key_exists($game, $cid2tid_l)) {
|
||||
gen_error_404("the game ".$game." does not exist");
|
||||
exit;
|
||||
}
|
||||
$cid2tid=$cid2tid_l[$game];
|
||||
unset($cid2tid_l);
|
||||
|
||||
$cid2tid_keys=array_keys($cid2tid);
|
||||
|
||||
require(__DIR__."/libvar_tid2proj.php");
|
||||
|
||||
$res=[];
|
||||
|
||||
for($a=0; $a<count($cid2tid_keys); $a++) {
|
||||
if(!array_key_exists($cid2tid[$cid2tid_keys[$a]], $tid2proj_l)) {
|
||||
gen_error_500("the tid ".$cid2tid[$cid2tid_keys[$a]]." is set but does not exist in \$tid2proj_l");
|
||||
exit;
|
||||
}
|
||||
$b=$tid2proj_l[$cid2tid[$cid2tid_keys[$a]]];
|
||||
if(array_key_exists("hidden", $b)&&$b["hidden"]) {
|
||||
continue;
|
||||
}
|
||||
$b["cid"]=$cid2tid_keys[$a];
|
||||
$b["tid"]=$cid2tid[$cid2tid_keys[$a]];
|
||||
$res[]=$b;
|
||||
}
|
||||
unset($b);
|
||||
unset($a);
|
||||
return $res;
|
||||
}
|
32
phplib/libcustomerrorgen.php
Normal file
32
phplib/libcustomerrorgen.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
function gen_error_400($reason="") {
|
||||
http_response_code(400);
|
||||
echo "bad request: ";
|
||||
echo $reason;
|
||||
echo "\n";
|
||||
echo "(,,#゚Д゚)你对这个小程序做了什么哇...";
|
||||
echo "\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
function gen_error_404($reason="") {
|
||||
http_response_code(404);
|
||||
echo $reason;
|
||||
echo "\n";
|
||||
echo "(⊙.⊙)这...这不对吧...";
|
||||
echo "\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
function gen_error_500($reason="") {
|
||||
http_response_code(500);
|
||||
echo "internal error: ";
|
||||
echo $reason;
|
||||
echo "\n";
|
||||
echo "Σ(っ °Д °;)っ哇啊!服务器居然出错惹...呜呜...╥﹏╥";
|
||||
echo "\n";
|
||||
echo "请刷新重试几次,还是不行的话,请从群里找到ly65喵(可能叫 流萤#65 或者 lhy6305 之类的)私聊进行敲打,附上你的请求参数和上面的报错信息,谢谢喵";
|
||||
echo "\n";
|
||||
exit;
|
||||
}
|
50
phplib/libfilelist2zip.php
Normal file
50
phplib/libfilelist2zip.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
function filelist_to_zip($fnl) {
|
||||
//$fnl = [ [ (string)name, (string)data ], ...]
|
||||
$res="";
|
||||
|
||||
$fentry_info=[];
|
||||
for($a=0; $a<count($fnl); $a++) {
|
||||
$fentry_info[$a]=strlen($res);
|
||||
$fe="";
|
||||
$fe.=pack("H*", str_replace(" ", "", "50 4B 03 04 01 00 00 08 00 00 00 00 00 00"));
|
||||
$fe.=strrev(pack("H*", hash("crc32b", $fnl[$a][1])));
|
||||
$fe.=strrev(pack("H*", str_pad(dechex(strlen($fnl[$a][1])), 8, "0", STR_PAD_LEFT)));
|
||||
$fe.=strrev(pack("H*", str_pad(dechex(strlen($fnl[$a][1])), 8, "0", STR_PAD_LEFT)));
|
||||
$fe.=strrev(pack("H*", str_pad(dechex(strlen($fnl[$a][0])), 4, "0", STR_PAD_LEFT)));
|
||||
$fe.=pack("H*", str_replace(" ", "", "00 00"));
|
||||
$fe.=$fnl[$a][0];
|
||||
$fe.=$fnl[$a][1];
|
||||
$res.=$fe;
|
||||
}
|
||||
unset($fe);
|
||||
unset($a);
|
||||
|
||||
$doffset=strlen($res);
|
||||
|
||||
for($a=0; $a<count($fnl); $a++) {
|
||||
$de="";
|
||||
$de.=pack("H*", str_replace(" ", "", "50 4B 01 02 01 00 01 00 00 08 00 00 00 00 00 00"));
|
||||
$de.=strrev(pack("H*", hash("crc32b", $fnl[$a][1])));
|
||||
$de.=strrev(pack("H*", str_pad(dechex(strlen($fnl[$a][1])), 8, "0", STR_PAD_LEFT)));
|
||||
$de.=strrev(pack("H*", str_pad(dechex(strlen($fnl[$a][1])), 8, "0", STR_PAD_LEFT)));
|
||||
$de.=strrev(pack("H*", str_pad(dechex(strlen($fnl[$a][0])), 4, "0", STR_PAD_LEFT)));
|
||||
$de.=pack("H*", str_replace(" ", "", "00 00 00 00 00 00 00 00 00 00 00 00"));
|
||||
$de.=strrev(pack("H*", str_pad(dechex($fentry_info[$a]), 8, "0", STR_PAD_LEFT)));
|
||||
$de.=$fnl[$a][0];
|
||||
$res.=$de;
|
||||
}
|
||||
unset($de);
|
||||
unset($a);
|
||||
|
||||
$dsize=strlen($res)-$doffset;
|
||||
|
||||
$res.=pack("H*", str_replace(" ", "", "50 4B 05 06 00 00 00 00"));
|
||||
$res.=strrev(pack("H*", str_pad(dechex(count($fnl)), 4, "0", STR_PAD_LEFT)));
|
||||
$res.=strrev(pack("H*", str_pad(dechex(count($fnl)), 4, "0", STR_PAD_LEFT)));
|
||||
$res.=strrev(pack("H*", str_pad(dechex($dsize), 8, "0", STR_PAD_LEFT)));
|
||||
$res.=strrev(pack("H*", str_pad(dechex($doffset), 8, "0", STR_PAD_LEFT)));
|
||||
$res.=pack("H*", str_replace(" ", "", "00 00"));
|
||||
return $res;
|
||||
}
|
9
phplib/libteamhashgen.php
Normal file
9
phplib/libteamhashgen.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
function gen_team_hash($gsalt, $cid, $team_token) {
|
||||
//you should verify the variable $team_token before calling this function!
|
||||
$csalt = hash("sha256", $gsalt."::".$cid);
|
||||
$thash = hash("sha256", $csalt."::".$team_token);
|
||||
$thash = substr($thash, 12, 12);
|
||||
return $thash;
|
||||
}
|
71
phplib/libteaminfo.php
Normal file
71
phplib/libteaminfo.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
require_once(__DIR__."/libutil.php");
|
||||
require_once(__DIR__."/libcustomerrorgen.php");
|
||||
|
||||
function get_team_info($game, $team_id) {
|
||||
//read from cache first
|
||||
$cache_file_name=__DIR__."/teaminfo_cache_".$game.".json";
|
||||
$cache_file=false;
|
||||
if(file_exists($cache_file_name)&&is_readable($cache_file_name)) {
|
||||
$cache_file=file_get_contents_with_lock($cache_file_name);
|
||||
}
|
||||
|
||||
$cache_file=json_decode($cache_file, true);
|
||||
if($cache_file===null) {
|
||||
$cache_file=false;
|
||||
}
|
||||
|
||||
if($cache_file===false||!array_key_exists($team_id, $cache_file)) {
|
||||
require(__DIR__."/libvar_gsec.php");
|
||||
|
||||
if(!array_key_exists($game, $gsecret_l)) {
|
||||
gen_error_400("game ".$game." is not found in config file.");
|
||||
exit;
|
||||
}
|
||||
$ginfo=$gsecret_l[$game];
|
||||
unset($gsecret_l);
|
||||
|
||||
$url=$ginfo["gurlbase"]."/api/game/".$ginfo["gid"]."/scoreboard";
|
||||
$url=preg_replace("#/+#", "/", $url);
|
||||
|
||||
$cu=curl_init($url);
|
||||
curl_setopt($cu, CURLOPT_RETURNTRANSFER, true);
|
||||
//curl_setopt($cu, CURLOPT_SSL_VERIFYPEER, false);
|
||||
//curl_setopt($cu, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($cu, CURLOPT_CONNECTTIMEOUT_MS, 2000);
|
||||
curl_setopt($cu, CURLOPT_TIMEOUT_MS, 7000);
|
||||
$re=curl_exec($cu);
|
||||
$err=curl_error($cu);
|
||||
curl_close($cu);
|
||||
if(strlen($err)>0||$re===false||strlen($re)<=0) {
|
||||
gen_error_500("api request failed when trying to fetch team_info: ".$err);
|
||||
exit;
|
||||
}
|
||||
$jo=json_decode($re, true);
|
||||
if($jo===null) {
|
||||
gen_error_500("api request failed when trying to fetch team_info: cannot decode response as json");
|
||||
exit;
|
||||
}
|
||||
if(!array_key_exists("items", $jo)) {
|
||||
gen_error_500("api request failed when trying to fetch team_info: key \"items\" does not exist");
|
||||
exit;
|
||||
}
|
||||
$jo1=[];
|
||||
for($a=0; $a<count($jo["items"]); $a++) {
|
||||
$jo1["team_".(string)$jo["items"][$a]["id"]]=$jo["items"][$a];
|
||||
}
|
||||
$cache_file=$jo1;
|
||||
unset($jo1);
|
||||
unset($jo);
|
||||
unset($a);
|
||||
file_put_contents_with_lock($cache_file_name, json_encode($cache_file, JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
if(!array_key_exists($team_id, $cache_file)) {
|
||||
//unexpected logic here... why...
|
||||
gen_error_500("unexpected logic: team token is valid, but is not found in team_info");
|
||||
exit;
|
||||
}
|
||||
return $cache_file[$team_id];
|
||||
}
|
26
phplib/libteamtokenverifier.php
Normal file
26
phplib/libteamtokenverifier.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
function verify_team_token($gpub, $ttok) {
|
||||
if(!function_exists("sodium_crypto_sign_verify_detached")) {
|
||||
gen_error_500("function sodium_crypto_sign_verify_detached() not exists");
|
||||
exit;
|
||||
}
|
||||
$gpub=base64_decode($gpub);
|
||||
if($gpub===false||strlen($gpub)!==SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES) {
|
||||
gen_error_500("invalid \$gpub data");
|
||||
exit;
|
||||
}
|
||||
$ttok=explode(":", $ttok, 2);
|
||||
if(count($ttok)!==2) {
|
||||
return false;
|
||||
}
|
||||
if(!preg_match("#^[0-9]+$#", $ttok[0])) {
|
||||
return false;
|
||||
}
|
||||
$data="GZCTF_TEAM_".$ttok[0];
|
||||
$ttok[1]=base64_decode($ttok[1]);
|
||||
if($ttok[1]===false||strlen($ttok[1])!==SODIUM_CRYPTO_SIGN_BYTES) {
|
||||
return false;
|
||||
}
|
||||
return sodium_crypto_sign_verify_detached($ttok[1], $data, $gpub);
|
||||
}
|
57
phplib/libtemplate_replace_anchor.php
Normal file
57
phplib/libtemplate_replace_anchor.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
function template_replace_anchor($str, $li) {
|
||||
$ptr=0;
|
||||
for(;;) {
|
||||
$ma=[];
|
||||
/*
|
||||
replace flag list
|
||||
multiple flags can be used together
|
||||
|
||||
<empty>: raw string. e.g. string
|
||||
V: variable-like. e.g. "string"
|
||||
N: same as V, but with quotes removed. e.g. string
|
||||
U: utf-8 encoded. e.g. \uxxxx\uxxxx\uxxxx
|
||||
*/
|
||||
preg_match("/#REPLACE-ANCHOR-([A-Z]*?)([0-9]+)#/", $str, $ma, PREG_OFFSET_CAPTURE, $ptr);
|
||||
if(count($ma)<=0) {
|
||||
break;
|
||||
}
|
||||
$da="";
|
||||
if(array_key_exists((int)$ma[2][0], $li)) {
|
||||
$da=$li[$ma[2][0]];
|
||||
}
|
||||
|
||||
$ma[1][0]=strtoupper($ma[1][0]);
|
||||
//process flags
|
||||
for($a=0; $a<strlen($ma[1][0]); $a++) {
|
||||
if($ma[1][0][$a]=="V") {
|
||||
@$da=(string)$da;
|
||||
$da=json_encode($da, JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE);
|
||||
} else if($ma[1][0][$a]=="N") {
|
||||
$da=substr($da, 1, -1);
|
||||
} else if($ma[1][0][$a]=="U") {
|
||||
$da1="";
|
||||
for($b=0; $b<mb_strlen($da); $b++) {
|
||||
$c=mb_substr($da, $b, 1);
|
||||
if(strlen($c)===1) {
|
||||
$da1.=$c;
|
||||
} else {
|
||||
$da1.=sprintf("\\u%04x", mb_ord($c));
|
||||
}
|
||||
}
|
||||
$da=$da1;
|
||||
unset($da1);
|
||||
unset($b);
|
||||
unset($c);
|
||||
}
|
||||
}
|
||||
unset($a);
|
||||
//merge string
|
||||
$str=substr($str, 0, $ma[0][1]).$da.substr($str, $ma[0][1]+strlen($ma[0][0]));
|
||||
$ptr=$ma[0][1]+strlen($da);
|
||||
}
|
||||
unset($ma);
|
||||
unset($da);
|
||||
return $str;
|
||||
}
|
118
phplib/libutil.php
Normal file
118
phplib/libutil.php
Normal file
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
if(!function_exists("str_starts_with")) {
|
||||
function str_starts_with($haystack, $needle) {
|
||||
if(!is_string($needle)||!is_string($haystack)) {
|
||||
return false;
|
||||
}
|
||||
if(strlen($needle)<=0) {
|
||||
return true;
|
||||
}
|
||||
if(strlen($needle)>strlen($haystack)) {
|
||||
return false;
|
||||
}
|
||||
if(strncmp($needle, $haystack, strlen($needle))==0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
//end of str_starts_with
|
||||
}
|
||||
}
|
||||
|
||||
if(!function_exists("mb_str_pad")) {
|
||||
function mb_str_pad($str, $pad_len, $pad_str=" ", $dir=STR_PAD_RIGHT, $encoding=null) {
|
||||
$encoding=($encoding===null?mb_internal_encoding():$encoding);
|
||||
$padBefore=($dir===STR_PAD_BOTH||$dir===STR_PAD_LEFT);
|
||||
$padAfter=($dir===STR_PAD_BOTH||$dir===STR_PAD_RIGHT);
|
||||
$pad_len-=mb_strlen($str, $encoding);
|
||||
$targetLen=$padBefore&&$padAfter?$pad_len/2:$pad_len;
|
||||
$strToRepeatLen=mb_strlen($pad_str, $encoding);
|
||||
$repeatTimes=ceil($targetLen/$strToRepeatLen);
|
||||
$repeatedString=str_repeat($pad_str, max(0, $repeatTimes)); // safe if used with valid utf-8 strings
|
||||
$before=$padBefore?mb_substr($repeatedString, 0, floor($targetLen), $encoding):"";
|
||||
$after=$padAfter?mb_substr($repeatedString, 0, ceil($targetLen), $encoding):"";
|
||||
return $before.$str.$after;
|
||||
//end of mb_str_pad
|
||||
}
|
||||
}
|
||||
|
||||
function getms() {
|
||||
list($u, $s)=explode(" ", microtime());
|
||||
return (string)round(((float)$u+(float)$s)*1000);
|
||||
}
|
||||
|
||||
function query2param() {
|
||||
$qstr="";
|
||||
if(array_key_exists("QUERY_STRING", $_SERVER)) {
|
||||
$qstr=$_SERVER["QUERY_STRING"];
|
||||
} else {
|
||||
$qstr=file_get_contents("php://input");
|
||||
}
|
||||
if(gettype($qstr)!="string"||strlen($qstr)<=0) {
|
||||
return false;
|
||||
}
|
||||
$param=[];
|
||||
$qstr=explode("&", $qstr);
|
||||
for($a=0; $a<count($qstr); $a++) {
|
||||
$qstr[$a]=explode("=", $qstr[$a], 2);
|
||||
if(count($qstr[$a])<=1) {
|
||||
$param[$qstr[$a][0]]="";
|
||||
continue;
|
||||
}
|
||||
$param[$qstr[$a][0]]=rawurldecode($qstr[$a][1]);
|
||||
}
|
||||
return $param;
|
||||
}
|
||||
|
||||
function file_put_contents_with_lock($filename, $data) {
|
||||
$handle=fopen($filename, "c+");
|
||||
if($handle===false) {
|
||||
trigger_error("file_put_contents_with_lock: failed to open file ".$filename, E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
if(!flock($handle, LOCK_EX)) {
|
||||
trigger_error("file_put_contents_with_lock: failed to lock file ".$filename." after fopen(...)", E_USER_WARNING);
|
||||
fclose($handle);
|
||||
return false;
|
||||
}
|
||||
ftruncate($handle, 0);
|
||||
rewind($handle);
|
||||
$result=fwrite($handle, $data);
|
||||
if($result===false) {
|
||||
trigger_error("file_put_contents_with_lock: failed to write file content of ".$filename, E_USER_WARNING);
|
||||
} else {
|
||||
fflush($handle);
|
||||
}
|
||||
flock($handle, LOCK_UN);
|
||||
fclose($handle);
|
||||
return $result;
|
||||
}
|
||||
|
||||
function file_get_contents_with_lock($filename) {
|
||||
if(!file_exists($filename) || !is_readable($filename)) {
|
||||
trigger_error("file_get_contents_with_lock: file ".$filename." not exists or is not readable", E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
$handle=fopen($filename, "rb");
|
||||
if($handle===false) {
|
||||
trigger_error("file_get_contents_with_lock: failed to open file ".$filename, E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
if(!flock($handle, LOCK_SH)) {
|
||||
trigger_error("file_get_contents_with_lock: failed to lock file ".$filename." after fopen(...)", E_USER_WARNING);
|
||||
fclose($handle);
|
||||
return false;
|
||||
}
|
||||
$fsize=filesize($filename);
|
||||
$data=false;
|
||||
if($fsize===false) {
|
||||
trigger_error("file_get_contents_with_lock: failed to get size of ".$filename, E_USER_WARNING);
|
||||
} else if($fsize==0) {
|
||||
$data="";
|
||||
} else {
|
||||
$data=fread($handle, $fsize);
|
||||
}
|
||||
flock($handle, LOCK_UN);
|
||||
fclose($handle);
|
||||
return $data;
|
||||
}
|
35
phplib/libvar_cid2tid.php
Normal file
35
phplib/libvar_cid2tid.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
//this is for converting between challenge_id and task_id
|
||||
|
||||
$cid2tid_l=[
|
||||
|
||||
"test-1"=>[
|
||||
"cid_7"=>"tid_0",
|
||||
"cid_1"=>"tid_1",
|
||||
"cid_2"=>"tid_2",
|
||||
"cid_3"=>"tid_3",
|
||||
"cid_4"=>"tid_4",
|
||||
"cid_5"=>"tid_5",
|
||||
"cid_6"=>"tid_6",
|
||||
],
|
||||
|
||||
"wood-1"=>[
|
||||
"cid_39"=>"tid_1",
|
||||
"cid_40"=>"tid_2",
|
||||
"cid_43"=>"tid_3",
|
||||
"cid_42"=>"tid_4",
|
||||
"cid_44"=>"tid_5",
|
||||
"cid_41"=>"tid_6",
|
||||
],
|
||||
|
||||
"wood-2"=>[
|
||||
"cid_1"=>"tid_1",
|
||||
"cid_2"=>"tid_2",
|
||||
"cid_3"=>"tid_3",
|
||||
"cid_4"=>"tid_4",
|
||||
"cid_5"=>"tid_5",
|
||||
"cid_6"=>"tid_6",
|
||||
],
|
||||
|
||||
];
|
17
phplib/libvar_gsec.example.php
Normal file
17
phplib/libvar_gsec.example.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
//this is the secret pool for signing flags
|
||||
|
||||
//!WARNING! Disclosure of the contents of this document is strictly prohibited!
|
||||
|
||||
// !NOTICE! This is ONLY a TEMPLATE file !!
|
||||
// PLEASE REPORT IMMEDIATELY if you found a real one named libvar_gsec.php
|
||||
|
||||
$gsecret_l=[
|
||||
"test-1"=>[
|
||||
"gurlbase"=>"http://192.168.1.66/",
|
||||
"gid"=>1,
|
||||
"gpub"=>"nvnP000000000000000000000000000000000000gb4=",
|
||||
"gsalt"=>"bfc90000000000000000000000000000000000000000000000000000000037e5",
|
||||
],
|
||||
];
|
13
phplib/libvar_tid2proj.example.php
Normal file
13
phplib/libvar_tid2proj.example.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
//this is for converting between task_id and proj_info
|
||||
|
||||
$tid2proj_l=[
|
||||
|
||||
"tid_0"=>[
|
||||
"name"=>"misc::hash-test",
|
||||
"path"=>"./misc/local-hash-test/",
|
||||
"hidden"=>false,
|
||||
],
|
||||
|
||||
];
|
13
readme.md
Normal file
13
readme.md
Normal file
@ -0,0 +1,13 @@
|
||||
# attachment-server
|
||||
|
||||
这是一个简单的ctf动态附件分发程序,为woodpecker ctf编写
|
||||
|
||||
## 如果你看到了下面列出的文件*本身*而不是*模板示例*,请立刻上报管理员,这很重要!
|
||||
|
||||
- `phplib/libvar_gsec.php` 存放比赛的 **公钥`gpub`** 和 **`gamesalt`(`gsalt`)** 。
|
||||
这两个值分别用于验证`team_token`和计算`team_hash`,此文件泄漏会导致 **全部`team_hash`** 泄漏为可计算的,从而丢失动态flag中`team_hash`的随机性。
|
||||
|
||||
- `phplib/libvar_tid2proj.php` 存放 **本地题目id `task_id`(`tid`)** 和 **本地工程信息 `proj_info`** 的映射关系,此文件泄漏会导致 **题目文件夹相对路径** 泄漏,从而可能导致 **题目名称** 泄漏。
|
||||
|
||||
## LICENCE
|
||||
作者保留所有权利,暂不开放使用
|
Loading…
x
Reference in New Issue
Block a user