+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 a20476ae..5c58c92b 100644
--- a/java-sec-code.iml
+++ b/java-sec-code.iml
@@ -1,232 +1,14 @@
-+ * 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/XXE.java b/src/main/java/org/joychou/controller/XXE.java
index 36372727..58e90739 100644
--- a/src/main/java/org/joychou/controller/XXE.java
+++ b/src/main/java/org/joychou/controller/XXE.java
@@ -234,7 +234,7 @@ public String DigesterSec(HttpServletRequest request) {
* Use request.getInputStream to support UTF16 encoding.
*/
@RequestMapping(value = "/DocumentBuilder/vuln", method = RequestMethod.POST)
- public String DocumentBuilderVuln01(HttpServletRequest request) {
+ public String DocumentBuilderVuln(HttpServletRequest request) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
@@ -436,8 +436,8 @@ public interface UserPayload {
String getUserName();
}
+ public static void main(String[] args) {
- public static void main(String[] args) {
}
}
\ No newline at end of file
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/security/ssrf/SSRFChecker.java b/src/main/java/org/joychou/security/ssrf/SSRFChecker.java
index 71abc91e..c2b3896a 100644
--- a/src/main/java/org/joychou/security/ssrf/SSRFChecker.java
+++ b/src/main/java/org/joychou/security/ssrf/SSRFChecker.java
@@ -188,6 +188,7 @@ public static String host2ip(String host) {
InetAddress IpAddress = InetAddress.getByName(host);
return IpAddress.getHostAddress();
} catch (Exception e) {
+ logger.error("host2ip exception " + e.getMessage());
return "";
}
}
@@ -198,45 +199,57 @@ public static String host2ip(String host) {
* @return Octal ip returns true, others return false. 012.23.78.233 return true. 012.0x17.78.233 return false.
*/
public static boolean isOctalIP(String host) {
- String[] ipParts = host.split("\\.");
- StringBuilder newDecimalIP = new StringBuilder();
- boolean is_octal = false;
-
- // Octal ip only has number and dot character.
- if (isNumberOrDot(host)) {
-
- // not support ipv6
- if (ipParts.length > 4) {
- throw new SSRFException("Illegal ipv4: " + host);
- }
-
- // 01205647351
- if( ipParts.length == 1 && host.startsWith("0") ) {
- decimalIp = Integer.valueOf(host, 8).toString();
- return true;
- }
+ try{
+ String[] ipParts = host.split("\\.");
+ StringBuilder newDecimalIP = new StringBuilder();
+ boolean is_octal = false;
+
+ // Octal ip only has number and dot character.
+ if (isNumberOrDot(host)) {
+
+ // not support ipv6
+ if (ipParts.length > 4) {
+ logger.error("Illegal ipv4: " + host);
+ return false;
+ }
- // 012.23.78.233
- for(String ip : ipParts) {
- if (!isNumber(ip)){
- throw new SSRFException("Illegal ipv4: " + host);
+ // 01205647351
+ if( ipParts.length == 1 && host.startsWith("0") ) {
+ decimalIp = Integer.valueOf(host, 8).toString();
+ return true;
}
- if (ip.startsWith("0")) {
- if (Integer.valueOf(ip, 8) >= 256){
- throw new SSRFException("Illegal ipv4: " + host);
+
+ // 012.23.78.233
+ for(String ip : ipParts) {
+ if (!isNumber(ip)){
+ logger.error("Illegal ipv4: " + host);
+ return false;
}
- newDecimalIP.append(Integer.valueOf(ip, 8)).append(".");
- is_octal = true;
- }else{
- if (Integer.valueOf(ip, 10) >= 256) {
- throw new SSRFException("Illegal ipv4: " + host);
+ // start with "0", but not "0"
+ if (ip.startsWith("0") && !ip.equals("0")) {
+ if (Integer.valueOf(ip, 8) >= 256){
+ logger.error("Illegal ipv4: " + host);
+ return false;
+ }
+ newDecimalIP.append(Integer.valueOf(ip, 8)).append(".");
+ is_octal = true;
+ }else{
+ if (Integer.valueOf(ip, 10) >= 256) {
+ logger.error("Illegal ipv4: " + host);
+ return false;
+ }
+ newDecimalIP.append(ip).append(".");
}
- newDecimalIP.append(ip).append(".");
}
+ // delete last char .
+ decimalIp = newDecimalIP.substring(0, newDecimalIP.lastIndexOf("."));
}
- decimalIp = newDecimalIP.substring(0, newDecimalIP.lastIndexOf("."));
+ return is_octal;
+ } catch (Exception e){
+ logger.error("SSRFChecker isOctalIP exception: " + e.getMessage());
+ return false;
}
- return is_octal;
+
}
/**
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 d5c6d5ab..326a2b76 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -9,8 +9,6 @@ logging.level.org.joychou.mapper=debug
# Spring Boot Actuator Config
management.security.enabled=false
-endpoints.enabled=true
-
# logging.config=classpath:logback-online.xml
@@ -48,10 +46,14 @@ 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 ###
# 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/index.html b/src/main/resources/templates/index.html
index 8511d5fd..7e7061be 100644
--- a/src/main/resources/templates/index.html
+++ b/src/main/resources/templates/index.html
@@ -5,29 +5,30 @@
Hello .
-Welcome to login java-sec-code application. Application Infomation
-- Swagger - CmdInject - JSONP - Picture Upload - File Upload - Cors - PathTraversal - SqlInject - SSRF - RCE - ooxml XXE - xlsx-streamer XXE -
+Hello .
+Welcome to login java-sec-code application. Application Infomation
++ Swagger + CmdInject + JSONP + Picture Upload + File Upload + Cors + PathTraversal + SqlInject + SSRF + RCE + ooxml XXE + xlsx-streamer XXE + actuator env +
-- JWTCreateToken - GetUserFromJWTToken -
-...
- logout ++ JWTCreateToken + GetUserFromJWTToken +
+...
+logout -