在某些情况下,需要隐藏 GZCTF 的排行榜和排名。
1.Dockerfile 开一个 OpenResty 做反代。
FROM openresty/openresty:centos
COPY hide.js /usr/local/openresty/nginx/conf/
COPY nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
RUN /usr/local/openresty/luajit/bin/luarocks install lua-resty-http
2.OpenResty 里隐藏API的返回。
location ~ ^/api/game/(\d+)/details$ {
gzip off;
content_by_lua_block {
local http = require('resty.http')
local cjson = require "cjson"
-- 获取客户端请求的 Cookie
local cookie = ngx.var.http_cookie
-- 获取游戏 ID
local game_id = ngx.var[1]
-- 创建 HTTP 客户端实例
local httpc = http.new()
-- 发起 HTTP 请求
local res, err = httpc:request_uri("http://gzctf:8080/api/game/" .. game_id .. "/details", {
method = "GET",
headers = {
["Cookie"] = cookie,
["X-Forwarded-For"] = ngx.var.remote_addr,
},
query = ngx.var.args -- 转发查询参数
})
if not res then
ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR
ngx.say("failed to request: ", err)
return
end
if res.status ~= ngx.HTTP_OK then
ngx.status = res.status
ngx.say("failed to request: ", res.body)
return
end
-- 解析 JSON 响应
local data, err = cjson.decode(res.body)
if not data then
ngx.say("failed to decode JSON: ", err)
return
end
-- 修改 rank 字段的正则表达式替换
local modified_body = ngx.re.gsub(res.body, '"rank":\\s*\\d+', '"rank": -1')
modified_body = ngx.re.gsub(modified_body, '"solved":\\s*\\d+', '"solved": -1')
modified_body = ngx.re.gsub(modified_body, '"bloods":\\s*\\[[^\\]]*\\]', '"bloods": []')
-- 发送修改后的 JSON 响应
ngx.header.content_type = "application/json"
ngx.say(modified_body)
}
}
location ~ ^/api/game/(\d+)/scoreboard$ {
return 200 '{
"updateTimeUtc": "2024-05-13T08:54:29.6383344+00:00",
"bloodBonus": 52459530,
"timeLines": {
"all": []
},
"items": [],
"challenges": {}
}';
add_header Content-Type application/json;
}
排名直接改为 -1,积分榜直接返回空。
3. 配置中注入 JS,添加 CSS,把积分展示对应的区域和积分榜按钮隐藏。
location /static/index.CNx9s2ZO.js {
content_by_lua_block {
local http = require("resty.http")
local httpc = http.new()
-- 发起 HTTP 请求
local res, err = httpc:request_uri("http://gzctf:8080/static/index.CNx9s2ZO.js", {
method = "GET",
headers = {
["X-Forwarded-For"] = ngx.var.remote_addr,
}
})
if not res then
ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR
ngx.say("failed to request: ", err)
return
end
if res.status ~= ngx.HTTP_OK then
ngx.status = res.status
ngx.say("failed to request: ", res.body)
return
end
-- 获取响应体
local body = res.body
-- 读取并追加外部 JavaScript 文件内容
local file = io.open("/usr/local/openresty/nginx/conf/hide.js", "r")
local js_code = file:read("*all")
file:close()
-- 在响应体末尾追加 JavaScript 代码
body = body .. js_code
-- 设置响应头的内容类型
ngx.header.content_type = "application/javascript"
-- 发送修改后的响应体
ngx.say(body)
}
}
hide.js和整个容器构建文件可以在 https://github.com/glzjin/GZCTF-Scoreboard-Hide 找到。
1.克隆项目。
git clone https://github.com/glzjin/GZCTF-Scoreboard-Hide.git
2.构建
cd GZCTF-Scoreboard-Hide
docker build -t glzjin/gzctf_scoreboard_hide ./
3.修改docker-compose.yml
version: "3.0"
services:
gzctf:
image: gztime/gzctf:latest
restart: always
environment:
- "GZCTF_ADMIN_PASSWORD=密码"
# choose your backend language `en_US` / `zh_CN` / `ja_JP`
- "LC_ALL=zh_CN.UTF-8"
#ports:
# - "82:8080"
volumes:
- "./data/files:/app/files"
- "./appsettings.json:/app/appsettings.json:ro"
# - "./kube-config.yaml:/app/kube-config.yaml:ro" # this is required for k8s deployment
- "/var/run/docker.sock:/var/run/docker.sock" # this is required for docker deployment
depends_on:
- db
networks:
- default
- challenges
proxy:
image: glzjin/gzctf_scoreboard_hide
restart: always
ports:
- "80:80"
depends_on:
- gzctf
networks:
- default
db:
image: postgres:alpine
restart: always
environment:
- "POSTGRES_PASSWORD=密码"
volumes:
- "./data/db:/var/lib/postgresql/data"
networks:
challenges:
external: true
gzctf端口注释掉,并且把代理加上。
4.重启 GZCTF。
docker-compose up -d