From a37c6a7fd23ae17a18c4f2cda3153746e05efe97 Mon Sep 17 00:00:00 2001 From: whgojp <3242246891@qq.com> Date: Fri, 21 Mar 2025 16:54:46 +0800 Subject: [PATCH 01/22] V1.4 --- .gitignore | 3 +- Dockerfile | 2 +- pom.xml | 66 +- sql/JavaSecLab.sql | 51 +- .../whgojp/common/utils/CheckUserInput.java | 27 +- .../controller/FastjsonController.java | 5 + .../controller/ReadObjectController.java | 36 +- .../controller/SnakeYamlController.java | 1 + .../funny/controller/HijackController.java | 26 + .../logic/pay/controller/PayController.java | 221 ++- .../controller/CredentialController.java | 54 +- .../controller/SpringBootController.java | 89 + .../springboot/entity/MaliciousObject.java | 21 + .../xss/config/XssWebSocketConfig.java | 18 + .../xss/config/XssWebSocketHandler.java | 53 + .../xss/controller/ActionEnterRewrite.java | 4 - .../modules/xss/controller/FileUtils.java | 53 +- .../xss/controller/JsonpController.java | 17 + .../xss/controller/OtherController.java | 6 +- .../xss/controller/PostMessageController.java | 20 + .../xss/controller/ReflectController.java | 116 +- .../xss/controller/StoreController.java | 10 +- .../controller/base/XssBaseController.java | 41 + .../xss/service/impl/XssServiceImpl.java | 37 +- src/main/resources/application-dev.yml | 60 +- src/main/resources/application-docker.yml | 55 +- src/main/resources/application.yml | 9 +- src/main/resources/banner.txt | 7 +- src/main/resources/static/api/init.json | 1 + .../resources/static/images/vul/jdbc/jdbc.png | Bin 0 -> 152497 bytes .../static/images/vul/memshell/filter.png | 1 + .../static/images/vul/memshell/listener.png | 1 + .../static/images/vul/memshell/servlet.png | 1 + src/main/resources/static/js/jsencrypt.min.js | 1540 +++++++++++++++++ .../static/js/lay-module/common/common.js | 2 +- src/main/resources/static/js/md5.min.js | 109 ++ src/main/resources/static/js/staticcode.js | 65 +- .../static/lib/custom-icon/demo_index.html | 71 +- .../static/lib/custom-icon/iconfont.css | 14 +- .../static/lib/custom-icon/iconfont.js | 2 +- .../static/lib/custom-icon/iconfont.json | 21 + .../static/lib/custom-icon/iconfont.woff2 | Bin 15816 -> 16368 bytes .../static/lib/layui-v2.6.3/css/layui.css | 23 + src/main/resources/static/other/cookie.txt | 1 + .../other/datapackage/file/delete.pcapng | Bin 0 -> 8360 bytes .../other/datapackage/file/download.pcapng | Bin 0 -> 6288 bytes .../datapackage/file/payload}/test.jsp | 0 .../static/other/datapackage/file/read.pcapng | Bin 0 -> 4420 bytes .../other/datapackage/file/upload.pcapng | Bin 0 -> 4136 bytes .../datapackage/rce/code_injection.pcapng | Bin 0 -> 7112 bytes .../datapackage/rce/command_injection.pcapng | Bin 0 -> 6960 bytes .../static/other/datapackage/spel/spel.pcapng | Bin 0 -> 3760 bytes .../datapackage/springboot/actuator.pcapng | Bin 0 -> 3988 bytes .../other/datapackage/springboot/druid.pcapng | Bin 0 -> 181832 bytes .../datapackage/springboot/mysql_jdbc.pcapng | Bin 0 -> 4148 bytes .../datapackage/springboot/swagger_ui.pcapng | Bin 0 -> 494464 bytes .../datapackage/sqli/sqli_boolean.pcapng | Bin 0 -> 5104 bytes .../other/datapackage/sqli/sqli_error.pcapng | Bin 0 -> 2792 bytes .../other/datapackage/sqli/sqli_time.pcapng | Bin 0 -> 2776 bytes .../other/datapackage/sqli/sqli_xpath.pcapng | Bin 0 -> 2748 bytes .../static/other/datapackage/ssrf/ssrf.pcapng | Bin 0 -> 3592 bytes .../other/datapackage/ssti/ssti_return.pcapng | Bin 0 -> 13988 bytes .../other/datapackage/ssti/ssti_url.pcapng | Bin 0 -> 13608 bytes .../xss/payload}/xss.html | 0 .../{demo => datapackage/xss/payload}/xss.pdf | Bin .../{demo => datapackage/xss/payload}/xss.svg | 0 .../{demo => datapackage/xss/payload}/xss.xml | 0 .../other/datapackage/xss/xss_store.pcapng | Bin 0 -> 348204 bytes .../other/datapackage/xss/xss_swagger.pcapng | Bin 0 -> 9992 bytes .../other/datapackage/xss/xss_th_html.pcapng | Bin 0 -> 204964 bytes .../other/datapackage/xss/xss_th_text.pcapng | Bin 0 -> 639500 bytes .../datapackage/xss/xss_upload_html.pcapng | Bin 0 -> 5780 bytes .../datapackage/xss/xss_upload_pdf.pcapng | Bin 0 -> 14520 bytes .../datapackage/xss/xss_upload_svg.pcapng | Bin 0 -> 6800 bytes .../datapackage/xss/xss_upload_xml.pcapng | Bin 0 -> 4240 bytes src/main/resources/templates/index.html | 2 +- src/main/resources/templates/login.html | 2 +- src/main/resources/templates/system/home.html | 2 +- .../templates/vul/deserialize/readObject.html | 7 +- .../templates/vul/deserialize/snakeYaml.html | 3 +- .../resources/templates/vul/file/delete.html | 12 +- .../templates/vul/file/download.html | 13 +- .../resources/templates/vul/file/read.html | 12 +- .../resources/templates/vul/file/upload.html | 17 +- .../resources/templates/vul/funny/hijack.html | 177 ++ .../templates/vul/funny/js/hijack.js | 77 + .../templates/vul/infoleak/dirTraversal.html | 4 +- .../vul/loginconfront/credential.html | 63 +- .../vul/loginconfront/resetpass.html | 5 +- .../templates/vul/loginconfront/reverse.html | 5 +- .../resources/templates/vul/other/xpath.html | 2 +- .../resources/templates/vul/rce/code.html | 12 +- .../resources/templates/vul/rce/command.html | 12 +- .../resources/templates/vul/spel/spel.html | 13 +- .../templates/vul/springboot/springboot.html | 142 +- .../templates/vul/sqli/jdbcSpecial.html | 2 +- .../resources/templates/vul/sqli/jdbcVul.html | 51 +- .../resources/templates/vul/sqli/mybatis.html | 2 +- .../resources/templates/vul/ssrf/ssrf.html | 24 +- .../resources/templates/vul/ssti/ssti.html | 42 +- src/main/resources/templates/vul/xss/dom.html | 143 +- .../resources/templates/vul/xss/other.html | 330 +++- .../vul/xss/postmessage/receiver.html | 54 + .../templates/vul/xss/postmessage/sender.html | 47 + .../{reflect-safe.html => reflect/safe.html} | 14 +- .../{reflect-vul.html => reflect/vul.html} | 10 +- .../resources/templates/vul/xss/store.html | 35 +- 107 files changed, 3939 insertions(+), 357 deletions(-) create mode 100644 src/main/java/top/whgojp/modules/funny/controller/HijackController.java create mode 100644 src/main/java/top/whgojp/modules/springboot/entity/MaliciousObject.java create mode 100644 src/main/java/top/whgojp/modules/xss/config/XssWebSocketConfig.java create mode 100644 src/main/java/top/whgojp/modules/xss/config/XssWebSocketHandler.java create mode 100644 src/main/java/top/whgojp/modules/xss/controller/JsonpController.java create mode 100644 src/main/java/top/whgojp/modules/xss/controller/PostMessageController.java create mode 100644 src/main/java/top/whgojp/modules/xss/controller/base/XssBaseController.java create mode 100644 src/main/resources/static/images/vul/jdbc/jdbc.png create mode 100644 src/main/resources/static/images/vul/memshell/filter.png create mode 100644 src/main/resources/static/images/vul/memshell/listener.png create mode 100644 src/main/resources/static/images/vul/memshell/servlet.png create mode 100644 src/main/resources/static/js/jsencrypt.min.js create mode 100644 src/main/resources/static/js/md5.min.js create mode 100644 src/main/resources/static/other/datapackage/file/delete.pcapng create mode 100644 src/main/resources/static/other/datapackage/file/download.pcapng rename src/main/resources/static/{upload => other/datapackage/file/payload}/test.jsp (100%) create mode 100644 src/main/resources/static/other/datapackage/file/read.pcapng create mode 100644 src/main/resources/static/other/datapackage/file/upload.pcapng create mode 100644 src/main/resources/static/other/datapackage/rce/code_injection.pcapng create mode 100644 src/main/resources/static/other/datapackage/rce/command_injection.pcapng create mode 100644 src/main/resources/static/other/datapackage/spel/spel.pcapng create mode 100644 src/main/resources/static/other/datapackage/springboot/actuator.pcapng create mode 100644 src/main/resources/static/other/datapackage/springboot/druid.pcapng create mode 100644 src/main/resources/static/other/datapackage/springboot/mysql_jdbc.pcapng create mode 100644 src/main/resources/static/other/datapackage/springboot/swagger_ui.pcapng create mode 100644 src/main/resources/static/other/datapackage/sqli/sqli_boolean.pcapng create mode 100644 src/main/resources/static/other/datapackage/sqli/sqli_error.pcapng create mode 100644 src/main/resources/static/other/datapackage/sqli/sqli_time.pcapng create mode 100644 src/main/resources/static/other/datapackage/sqli/sqli_xpath.pcapng create mode 100644 src/main/resources/static/other/datapackage/ssrf/ssrf.pcapng create mode 100644 src/main/resources/static/other/datapackage/ssti/ssti_return.pcapng create mode 100644 src/main/resources/static/other/datapackage/ssti/ssti_url.pcapng rename src/main/resources/static/other/{demo => datapackage/xss/payload}/xss.html (100%) rename src/main/resources/static/other/{demo => datapackage/xss/payload}/xss.pdf (100%) rename src/main/resources/static/other/{demo => datapackage/xss/payload}/xss.svg (100%) rename src/main/resources/static/other/{demo => datapackage/xss/payload}/xss.xml (100%) create mode 100644 src/main/resources/static/other/datapackage/xss/xss_store.pcapng create mode 100644 src/main/resources/static/other/datapackage/xss/xss_swagger.pcapng create mode 100644 src/main/resources/static/other/datapackage/xss/xss_th_html.pcapng create mode 100644 src/main/resources/static/other/datapackage/xss/xss_th_text.pcapng create mode 100644 src/main/resources/static/other/datapackage/xss/xss_upload_html.pcapng create mode 100644 src/main/resources/static/other/datapackage/xss/xss_upload_pdf.pcapng create mode 100644 src/main/resources/static/other/datapackage/xss/xss_upload_svg.pcapng create mode 100644 src/main/resources/static/other/datapackage/xss/xss_upload_xml.pcapng create mode 100644 src/main/resources/templates/vul/funny/hijack.html create mode 100644 src/main/resources/templates/vul/funny/js/hijack.js create mode 100644 src/main/resources/templates/vul/xss/postmessage/receiver.html create mode 100644 src/main/resources/templates/vul/xss/postmessage/sender.html rename src/main/resources/templates/vul/xss/{reflect-safe.html => reflect/safe.html} (98%) rename src/main/resources/templates/vul/xss/{reflect-vul.html => reflect/vul.html} (98%) diff --git a/.gitignore b/.gitignore index 3b720ab..ee547e7 100644 --- a/.gitignore +++ b/.gitignore @@ -36,4 +36,5 @@ build/ /logs/ /.idea/ -/src/test/ \ No newline at end of file +/src/test/ +src/main/resources/application-aliyun.yml \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 876ae8e..f345b4c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ FROM openjdk:8 WORKDIR /work LABEL maintainer="whgojp@foxmail.com" -LABEL version="1.3" +LABEL version="1.4" LABEL description="I think therefore I am." COPY target/JavaSecLab.jar /work/JavaSecLab.jar diff --git a/pom.xml b/pom.xml index c7abdbb..8795ba1 100644 --- a/pom.xml +++ b/pom.xml @@ -8,14 +8,14 @@ JavaSecLab 1.3.0 Java综合漏洞平台 - hello JavaSec! + hello JavaSecLab! org.springframework.boot spring-boot-starter-parent - - 2.4.1 - + + 2.4.1 + @@ -26,9 +26,10 @@ 5.8.21 1.18.4 3.5.1 - 8.0.33 + + 8.0.14 2.2.0.0 - 0.10.7 + 0.11.5 @@ -106,12 +107,18 @@ + + + + + - com.mysql - mysql-connector-j - ${mysql.version} + mysql + mysql-connector-java + 8.0.14 + com.baomidou @@ -271,7 +278,23 @@ 1.70 + + ognl + ognl + 3.3.1 + + + commons-collections + commons-collections + 3.2.1 + + + + org.springframework.boot + spring-boot-starter-websocket + 2.4.1 + @@ -296,29 +319,16 @@ + - central - https://repo.maven.apache.org/maven2 - - - spring-milestone - https://repo.spring.io/milestone - - - spring-release - https://repo.spring.io/release + aliyun-central + https://maven.aliyun.com/repository/central - acfunnexus - https://maven.aliyun.com/repository/public/ - default - - true - - - true - + aliyun-public + https://maven.aliyun.com/repository/public + diff --git a/sql/JavaSecLab.sql b/sql/JavaSecLab.sql index d1051d7..70584d6 100644 --- a/sql/JavaSecLab.sql +++ b/sql/JavaSecLab.sql @@ -1,5 +1,5 @@ /* - Navicat Premium Data Transfer + Navicat Premium Dump SQL Source Server : mysql_docker_mac Source Server Type : MySQL @@ -11,10 +11,8 @@ Target Server Version : 80200 (8.2.0) File Encoding : 65001 - Date: 10/11/2024 13:17:18 + Date: 21/03/2025 16:51:30 */ -CREATE DATABASE IF NOT EXISTS JavaSecLab; -USE JavaSecLab; SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; @@ -25,8 +23,8 @@ SET FOREIGN_KEY_CHECKS = 0; DROP TABLE IF EXISTS `hsqli`; CREATE TABLE `hsqli` ( `id` bigint NOT NULL AUTO_INCREMENT, - `password` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL, - `username` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL, + `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; @@ -41,11 +39,11 @@ COMMIT; -- ---------------------------- DROP TABLE IF EXISTS `log`; CREATE TABLE `log` ( - `logId` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'log_id', - `username` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户名', - `optionName` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户操作', - `optionTerminal` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '操作终端', - `optionIp` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Ip地址', + `logId` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'log_id', + `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户名', + `optionName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户操作', + `optionTerminal` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '操作终端', + `optionIp` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'Ip地址', `optionTime` date DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (`logId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; @@ -56,14 +54,31 @@ CREATE TABLE `log` ( BEGIN; COMMIT; +-- ---------------------------- +-- Table structure for objects +-- ---------------------------- +DROP TABLE IF EXISTS `objects`; +CREATE TABLE `objects` ( + `id` int NOT NULL, + `malicious_object` blob, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; + +-- ---------------------------- +-- Records of objects +-- ---------------------------- +BEGIN; +INSERT INTO `objects` (`id`, `malicious_object`) VALUES (1, 0xACED000573720034746F702E7768676F6A702E6D6F64756C65732E737072696E67626F6F742E656E746974792E4D616C6963696F75734F626A656374C007A841C29C41060200014C0007636F6D6D616E647400124C6A6176612F6C616E672F537472696E673B78707400126F70656E202D612043616C63756C61746F72); +COMMIT; + -- ---------------------------- -- Table structure for sqli -- ---------------------------- DROP TABLE IF EXISTS `sqli`; CREATE TABLE `sqli` ( `id` int NOT NULL AUTO_INCREMENT, - `username` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名', - `password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码', + `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名', + `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码', PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; @@ -79,8 +94,8 @@ COMMIT; -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( - `username` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名', - `password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码', + `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名', + `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码', PRIMARY KEY (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; @@ -99,11 +114,11 @@ COMMIT; DROP TABLE IF EXISTS `xss`; CREATE TABLE `xss` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键id', - `content` text COLLATE utf8mb4_general_ci NOT NULL COMMENT '插入内容', + `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '插入内容', `ua` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'User-Agent', - `date` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '插入时间', + `date` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '插入时间', PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=82 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +) ENGINE=InnoDB AUTO_INCREMENT=84 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; -- ---------------------------- -- Records of xss diff --git a/src/main/java/top/whgojp/common/utils/CheckUserInput.java b/src/main/java/top/whgojp/common/utils/CheckUserInput.java index 13f8ad9..8f191d8 100644 --- a/src/main/java/top/whgojp/common/utils/CheckUserInput.java +++ b/src/main/java/top/whgojp/common/utils/CheckUserInput.java @@ -1,12 +1,13 @@ package top.whgojp.common.utils; import org.springframework.stereotype.Component; - +import org.springframework.web.util.HtmlUtils; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.regex.Pattern; /** * @description 用户输入数据校验 @@ -16,6 +17,30 @@ */ @Component public class CheckUserInput { + private static final Pattern SCRIPT_PATTERN = Pattern.compile("]*>.*?", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); + private static final Pattern EVENT_PATTERN = Pattern.compile("on\\w+\\s*=", Pattern.CASE_INSENSITIVE); + private static final Pattern JAVASCRIPT_PATTERN = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE); + + public String filter(String input) { + if (input == null) { + return ""; + } + + // 基本HTML转义 + String filtered = HtmlUtils.htmlEscape(input); + + // 移除script标签 + filtered = SCRIPT_PATTERN.matcher(filtered).replaceAll(""); + + // 移除事件处理器 + filtered = EVENT_PATTERN.matcher(filtered).replaceAll(""); + + // 移除javascript:协议 + filtered = JAVASCRIPT_PATTERN.matcher(filtered).replaceAll(""); + + return filtered; + } + public String checkUser(String username, String password, Integer id) { String message = ""; if (username == null || username.isEmpty()) { diff --git a/src/main/java/top/whgojp/modules/components/fastjson/controller/FastjsonController.java b/src/main/java/top/whgojp/modules/components/fastjson/controller/FastjsonController.java index 0e7e200..03de345 100644 --- a/src/main/java/top/whgojp/modules/components/fastjson/controller/FastjsonController.java +++ b/src/main/java/top/whgojp/modules/components/fastjson/controller/FastjsonController.java @@ -38,6 +38,11 @@ public String vul(@RequestBody String content) { } } + public String vul2(){ + + return ""; + } + @PostMapping("/safe") @ResponseBody public String safe(@RequestBody String content) { diff --git a/src/main/java/top/whgojp/modules/deserialize/readobject/controller/ReadObjectController.java b/src/main/java/top/whgojp/modules/deserialize/readobject/controller/ReadObjectController.java index f49db0f..e014f8e 100644 --- a/src/main/java/top/whgojp/modules/deserialize/readobject/controller/ReadObjectController.java +++ b/src/main/java/top/whgojp/modules/deserialize/readobject/controller/ReadObjectController.java @@ -8,6 +8,9 @@ import org.springframework.web.bind.annotation.*; import top.whgojp.common.utils.R; import top.whgojp.modules.sqli.entity.Sqli; +import java.io.ByteArrayInputStream; +import java.io.ObjectInputStream; + import java.io.ByteArrayInputStream; import java.util.Base64; @@ -30,23 +33,46 @@ public String readObject(){ return "vul/deserialize/readObject"; } +// @RequestMapping("/vul") +// @ResponseBody +// public R vul(String payload) { +// System.setProperty("org.apache.commons.collections.enableUnsafeSerialization", "true"); +// log.info("Java反序列化:"+payload); +// try { +// payload = payload.replace(" ", "+"); +// byte[] bytes = Base64.getDecoder().decode(payload); +// ByteArrayInputStream stream = new ByteArrayInputStream(bytes); +// java.io.ObjectInputStream in = new java.io.ObjectInputStream(stream); +// in.readObject(); +// in.close(); +// return R.ok("[+]Java反序列化:ObjectInputStream.readObject()"); +// } catch (Exception e) { +// return R.error("[-]请输入正确的Payload!\n"+e.getMessage()); +// } +// } @RequestMapping("/vul") @ResponseBody public R vul(String payload) { System.setProperty("org.apache.commons.collections.enableUnsafeSerialization", "true"); - log.info("Java反序列化:"+payload); + log.info("Java反序列化:" + payload); try { payload = payload.replace(" ", "+"); byte[] bytes = Base64.getDecoder().decode(payload); ByteArrayInputStream stream = new ByteArrayInputStream(bytes); - java.io.ObjectInputStream in = new java.io.ObjectInputStream(stream); - in.readObject(); + ObjectInputStream in = new ObjectInputStream(stream); + + Object obj = in.readObject(); + log.info("反序列化对象:" + obj.toString()); + in.close(); - return R.ok("[+]Java反序列化:ObjectInputStream.readObject()"); + return R.ok("[+]Java反序列化:"+obj); } catch (Exception e) { - return R.error("[-]请输入正确的Payload!\n"+e.getMessage()); + return R.error("[-] 请输入正确的 Payload!\n" + e.getMessage()); } } + + + @RequestMapping("/safe1") @ResponseBody public R safe1(String payload) { diff --git a/src/main/java/top/whgojp/modules/deserialize/snakeyaml/controller/controller/SnakeYamlController.java b/src/main/java/top/whgojp/modules/deserialize/snakeyaml/controller/controller/SnakeYamlController.java index 20d5592..25c3792 100644 --- a/src/main/java/top/whgojp/modules/deserialize/snakeyaml/controller/controller/SnakeYamlController.java +++ b/src/main/java/top/whgojp/modules/deserialize/snakeyaml/controller/controller/SnakeYamlController.java @@ -32,6 +32,7 @@ public String snakeYaml(){ @RequestMapping("/vul") @ResponseBody public R vul(String payload) { + log.info("payload:"+payload); Yaml y = new Yaml(); y.load(payload); return R.ok("[+]Java反序列化:SnakeYaml原生漏洞"); diff --git a/src/main/java/top/whgojp/modules/funny/controller/HijackController.java b/src/main/java/top/whgojp/modules/funny/controller/HijackController.java new file mode 100644 index 0000000..ab1df77 --- /dev/null +++ b/src/main/java/top/whgojp/modules/funny/controller/HijackController.java @@ -0,0 +1,26 @@ +package top.whgojp.modules.funny.controller; + +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * @description <功能描述> + * @author: whgojp + * @email: whgojp@foxmail.com + * @Date: 2025/1/17 16:31 + */ +@Slf4j +@Api(value = "HijackController", tags = "劫持模块") +@Controller +@CrossOrigin(origins = "*") +@RequestMapping("/funny/hijack") +public class HijackController { + @RequestMapping() + public String hijack(){ + return "/vul/funny/hijack"; + } + +} diff --git a/src/main/java/top/whgojp/modules/logic/pay/controller/PayController.java b/src/main/java/top/whgojp/modules/logic/pay/controller/PayController.java index 0abbb85..328461f 100644 --- a/src/main/java/top/whgojp/modules/logic/pay/controller/PayController.java +++ b/src/main/java/top/whgojp/modules/logic/pay/controller/PayController.java @@ -1,10 +1,229 @@ package top.whgojp.modules.logic.pay.controller; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import top.whgojp.common.utils.R; + +import java.math.BigDecimal; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; +import java.util.HashMap; + /** - * @description <功能描述> + * @description 逻辑漏洞-支付漏洞 * @author: whgojp * @email: whgojp@foxmail.com * @Date: 2024/8/28 22:07 */ +@Slf4j +@Api(value = "PayController", tags = "逻辑漏洞-支付漏洞") +@Controller +@CrossOrigin(origins = "*") +@RequestMapping("/logic/pay") public class PayController { + // 用户余额 + private final AtomicReference userMoney = new AtomicReference<>(new BigDecimal("1000.00")); + // 商品单价(用于服务端验证) + private final BigDecimal goodPrice = new BigDecimal("100.00"); + // 订单状态缓存 + private final Map orderStatusMap = new ConcurrentHashMap<>(); + // 支付状态缓存(用于防止重复支付) + private final Map paymentStatusMap = new ConcurrentHashMap<>(); + + @RequestMapping("") + public String pay() { + return "/vul/logic/pay/pay"; + } + + /** + * 订单状态类 + */ + private static class OrderStatus { + BigDecimal amount; + boolean isPaid; + String orderId; + + public OrderStatus(String orderId, BigDecimal amount) { + this.orderId = orderId; + this.amount = amount; + this.isPaid = false; + } + } + + /** + * 漏洞场景1:支付金额参数篡改 + * 由于未对客户端传入的价格参数进行验证,攻击者可以修改支付金额 + */ + @ApiOperation("支付金额参数篡改漏洞") + @RequestMapping("/vul1") + @ResponseBody + public R vul1(@RequestParam String count, @RequestParam String price) { + try { + double totalPrice = Integer.parseInt(count) * Double.parseDouble(price); + log.info("用户需支付金额:" + totalPrice); + + // 直接使用客户端传入的价格,未与服务端商品实际价格进行校验 + BigDecimal currentMoney = userMoney.get(); + if (currentMoney.compareTo(BigDecimal.valueOf(totalPrice)) < 0) { + return R.error("支付金额不足,支付失败!"); + } + userMoney.set(currentMoney.subtract(BigDecimal.valueOf(totalPrice))); + return R.ok("支付成功!剩余余额:" + userMoney.get()); + } catch (Exception e) { + return R.error(e.toString()); + } + } + + /** + * 漏洞场景2:订单重放攻击 + * 由于未对订单是否重复支付进行验证,攻击者可以重复发送相同的支付请求 + */ + @ApiOperation("订单重放攻击漏洞") + @RequestMapping("/vul2") + @ResponseBody + public R vul2(@RequestParam String orderId, @RequestParam double amount) { + // 未检查订单是否已支付 + // 这里应该使用paymentStatusMap检查订单是否已支付,但为了演示漏洞,故意不检查 + BigDecimal currentMoney = userMoney.get(); + if (currentMoney.compareTo(BigDecimal.valueOf(amount)) < 0) { + return R.error("余额不足"); + } + userMoney.set(currentMoney.subtract(BigDecimal.valueOf(amount))); + return R.ok("支付成功!剩余余额:" + userMoney.get()); + } + + /** + * 漏洞场景3:竞态条件漏洞 + * 由于未正确处理并发支付请求,可能导致重复扣款或余额计算错误 + */ + @ApiOperation("竞态条件漏洞") + @RequestMapping("/vul3") + @ResponseBody + public R vul3(@RequestParam String orderId, @RequestParam double amount) { + // 模拟处理延迟 + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + + BigDecimal currentMoney = userMoney.get(); + if (currentMoney.compareTo(BigDecimal.valueOf(amount)) < 0) { + return R.error("余额不足"); + } + userMoney.set(currentMoney.subtract(BigDecimal.valueOf(amount))); + return R.ok("支付成功!剩余余额:" + userMoney.get()); + } + + /** + * 漏洞场景4:支付流程绕过 + * 由于状态校验不完整,攻击者可能绕过支付流程直接修改订单状态 + */ + @ApiOperation("支付流程绕过漏洞 - 创建订单") + @RequestMapping("/vul4/create") + @ResponseBody + public R createOrder(@RequestParam String orderId, @RequestParam double amount) { + OrderStatus status = new OrderStatus(orderId, BigDecimal.valueOf(amount)); + orderStatusMap.put(orderId, status); + Map data = new HashMap<>(); + data.put("orderId", orderId); + data.put("amount", amount); + return R.ok("订单创建成功").put("data", data); + } + + @ApiOperation("支付流程绕过漏洞 - 查询订单状态") + @RequestMapping("/vul4/status") + @ResponseBody + public R getOrderStatus(@RequestParam String orderId) { + OrderStatus status = orderStatusMap.get(orderId); + if (status == null) { + return R.error("订单不存在"); + } + Map data = new HashMap<>(); + data.put("orderId", status.orderId); + data.put("amount", status.amount); + data.put("isPaid", status.isPaid); + return R.ok().put("data", data); + } + + @ApiOperation("支付流程绕过漏洞 - 支付通知") + @RequestMapping("/vul4/notify") + @ResponseBody + public R paymentNotify(@RequestParam String orderId, @RequestParam boolean success) { + // 未验证通知来源,直接更新订单状态 + OrderStatus status = orderStatusMap.get(orderId); + if (status == null) { + return R.error("订单不存在"); + } + status.isPaid = success; + return R.ok("状态更新成功"); + } + + + /** + * 漏洞场景5:整数溢出漏洞 + * 当count或price数值过大时,可能会导致整数溢出 + */ + @ApiOperation("整数溢出漏洞") + @RequestMapping("/vul5") + @ResponseBody + public R integerOverflow(@RequestParam String count, @RequestParam String price) { + try { + Integer countValue = Integer.valueOf(count); + Integer priceValue = Integer.valueOf(price); + + // 整数溢出场景:当 count 或 price 数值过大时,可能会导致溢出 + int totalAmount = countValue * priceValue; + log.info("用户需支付金额:" + totalAmount); + + BigDecimal currentMoney = userMoney.get(); + if (currentMoney.compareTo(BigDecimal.valueOf(totalAmount)) < 0) { + return R.error("支付金额不足,支付失败!"); + } + userMoney.set(currentMoney.subtract(BigDecimal.valueOf(totalAmount))); + return R.ok("支付成功!剩余余额:" + userMoney.get()); + } catch (Exception e) { + return R.error("无效的输入,请输入有效的数量和价格!"); + } + } + + /** + * 漏洞场景6:浮点数精度漏洞 + * 由于未正确处理浮点数精度,可能导致金额计算不准确 + */ + @ApiOperation("浮点数精度漏洞") + @RequestMapping("/vul6") + @ResponseBody + public R floatingPointPrecision(@RequestParam String count, @RequestParam String price) { + try { + // 使用BigDecimal处理金额计算,避免浮点数精度问题 + BigDecimal amountValue = new BigDecimal(price).multiply(new BigDecimal(count)); + log.info("用户需支付金额:" + amountValue); + + BigDecimal currentMoney = userMoney.get(); + if (currentMoney.compareTo(amountValue) < 0) { + return R.error("支付金额不足,支付失败!"); + } + userMoney.set(currentMoney.subtract(amountValue)); + return R.ok("支付成功!剩余余额:" + userMoney.get()); + } catch (Exception e) { + return R.error("无效的输入,请输入有效的数量和价格!"); + } + } + + @ApiOperation("重置用户余额") + @RequestMapping("/resetBalance") + @ResponseBody + public R resetBalance() { + userMoney.set(new BigDecimal("1000.00")); + return R.ok("余额已重置为1000.00元"); + } } diff --git a/src/main/java/top/whgojp/modules/loginconfront/controller/CredentialController.java b/src/main/java/top/whgojp/modules/loginconfront/controller/CredentialController.java index a8c5d91..b9774aa 100644 --- a/src/main/java/top/whgojp/modules/loginconfront/controller/CredentialController.java +++ b/src/main/java/top/whgojp/modules/loginconfront/controller/CredentialController.java @@ -1,12 +1,19 @@ package top.whgojp.modules.loginconfront.controller; +import io.jsonwebtoken.*; +import io.jsonwebtoken.security.Keys; import io.swagger.annotations.Api; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.*; import top.whgojp.common.utils.R; +import javax.crypto.spec.SecretKeySpec; +import javax.servlet.http.HttpSession; +import java.nio.charset.StandardCharsets; +import java.security.Key; + /** * @description 登录对抗-凭证安全 * @author: whgojp @@ -24,9 +31,48 @@ public String credential() { return "vul/loginconfront/credential"; } + // 生成一个符合HS256要求的强密钥(至少256位) + @Value("${jwt.key}") + String secretKey = "f3a4c6d5b9bfeff28b1f529b0840134bcd4183474e2d4a97c05615a134e4f4da"; + Key key = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), SignatureAlgorithm.HS256.getJcaName()); + +// Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256); + + @GetMapping("/generate-jwt") + @ResponseBody + public R generateJWT(String username, String role) { + String jwt = Jwts.builder() + .setSubject(username) + .claim("role", role) + .signWith(key) + .compact(); + log.info("生成的JWT: " + jwt); + return R.ok(jwt); + } + @RequestMapping("/vul1") - public R vul1() { - return R.ok(); + @ResponseBody + public R vul1(@RequestHeader("Auth_Token") String jwt) { // 从请求头获取 JWT + log.info("获取到的JWT:" + jwt); + try { + String user = Jwts.parser() + .setSigningKey(key) + .parseClaimsJws(jwt) + .getBody() + .getSubject(); + String role = Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(jwt) + .getBody() + .get("role", String.class); + + log.info("JWT解析成功,用户:" + user); + return R.ok("JWT解析成功,user:" + user+",role:"+role); + } catch (Exception e) { + log.info("JWT解析失败:" + e.getMessage()); + return R.error("JWT解析失败:" + e.getMessage()); + } } @RequestMapping("/vul2") diff --git a/src/main/java/top/whgojp/modules/springboot/controller/SpringBootController.java b/src/main/java/top/whgojp/modules/springboot/controller/SpringBootController.java index 20ffe20..aa0ed81 100644 --- a/src/main/java/top/whgojp/modules/springboot/controller/SpringBootController.java +++ b/src/main/java/top/whgojp/modules/springboot/controller/SpringBootController.java @@ -2,9 +2,20 @@ import io.swagger.annotations.Api; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import top.whgojp.common.utils.R; +import top.whgojp.modules.springboot.entity.MaliciousObject; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.sql.*; /** * @description java专题-SpringBoot相关漏洞 @@ -23,4 +34,82 @@ public String springboot() { return "vul/springboot/springboot"; } + @Value("${spring.datasource.url:jdbc:mysql://localhost:13306/JavaSecLab}") + String url = ""; + @Value("${spring.datasource.username:jdbc:root}") + String username = ""; + @Value("${spring.datasource.password:jdbc:QWE123qwe}") + String password = ""; + + @RequestMapping("/jdbc") + @ResponseBody + public R jdbc() { + try { + Connection conn = DriverManager.getConnection(url, username, password); + String selectQuery = "SELECT malicious_object FROM objects WHERE id = 1"; + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(selectQuery); + + if (rs.next()) { + byte[] maliciousObjectBytes = rs.getBytes("malicious_object"); + // 反序列化恶意对象 + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(maliciousObjectBytes); + ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream); + + MaliciousObject maliciousObject = (MaliciousObject) objectInputStream.readObject(); + + log.info("触发MYSQL-JBDC反序列化漏洞!"); + } + + stmt.close(); + conn.close(); + + } catch (Exception e) { + e.printStackTrace(); + } + return R.ok("触发MYSQL-JBDC反序列化漏洞!"); + } + + @RequestMapping("/insert") + @ResponseBody + public R insertMaliciousObject(@RequestParam String command) { + try { + MaliciousObject maliciousObject = new MaliciousObject(command); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(maliciousObject); + byte[] objectBytes = baos.toByteArray(); + + Connection conn = DriverManager.getConnection(url, username, password); + String insertQuery = "INSERT INTO objects (id, malicious_object) VALUES (?, ?)"; + PreparedStatement stmt = conn.prepareStatement(insertQuery); + stmt.setInt(1, 1); + stmt.setBytes(2, objectBytes); + stmt.executeUpdate(); + stmt.close(); + conn.close(); + + return R.ok("恶意对象插入成功!"); + } catch (Exception e) { + e.printStackTrace(); + return R.error("恶意对象插入失败(主键冲突的话在请数据库中删除该记录):" + e.getMessage()); + } + } + + @RequestMapping("/vul") + @ResponseBody + public R vul(String url, String username, String password) { + + try { +// Class.forName("com.mysql.jdbc.Driver"); + Class.forName("com.mysql.cj.jdbc.Driver"); + DriverManager.getConnection(url,username,password); + } catch (Exception e) { + e.printStackTrace(); + } + return R.ok(); + } + + } diff --git a/src/main/java/top/whgojp/modules/springboot/entity/MaliciousObject.java b/src/main/java/top/whgojp/modules/springboot/entity/MaliciousObject.java new file mode 100644 index 0000000..34ed3cd --- /dev/null +++ b/src/main/java/top/whgojp/modules/springboot/entity/MaliciousObject.java @@ -0,0 +1,21 @@ +package top.whgojp.modules.springboot.entity; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; + +public class MaliciousObject implements Serializable { + private String command; + + public MaliciousObject(String command) { + this.command = command; + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + String command = (String) in.readObject(); + if (command != null) { + Runtime.getRuntime().exec(command); + } + } + +} diff --git a/src/main/java/top/whgojp/modules/xss/config/XssWebSocketConfig.java b/src/main/java/top/whgojp/modules/xss/config/XssWebSocketConfig.java new file mode 100644 index 0000000..e1e67f6 --- /dev/null +++ b/src/main/java/top/whgojp/modules/xss/config/XssWebSocketConfig.java @@ -0,0 +1,18 @@ +package top.whgojp.modules.xss.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.lang.NonNull; +import org.springframework.web.socket.config.annotation.EnableWebSocket; +import org.springframework.web.socket.config.annotation.WebSocketConfigurer; +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; + +@Configuration +@EnableWebSocket +public class XssWebSocketConfig implements WebSocketConfigurer { + + @Override + public void registerWebSocketHandlers(@NonNull WebSocketHandlerRegistry registry) { + registry.addHandler(new XssWebSocketHandler(), "/xss/websocket") + .setAllowedOrigins("*"); // 故意允许所有源,用于演示XSS风险 + } +} diff --git a/src/main/java/top/whgojp/modules/xss/config/XssWebSocketHandler.java b/src/main/java/top/whgojp/modules/xss/config/XssWebSocketHandler.java new file mode 100644 index 0000000..18488ef --- /dev/null +++ b/src/main/java/top/whgojp/modules/xss/config/XssWebSocketHandler.java @@ -0,0 +1,53 @@ +package top.whgojp.modules.xss.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.lang.NonNull; +import org.springframework.web.socket.CloseStatus; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; +import org.springframework.web.socket.handler.TextWebSocketHandler; + +import java.io.IOException; +import java.util.concurrent.CopyOnWriteArraySet; + +@Slf4j +public class XssWebSocketHandler extends TextWebSocketHandler { + + private static final CopyOnWriteArraySet sessions = new CopyOnWriteArraySet<>(); + + @Override + public void afterConnectionEstablished(@NonNull WebSocketSession session) { + sessions.add(session); + log.info("WebSocket connection established - Current connections: {}", sessions.size()); + try { + session.sendMessage(new TextMessage("Connected successfully")); + } catch (IOException e) { + log.error("Failed to send welcome message: {}", e.getMessage()); + } + } + + @Override + protected void handleTextMessage(@NonNull WebSocketSession session, @NonNull TextMessage message) { + log.info("Received message: {}", message.getPayload()); + // 故意不过滤消息内容,用于演示XSS风险 + broadcast(message); + } + + @Override + public void afterConnectionClosed(@NonNull WebSocketSession session, @NonNull CloseStatus status) { + sessions.remove(session); + log.info("WebSocket connection closed - Current connections: {}", sessions.size()); + } + + private void broadcast(TextMessage message) { + for (WebSocketSession session : sessions) { + try { + if (session.isOpen()) { + session.sendMessage(message); + } + } catch (IOException e) { + log.error("Failed to send message to session {}: {}", session.getId(), e.getMessage()); + } + } + } +} diff --git a/src/main/java/top/whgojp/modules/xss/controller/ActionEnterRewrite.java b/src/main/java/top/whgojp/modules/xss/controller/ActionEnterRewrite.java index cae747e..6c197b6 100644 --- a/src/main/java/top/whgojp/modules/xss/controller/ActionEnterRewrite.java +++ b/src/main/java/top/whgojp/modules/xss/controller/ActionEnterRewrite.java @@ -14,10 +14,6 @@ import javax.servlet.http.HttpServletRequest; import java.util.Map; -/** - * 描述: - * 创建人: 慌途L - */ @Slf4j public class ActionEnterRewrite { private HttpServletRequest request; diff --git a/src/main/java/top/whgojp/modules/xss/controller/FileUtils.java b/src/main/java/top/whgojp/modules/xss/controller/FileUtils.java index d5ab2ec..9a63996 100644 --- a/src/main/java/top/whgojp/modules/xss/controller/FileUtils.java +++ b/src/main/java/top/whgojp/modules/xss/controller/FileUtils.java @@ -11,48 +11,47 @@ import java.io.File; import java.io.IOException; -import java.util.Random; +import java.util.UUID; + -/** - * 功能 : 上传文件工具类 - * 创建人 : 慌途L - */ @Slf4j public class FileUtils { public static String upLoadFile(MultipartFile file, String path) { - - if(file.isEmpty()){ + if (file == null || file.isEmpty()) { log.info("文件为空!"); return null; } + String fileName = file.getOriginalFilename(); - int size = (int) file.getSize(); - log.info(fileName + "-->" + size); - - // 取得文件的后缀名。 - String ext = fileName.substring(fileName.lastIndexOf(".") + 1).toUpperCase(); - - String newFileName = - System.currentTimeMillis() / 1000 + new Random().nextInt(100000)+"." + ext; + log.info("上传文件: {} - 大小: {}", fileName, file.getSize()); - //String path = "F:/test" ; - File dest = new File(path + "/" + newFileName); - if(!dest.getParentFile().exists()){ //判断文件父目录是否存在 - dest.getParentFile().mkdir(); + String ext = getFileExtension(fileName); + String newFileName = generateUniqueFileName(ext); + + return saveFile(file, path, newFileName); + } + + private static String getFileExtension(String fileName) { + return fileName.substring(fileName.lastIndexOf(".") + 1).toUpperCase(); + } + + private static String generateUniqueFileName(String ext) { + return UUID.randomUUID().toString() + "." + ext; + } + + private static String saveFile(MultipartFile file, String path, String newFileName) { + File dest = new File(path, newFileName); + if (!dest.getParentFile().exists()) { + dest.getParentFile().mkdirs(); } + try { - file.transferTo(dest); //保存文件 + file.transferTo(dest); return newFileName; - } catch (IllegalStateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return null; } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + log.error("文件保存失败", e); return null; } } } - diff --git a/src/main/java/top/whgojp/modules/xss/controller/JsonpController.java b/src/main/java/top/whgojp/modules/xss/controller/JsonpController.java new file mode 100644 index 0000000..3c4a30f --- /dev/null +++ b/src/main/java/top/whgojp/modules/xss/controller/JsonpController.java @@ -0,0 +1,17 @@ +package top.whgojp.modules.xss.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/xss") +public class JsonpController { + + @GetMapping("/jsonp") + public String handleJsonp(@RequestParam String callback) { + // 故意不验证callback参数,直接拼接返回 + return callback + "(" + "{\"message\": \"Hello from JSONP\"}" + ");"; + } +} diff --git a/src/main/java/top/whgojp/modules/xss/controller/OtherController.java b/src/main/java/top/whgojp/modules/xss/controller/OtherController.java index ffc2778..727ce23 100644 --- a/src/main/java/top/whgojp/modules/xss/controller/OtherController.java +++ b/src/main/java/top/whgojp/modules/xss/controller/OtherController.java @@ -124,12 +124,12 @@ public R vul1Upload(@RequestParam("file") MultipartFile file, } @ApiOperation(value = "漏洞场景:模版引擎解析导致存储XSS", notes = "") @GetMapping("/vul2OtherTemplate") - public String vul2OtherTemplate(@RequestParam("content") String content, + public String vul2OtherTemplate(@RequestParam("payload") String payload, @RequestParam("type") String type, Model model) { if ("html".equals(type)) { - model.addAttribute("html", content); + model.addAttribute("html", payload); } else if ("text".equals(type)) { - model.addAttribute("text", content); + model.addAttribute("text", payload); } return "vul/xss/other"; } diff --git a/src/main/java/top/whgojp/modules/xss/controller/PostMessageController.java b/src/main/java/top/whgojp/modules/xss/controller/PostMessageController.java new file mode 100644 index 0000000..e5d8e82 --- /dev/null +++ b/src/main/java/top/whgojp/modules/xss/controller/PostMessageController.java @@ -0,0 +1,20 @@ +package top.whgojp.modules.xss.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@RequestMapping("/xss/postmessage") +public class PostMessageController { + + @GetMapping("/sender") + public String sender() { + return "vul/xss/postmessage/sender"; + } + + @GetMapping("/receiver") + public String receiver() { + return "vul/xss/postmessage/receiver"; + } +} diff --git a/src/main/java/top/whgojp/modules/xss/controller/ReflectController.java b/src/main/java/top/whgojp/modules/xss/controller/ReflectController.java index 2e0b7de..7df5caf 100644 --- a/src/main/java/top/whgojp/modules/xss/controller/ReflectController.java +++ b/src/main/java/top/whgojp/modules/xss/controller/ReflectController.java @@ -12,11 +12,11 @@ import org.thymeleaf.util.StringUtils; import top.whgojp.common.utils.CheckUserInput; import top.whgojp.common.utils.R; +import top.whgojp.modules.xss.controller.base.XssBaseController; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpUtils; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -27,43 +27,35 @@ * @Date: 2024/5/20 16:55 */ @Slf4j -@Api(value = "ReflectController", tags = "跨站脚本-反射型XSS") +@Api(value = "ReflectController", tags = "跨站脚本 - 反射型XSS") @Controller @CrossOrigin(origins = "*") @RequestMapping("/xss/reflect") -public class ReflectController { +public class ReflectController extends XssBaseController { + @Autowired private CheckUserInput checkUserInput; - @RequestMapping("") - public String xssReflect() { - return "vul/xss/reflect"; - } - @RequestMapping("/vul") - public String xssReflectVul() { - return "vul/xss/reflect-vul"; - } - @RequestMapping("/safe") - public String xssReflectSafe() { - return "vul/xss/reflect-safe"; - } + @RequestMapping("/{view}") + public String reflect(@PathVariable String view) { + return isValidView(view) ? "vul/xss/reflect/" + view : "error/404"; + } @ApiOperation(value = "漏洞场景:GET型与POST型", notes = "原生漏洞场景,未加任何过滤,Controller接口返回Json类型结果") @RequestMapping("/vul1") @ResponseBody - @ApiImplicitParam(name = "content", value = "请求参数", dataType = "String", paramType = "query", dataTypeClass = String.class) - public R vul1(@ApiParam(name = "content", value = "请求参数", required = true) @RequestParam String content) { - log.info("反射型XSS:" + content); - return R.ok(content); + @ApiImplicitParam(name = "payload", value = "请求参数", dataType = "String", paramType = "query", dataTypeClass = String.class) + public R vul1(@ApiParam(name = "payload", value = "请求参数", required = true) @RequestParam String payload) { + return handleXssPayload(payload, "反射型-GET/POST型", false); } @ApiOperation(value = "漏洞场景:String", notes = "原生漏洞场景,未加任何过滤,Controller接口返回String") @GetMapping("/vul2") @ResponseBody - @ApiImplicitParam(name = "content", value = "请求参数", dataType = "String", paramType = "query", dataTypeClass = String.class) - public String vul2(@ApiParam(name = "content", value = "请求参数", required = true) @RequestParam String content) { - - return content; + @ApiImplicitParam(name = "payload", value = "请求参数", dataType = "String", paramType = "query", dataTypeClass = String.class) + public String vul2(@ApiParam(name = "payload", value = "请求参数", required = true) @RequestParam String payload) { + log.info("[+]XSS-反射型-String型:" + payload); + return payload; } @SneakyThrows @@ -72,19 +64,19 @@ public String vul2(@ApiParam(name = "content", value = "请求参数", required @ResponseBody @ApiImplicitParams({ @ApiImplicitParam(name = "type", value = "类型", dataType = "String", paramType = "query", dataTypeClass = String.class), - @ApiImplicitParam(name = "content", value = "请求参数", dataType = "String", paramType = "query", dataTypeClass = String.class) + @ApiImplicitParam(name = "payload", value = "请求参数", dataType = "String", paramType = "query", dataTypeClass = String.class) }) - public void vul3(@ApiParam(name = "type", value = "类型", required = true) @RequestParam String type, @ApiParam(name = "content", value = "请求参数", required = true) @RequestParam String content, HttpServletResponse response) { + public void vul3(@ApiParam(name = "type", value = "类型", required = true) @RequestParam String type, @ApiParam(name = "payload", value = "请求参数", required = true) @RequestParam String payload, HttpServletResponse response) { switch (type) { case "html": - response.getWriter().print(content); - log.info("反射型XSS,Content-Type:text/html;charset=utf-8:" + content); + response.getWriter().print(payload); + log.info("[+]XSS-反射性-Content-Type:text/html;charset=utf-8:" + payload); response.setContentType("text/html;charset=utf-8"); response.getWriter().flush(); break; case "plain": - log.info("反射型XSS,Content-Type:text/plain;charset=utf-8:" + content); - response.getWriter().print(content); + log.info("[+]XSS-反射性-Content-Type:text/plain;charset=utf-8:" + payload); + response.getWriter().print(payload); response.setContentType("text/plain;charset=utf-8"); // response默认返回Content-Type类型是text/plain response.getWriter().flush(); break; @@ -95,44 +87,51 @@ public void vul3(@ApiParam(name = "type", value = "类型", required = true) @Re break; } } + private static final String WHITELIST_REGEX = "^[a-zA-Z0-9_\\s]+$"; private static final Pattern pattern = Pattern.compile(WHITELIST_REGEX); @ApiOperation(value = "安全代码:用户输入验证和过滤", notes = "对用户输入的数据进行验证和过滤,确保不包含恶意代码。使用白名单过滤,只允许特定类型的输入,如纯文本或指定格式的数据") - @RequestMapping("/safe1") + @GetMapping("/safe1") @ResponseBody @ApiImplicitParams({ @ApiImplicitParam(name = "type", value = "类型", dataType = "String", paramType = "query", dataTypeClass = String.class), @ApiImplicitParam(name = "content", value = "请求参数", dataType = "String", paramType = "query", dataTypeClass = String.class) }) - public R safe1(@ApiParam(name = "type", value = "类型", required = true) @RequestParam String type, @ApiParam(name = "content", value = "请求参数", required = true) @RequestParam String content) { + public R safe1(@ApiParam(name = "type", value = "类型", required = true) @RequestParam String type, @ApiParam(name = "payload", value = "请求参数", required = true) @RequestParam String payload) { String filterContented = ""; switch (type) { case "frontEnd": - filterContented = content; // 前端过滤后传递过来 后端未进行处理(同样存在安全问题) + log.info("[-]XSS-反射性-前端白名单过滤:" + payload); + filterContented = payload; // 前端过滤后传递过来 后端未进行处理(同样存在安全问题) break; case "backEnd": - Matcher matcher = pattern.matcher(content); - if (matcher.matches()){ - return R.ok(content); - }else return R.error("输入内容包含非法字符,请检查输入"); + log.info("[-]XSS-反射性-后端白名单过滤:" + payload); + Matcher matcher = pattern.matcher(payload); + if (matcher.matches()) { + return R.ok(payload); + } else return R.error("输入内容包含非法字符,请检查输入"); } return R.ok(filterContented); } + @ApiOperation(value = "安全代码:内容安全策略-CSP防护", notes = "内容安全策略(Content Security Policy)是一种由浏览器实施的安全机制,旨在减少和防范跨站脚本攻击(XSS)等安全威胁。它通过允许网站管理员定义哪些内容来源是可信任的,从而防止恶意内容的加载和执行") - @RequestMapping("/safe2") + @GetMapping("/safe2") @ResponseBody - @ApiImplicitParam(name = "content", value = "请求参数", dataType = "String", paramType = "query", dataTypeClass = String.class) - public String safe2(@ApiParam(name = "content", value = "请求参数", required = true) @RequestParam String content,HttpServletResponse response) { - response.setHeader("Content-Security-Policy","default-src self"); + @ApiImplicitParam(name = "payload", value = "请求参数", dataType = "String", paramType = "query", dataTypeClass = String.class) + public String safe2(@ApiParam(name = "payload", value = "请求参数", required = true) @RequestParam String payload, HttpServletResponse response) { + response.setHeader("Content-Security-Policy", "default-src self"); response.setHeader("Content-Security-Policy-Report-Only", "default-src 'self'; other-uri /xss/reflect/csp-other-endpoint"); - return content; + log.info("[-]XSS-反射性-内容安全策略-CSP防护:" + payload); + return payload; } + @GetMapping("/a-safe2-CSP-front") - public String safeCSPFront(){ + public String safeCSPFront() { return "vul/xss/csp-protect"; } + @PostMapping("/csp-report-endpoint") public void receiveCSPReport(@RequestBody String reportData) { // 获取当前时间 @@ -152,27 +151,30 @@ public void receiveCSPReport(@RequestBody String reportData) { // System.err.println("Error writing CSP violation other to file: " + e.getMessage()); // } } + @ApiOperation(value = "安全代码:特殊字符实体转义", notes = "特殊字符实体转义是一种将 HTML 中的特殊字符转换为预定义实体表示的过程。这种转义是为了确保在 HTML 页面中正确显示特定字符,同时避免它们被浏览器误解为 HTML 标签或JavaScript代码的一部分,从而导致页面结构混乱或安全漏洞。") - @RequestMapping("/safe3") + @GetMapping("/safe3") @ResponseBody @ApiImplicitParams({ @ApiImplicitParam(name = "type", value = "类型", dataType = "String", paramType = "query", dataTypeClass = String.class), - @ApiImplicitParam(name = "content", value = "请求参数", dataType = "String", paramType = "query", dataTypeClass = String.class) + @ApiImplicitParam(name = "payload", value = "请求参数", dataType = "String", paramType = "query", dataTypeClass = String.class) }) - public R safe3(@ApiParam(name = "type", value = "类型", required = true) @RequestParam String type, @ApiParam(name = "content", value = "请求参数", required = true) @RequestParam String content) { + public R safe3(@ApiParam(name = "type", value = "类型", required = true) @RequestParam String type, @ApiParam(name = "payload", value = "请求参数", required = true) @RequestParam String payload) { String filterContented = ""; - switch (type){ + switch (type) { case "manual": - content = StringUtils.replace(content, "&", "&"); - content = StringUtils.replace(content, "<", "<"); - content = StringUtils.replace(content, ">", ">"); - content = StringUtils.replace(content, "\"", """); - content = StringUtils.replace(content, "'", "'"); - content = StringUtils.replace(content, "/", "/"); - filterContented = content; + payload = StringUtils.replace(payload, "&", "&"); + payload = StringUtils.replace(payload, "<", "<"); + payload = StringUtils.replace(payload, ">", ">"); + payload = StringUtils.replace(payload, "\"", """); + payload = StringUtils.replace(payload, "'", "'"); + payload = StringUtils.replace(payload, "/", "/"); + filterContented = payload; + log.info("[-]XSS-反射性-内容安全策略-CSP防护-原生实体转移:" + payload); break; case "spring": - filterContented = HtmlUtils.htmlEscape(content); + filterContented = HtmlUtils.htmlEscape(payload); + log.info("[-]XSS-反射性-内容安全策略-CSP防护-Spring框架:" + payload); break; default: return R.error("参数输入有误!"); @@ -183,8 +185,8 @@ public R safe3(@ApiParam(name = "type", value = "类型", required = true) @Requ @ApiOperation(value = "安全代码:HttpOnly配置", notes = "HttpOnly是HTTP响应头属性,用于增强Web应用程序安全性。它防止客户端脚本访问(只能通过http/https协议访问)带有HttpOnly标记的 cookie,从而减少跨站点脚本攻击(XSS)的风险。") @RequestMapping(value = "/safe4", method = RequestMethod.GET) @ResponseBody - @ApiImplicitParam(name = "content", value = "请求参数", dataType = "String", paramType = "query", dataTypeClass = String.class) - public R safe4(@ApiParam(name = "content", value = "请求参数", required = true) String content, HttpServletRequest request,HttpServletResponse response) { + @ApiImplicitParam(name = "payload", value = "请求参数", dataType = "String", paramType = "query", dataTypeClass = String.class) + public R safe4(@ApiParam(name = "payload", value = "请求参数", required = true) String payload, HttpServletRequest request, HttpServletResponse response) { Cookie cookie = request.getCookies()[0]; cookie.setHttpOnly(true); // 设置为 HttpOnly @@ -192,6 +194,6 @@ public R safe4(@ApiParam(name = "content", value = "请求参数", required = tr cookie.setPath("/"); response.addCookie(cookie); - return R.ok("已设置httponly(有效期10分钟),请打开控制台查看cookie属性:"+content); + return R.ok("已设置httponly(有效期10分钟),请打开控制台查看cookie属性:" + payload); } } diff --git a/src/main/java/top/whgojp/modules/xss/controller/StoreController.java b/src/main/java/top/whgojp/modules/xss/controller/StoreController.java index a91f126..a4ecf20 100644 --- a/src/main/java/top/whgojp/modules/xss/controller/StoreController.java +++ b/src/main/java/top/whgojp/modules/xss/controller/StoreController.java @@ -46,13 +46,13 @@ public String xssStore() { } @ApiOperation(value = "漏洞场景:原生无过滤", notes = "原生漏洞场景,未加任何过滤,将用户输入存储到数据库中") - @RequestMapping("/vul") + @PostMapping("/vul") @ResponseBody - @ApiImplicitParam(name = "content", value = "请求参数", dataType = "String", paramType = "query", dataTypeClass = String.class) - public R vul(@ApiParam(name = "content", value = "请求参数", required = true) @RequestParam String content,HttpServletRequest request) { - log.info("存储型XSS:" + content); + @ApiImplicitParam(name = "payload", value = "请求参数", dataType = "String", paramType = "query", dataTypeClass = String.class) + public R vul(@ApiParam(name = "payload", value = "请求参数", required = true) @RequestParam String payload,HttpServletRequest request) { + log.info("[+]XSS-存储性-原生无过滤:" + payload); String ua = request.getHeader("User-Agent"); - final int code = xssService.insertOne(content,ua); + final int code = xssService.insertOne(payload,ua); if (code == 1) { log.info("插入数据成功!"); return R.ok("插入数据成功!"); diff --git a/src/main/java/top/whgojp/modules/xss/controller/base/XssBaseController.java b/src/main/java/top/whgojp/modules/xss/controller/base/XssBaseController.java new file mode 100644 index 0000000..4ad2018 --- /dev/null +++ b/src/main/java/top/whgojp/modules/xss/controller/base/XssBaseController.java @@ -0,0 +1,41 @@ +package top.whgojp.modules.xss.controller.base; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.thymeleaf.util.StringUtils; +import top.whgojp.common.utils.CheckUserInput; +import top.whgojp.common.utils.R; + +import javax.servlet.http.HttpServletRequest; + +@Slf4j +public abstract class XssBaseController { + @Autowired + protected CheckUserInput checkUserInput; + + protected R handleXssPayload(String payload, String type, boolean enableFilter) { + if (StringUtils.isEmpty(payload)) { + return R.error("参数不能为空"); + } + + log.info("[+]XSS-{}-收到payload:{}", type, payload); + + if (enableFilter) { + String filteredPayload = checkUserInput.filter(payload); + log.info("[+]XSS-{}-过滤后:{}", type, filteredPayload); + return R.ok(filteredPayload); + } + + return R.ok(payload); + } + + protected String getUserAgent(HttpServletRequest request) { + String ua = request.getHeader("User-Agent"); + return StringUtils.isEmpty(ua) ? "unknown" : ua; + } + + protected boolean isValidView(String view) { + return !StringUtils.isEmpty(view) && + (view.equals("vul") || view.equals("safe")); + } +} diff --git a/src/main/java/top/whgojp/modules/xss/service/impl/XssServiceImpl.java b/src/main/java/top/whgojp/modules/xss/service/impl/XssServiceImpl.java index 034a024..164e309 100644 --- a/src/main/java/top/whgojp/modules/xss/service/impl/XssServiceImpl.java +++ b/src/main/java/top/whgojp/modules/xss/service/impl/XssServiceImpl.java @@ -8,7 +8,6 @@ import top.whgojp.modules.xss.service.XssService; import top.whgojp.modules.xss.mapper.XssMapper; import org.springframework.stereotype.Service; - import java.util.List; /** @@ -18,30 +17,42 @@ */ @Slf4j @Service -public class XssServiceImpl extends ServiceImpl - implements XssService{ +public class XssServiceImpl extends ServiceImpl implements XssService { @Autowired private XssMapper xssMapper; @Override public int insertOne(String content, String ua) { - final int code = xssMapper.insertAll(content,ua,DateUtil.now()); - return code; + try { + log.info("插入XSS记录 - content: {}, ua: {}", content, ua); + final int code = xssMapper.insertAll(content,ua,DateUtil.now()); + return code; + } catch (Exception e) { + log.error("插入XSS记录失败", e); + return 0; + } } @Override public List selectAll() { - List xssList = xssMapper.selectAll(); - return xssList; + try { + List xssList = xssMapper.selectAll(); + return xssList; + } catch (Exception e) { + log.error("查询XSS记录失败", e); + return null; + } } @Override public int deleteById(int id) { - int i = xssMapper.deleteById(id); - return i; + try { + log.info("删除XSS记录 - id: {}", id); + int i = xssMapper.deleteById(id); + return i; + } catch (Exception e) { + log.error("删除XSS记录失败 - id: {}", id, e); + return 0; + } } } - - - - diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 999df61..da6b67f 100755 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -1,28 +1,24 @@ spring: datasource: - type: com.zaxxer.hikari.HikariDataSource + type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver username: root password: QWE123qwe url: jdbc:mysql://localhost:13306/JavaSecLab?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true&allowMultiQueries=true druid: - initial-size: 5 - min-idle: 5 - max-active: 20 - max-wait: 60000 - time-between-eviction-runs-millis: 60000 - min-evictable-idle-time-millis: 300000 - validation-query: SELECT 1 FROM DUAL - test-while-idle: true - test-on-borrow: false - test-on-return: false - pool-prepared-statements: true - max-pool-prepared-statement-per-connection-size: 20 - filters: stat,log4j # wall 这里关闭sql防火墙 - connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 - remove-abandoned: true - remove-abandoned-timeout: 1800 - log-abandoned: true + initial-size: 5 # 初始化连接数 + min-idle: 5 # 最小空闲连接数 + max-active: 20 # 最大连接数 + max-wait: 30000 # 获取连接的最大等待时间(单位:毫秒) + validation-query: SELECT 1 FROM DUAL # 用于验证连接是否可用的 SQL + test-while-idle: true # 是否在空闲时测试连接 + time-between-eviction-runs-millis: 60000 # 空闲连接检测周期(单位:毫秒) + min-evictable-idle-time-millis: 300000 # 连接在池中最小空闲时间(单位:毫秒) + pool-prepared-statements: true # 是否缓存PreparedStatement + max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的最大PreparedStatement数量 + log-abandoned: true # 是否记录被丢弃的连接 + remove-abandoned: true # 是否移除被丢弃的连接 + remove-abandoned-timeout: 180 # 丢弃连接的超时时间(单位:秒) web-stat-filter: enabled: true stat-view-servlet: @@ -31,13 +27,23 @@ spring: # login-username: admin # login-password: admin reset-enable: false - # 防火墙配置 -# wall: -# config: -# multi-statement-allow: false + # 防火墙配置 + # wall: + # config: + # multi-statement-allow: false + + # JPA 配置(可选) + #spring: + jpa: + hibernate: + ddl-auto: update # 自动更新数据库表结构(生产环境建议改为 validate 或 none) + show-sql: true # 打印 SQL 日志 + properties: + hibernate.format_sql: true # 格式化 SQL + hibernate.dialect: org.hibernate.dialect.MySQL8Dialect + +logging: + level: + root: INFO # 默认日志级别 + com.alibaba.druid.pool: DEBUG # 启用 Druid 的 DEBUG 日志(排查数据库连接池问题时启用) -# Hibernate 配置:将当前上下文策略设置为 Spring -# jpa: -# properties: -# hibernate: -# current_session_context_class: thread \ No newline at end of file diff --git a/src/main/resources/application-docker.yml b/src/main/resources/application-docker.yml index c0151f3..840616e 100755 --- a/src/main/resources/application-docker.yml +++ b/src/main/resources/application-docker.yml @@ -5,25 +5,20 @@ spring: username: root password: QWE123qwe url: jdbc:mysql://Container-MYSQL8:3306/JavaSecLab?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true&allowMultiQueries=true -# url: jdbc:mysql://47.94.130.42:3306/JavaSecLab?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true&allowMultiQueries=true druid: - initial-size: 5 - min-idle: 5 - max-active: 20 - max-wait: 60000 - time-between-eviction-runs-millis: 60000 - min-evictable-idle-time-millis: 300000 - validation-query: SELECT 1 FROM DUAL - test-while-idle: true - test-on-borrow: false - test-on-return: false - pool-prepared-statements: true - max-pool-prepared-statement-per-connection-size: 20 - filters: stat,log4j # wall 这里关闭sql防火墙 - connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 - remove-abandoned: true - remove-abandoned-timeout: 1800 - log-abandoned: true + initial-size: 5 # 初始化连接数 + min-idle: 5 # 最小空闲连接数 + max-active: 20 # 最大连接数 + max-wait: 30000 # 获取连接的最大等待时间(单位:毫秒) + validation-query: SELECT 1 FROM DUAL # 用于验证连接是否可用的 SQL + test-while-idle: true # 是否在空闲时测试连接 + time-between-eviction-runs-millis: 60000 # 空闲连接检测周期(单位:毫秒) + min-evictable-idle-time-millis: 300000 # 连接在池中最小空闲时间(单位:毫秒) + pool-prepared-statements: true # 是否缓存PreparedStatement + max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的最大PreparedStatement数量 + log-abandoned: true # 是否记录被丢弃的连接 + remove-abandoned: true # 是否移除被丢弃的连接 + remove-abandoned-timeout: 180 # 丢弃连接的超时时间(单位:秒) web-stat-filter: enabled: true stat-view-servlet: @@ -32,14 +27,22 @@ spring: # login-username: admin # login-password: admin reset-enable: false - # 防火墙配置 - # wall: - # config: - # multi-statement-allow: false + # 防火墙配置 + # wall: + # config: + # multi-statement-allow: false + # JPA 配置(可选) + #spring: jpa: hibernate: - ddl-auto: none - database: mysql - database-platform: org.hibernate.dialect.MySQLDialect - show-sql: true \ No newline at end of file + ddl-auto: update # 自动更新数据库表结构(生产环境建议改为 validate 或 none) + show-sql: true # 打印 SQL 日志 + properties: + hibernate.format_sql: true # 格式化 SQL + hibernate.dialect: org.hibernate.dialect.MySQL8Dialect + +logging: + level: + root: INFO # 默认日志级别 + com.alibaba.druid.pool: DEBUG # 启用 Druid 的 DEBUG 日志(排查数据库连接池问题时启用) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 2b612c5..79061cb 100755 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -41,6 +41,7 @@ management: web: exposure: include: '*' + exclude: base-path: /sys/actuator logging: @@ -56,6 +57,7 @@ mybatis-plus: # 关闭MP3.0自带的banner banner: false + folder: upload: /tmp/upload static: /tmp/static @@ -89,4 +91,9 @@ J2FhZOq2OdVaWGKwW9BEcnx1QjMSZgciYR9anFyX4haMlDUdSBQYt0FwfRFfzARd hGUahXhPvN1OkI+772dFhjpQYxf02oKrdW/pNrTAoYyE9tCUUeZngUZ6SkN+TlJa ouK1o4xnmMD2YhHhzmxyn8wlLB8KopMzCQ8WaooivlJbyXQVp6bq9UFaeQW0NtIB tzMFGyiO+DvR4pO52uQLEBU= ------END PRIVATE KEY-----" \ No newline at end of file +-----END PRIVATE KEY-----" + +jwt: + key: f3a4c6d5b9bfeff28b1f529b0840134bcd4183474e2d4a97c05615a134e4f4da + +#debug: true \ No newline at end of file diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt index cf6c02b..79d4bf5 100755 --- a/src/main/resources/banner.txt +++ b/src/main/resources/banner.txt @@ -1,5 +1,8 @@ ==================================================================================================================== - - Powered By whgojp + __ _____ __ __ + / /___ __ ______ _/ ___/___ _____/ / ____ _/ /_ + __ / / __ `/ | / / __ `/\__ \/ _ \/ ___/ / / __ `/ __ \ + / /_/ / /_/ /| |/ / /_/ /___/ / __/ /__/ /___/ /_/ / /_/ / + \____/\__,_/ |___/\__,_//____/\___/\___/_____/\__,_/_.___/ ==================================================================================================================== \ No newline at end of file diff --git a/src/main/resources/static/api/init.json b/src/main/resources/static/api/init.json index d7f58fe..5b85259 100644 --- a/src/main/resources/static/api/init.json +++ b/src/main/resources/static/api/init.json @@ -477,6 +477,7 @@ } ] } + ] } ] diff --git a/src/main/resources/static/images/vul/jdbc/jdbc.png b/src/main/resources/static/images/vul/jdbc/jdbc.png new file mode 100644 index 0000000000000000000000000000000000000000..a4cf54f62c047eaf4a574797c1f038823b97265b GIT binary patch literal 152497 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/static/images/vul/memshell/filter.png b/src/main/resources/static/images/vul/memshell/filter.png new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/main/resources/static/images/vul/memshell/filter.png @@ -0,0 +1 @@ + diff --git a/src/main/resources/static/images/vul/memshell/listener.png b/src/main/resources/static/images/vul/memshell/listener.png new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/main/resources/static/images/vul/memshell/listener.png @@ -0,0 +1 @@ + diff --git a/src/main/resources/static/images/vul/memshell/servlet.png b/src/main/resources/static/images/vul/memshell/servlet.png new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/main/resources/static/images/vul/memshell/servlet.png @@ -0,0 +1 @@ + diff --git a/src/main/resources/static/js/jsencrypt.min.js b/src/main/resources/static/js/jsencrypt.min.js new file mode 100644 index 0000000..c2b6b10 --- /dev/null +++ b/src/main/resources/static/js/jsencrypt.min.js @@ -0,0 +1,1540 @@ +/*! For license information please see jsencrypt.min.js.LICENSE.txt */ +!function (t, e) { + "object" == typeof exports && "object" == typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define([], e) : "object" == typeof exports ? exports.JSEncrypt = e() : t.JSEncrypt = e() +}(window, (function () { + return (() => { + "use strict"; + var t = { + 771: (t, e, i) => { + function r(t) { + return "0123456789abcdefghijklmnopqrstuvwxyz".charAt(t) + } + + function n(t, e) { + return t & e + } + + function s(t, e) { + return t | e + } + + function o(t, e) { + return t ^ e + } + + function h(t, e) { + return t & ~e + } + + function a(t) { + if (0 == t) return -1; + var e = 0; + return 0 == (65535 & t) && (t >>= 16, e += 16), 0 == (255 & t) && (t >>= 8, e += 8), 0 == (15 & t) && (t >>= 4, e += 4), 0 == (3 & t) && (t >>= 2, e += 2), 0 == (1 & t) && ++e, e + } + + function u(t) { + for (var e = 0; 0 != t;) t &= t - 1, ++e; + return e + } + + i.d(e, {default: () => nt}); + var c, f = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + function l(t) { + var e, i, r = ""; + for (e = 0; e + 3 <= t.length; e += 3) i = parseInt(t.substring(e, e + 3), 16), r += f.charAt(i >> 6) + f.charAt(63 & i); + for (e + 1 == t.length ? (i = parseInt(t.substring(e, e + 1), 16), r += f.charAt(i << 2)) : e + 2 == t.length && (i = parseInt(t.substring(e, e + 2), 16), r += f.charAt(i >> 2) + f.charAt((3 & i) << 4)); (3 & r.length) > 0;) r += "="; + return r + } + + function p(t) { + var e, i = "", n = 0, s = 0; + for (e = 0; e < t.length && "=" != t.charAt(e); ++e) { + var o = f.indexOf(t.charAt(e)); + o < 0 || (0 == n ? (i += r(o >> 2), s = 3 & o, n = 1) : 1 == n ? (i += r(s << 2 | o >> 4), s = 15 & o, n = 2) : 2 == n ? (i += r(s), i += r(o >> 2), s = 3 & o, n = 3) : (i += r(s << 2 | o >> 4), i += r(15 & o), n = 0)) + } + return 1 == n && (i += r(s << 2)), i + } + + var g, d = { + decode: function (t) { + var e; + if (void 0 === g) { + var i = "= \f\n\r\t \u2028\u2029"; + for (g = Object.create(null), e = 0; e < 64; ++e) g["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(e)] = e; + for (g["-"] = 62, g._ = 63, e = 0; e < i.length; ++e) g[i.charAt(e)] = -1 + } + var r = [], n = 0, s = 0; + for (e = 0; e < t.length; ++e) { + var o = t.charAt(e); + if ("=" == o) break; + if (-1 != (o = g[o])) { + if (void 0 === o) throw new Error("Illegal character at offset " + e); + n |= o, ++s >= 4 ? (r[r.length] = n >> 16, r[r.length] = n >> 8 & 255, r[r.length] = 255 & n, n = 0, s = 0) : n <<= 6 + } + } + switch (s) { + case 1: + throw new Error("Base64 encoding incomplete: at least 2 bits missing"); + case 2: + r[r.length] = n >> 10; + break; + case 3: + r[r.length] = n >> 16, r[r.length] = n >> 8 & 255 + } + return r + }, + re: /-----BEGIN [^-]+-----([A-Za-z0-9+\/=\s]+)-----END [^-]+-----|begin-base64[^\n]+\n([A-Za-z0-9+\/=\s]+)====/, + unarmor: function (t) { + var e = d.re.exec(t); + if (e) if (e[1]) t = e[1]; else { + if (!e[2]) throw new Error("RegExp out of sync"); + t = e[2] + } + return d.decode(t) + } + }, v = 1e13, m = function () { + function t(t) { + this.buf = [+t || 0] + } + + return t.prototype.mulAdd = function (t, e) { + var i, r, n = this.buf, s = n.length; + for (i = 0; i < s; ++i) (r = n[i] * t + e) < v ? e = 0 : r -= (e = 0 | r / v) * v, n[i] = r; + e > 0 && (n[i] = e) + }, t.prototype.sub = function (t) { + var e, i, r = this.buf, n = r.length; + for (e = 0; e < n; ++e) (i = r[e] - t) < 0 ? (i += v, t = 1) : t = 0, r[e] = i; + for (; 0 === r[r.length - 1];) r.pop() + }, t.prototype.toString = function (t) { + if (10 != (t || 10)) throw new Error("only base 10 is supported"); + for (var e = this.buf, i = e[e.length - 1].toString(), r = e.length - 2; r >= 0; --r) i += (v + e[r]).toString().substring(1); + return i + }, t.prototype.valueOf = function () { + for (var t = this.buf, e = 0, i = t.length - 1; i >= 0; --i) e = e * v + t[i]; + return e + }, t.prototype.simplify = function () { + var t = this.buf; + return 1 == t.length ? t[0] : this + }, t + }(), + y = /^(\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/, + b = /^(\d\d\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/; + + function T(t, e) { + return t.length > e && (t = t.substring(0, e) + "…"), t + } + + var S, E = function () { + function t(e, i) { + this.hexDigits = "0123456789ABCDEF", e instanceof t ? (this.enc = e.enc, this.pos = e.pos) : (this.enc = e, this.pos = i) + } + + return t.prototype.get = function (t) { + if (void 0 === t && (t = this.pos++), t >= this.enc.length) throw new Error("Requesting byte offset " + t + " on a stream of length " + this.enc.length); + return "string" == typeof this.enc ? this.enc.charCodeAt(t) : this.enc[t] + }, t.prototype.hexByte = function (t) { + return this.hexDigits.charAt(t >> 4 & 15) + this.hexDigits.charAt(15 & t) + }, t.prototype.hexDump = function (t, e, i) { + for (var r = "", n = t; n < e; ++n) if (r += this.hexByte(this.get(n)), !0 !== i) switch (15 & n) { + case 7: + r += " "; + break; + case 15: + r += "\n"; + break; + default: + r += " " + } + return r + }, t.prototype.isASCII = function (t, e) { + for (var i = t; i < e; ++i) { + var r = this.get(i); + if (r < 32 || r > 176) return !1 + } + return !0 + }, t.prototype.parseStringISO = function (t, e) { + for (var i = "", r = t; r < e; ++r) i += String.fromCharCode(this.get(r)); + return i + }, t.prototype.parseStringUTF = function (t, e) { + for (var i = "", r = t; r < e;) { + var n = this.get(r++); + i += n < 128 ? String.fromCharCode(n) : n > 191 && n < 224 ? String.fromCharCode((31 & n) << 6 | 63 & this.get(r++)) : String.fromCharCode((15 & n) << 12 | (63 & this.get(r++)) << 6 | 63 & this.get(r++)) + } + return i + }, t.prototype.parseStringBMP = function (t, e) { + for (var i, r, n = "", s = t; s < e;) i = this.get(s++), r = this.get(s++), n += String.fromCharCode(i << 8 | r); + return n + }, t.prototype.parseTime = function (t, e, i) { + var r = this.parseStringISO(t, e), n = (i ? y : b).exec(r); + return n ? (i && (n[1] = +n[1], n[1] += +n[1] < 70 ? 2e3 : 1900), r = n[1] + "-" + n[2] + "-" + n[3] + " " + n[4], n[5] && (r += ":" + n[5], n[6] && (r += ":" + n[6], n[7] && (r += "." + n[7]))), n[8] && (r += " UTC", "Z" != n[8] && (r += n[8], n[9] && (r += ":" + n[9]))), r) : "Unrecognized time: " + r + }, t.prototype.parseInteger = function (t, e) { + for (var i, r = this.get(t), n = r > 127, s = n ? 255 : 0, o = ""; r == s && ++t < e;) r = this.get(t); + if (0 == (i = e - t)) return n ? -1 : 0; + if (i > 4) { + for (o = r, i <<= 3; 0 == (128 & (+o ^ s));) o = +o << 1, --i; + o = "(" + i + " bit)\n" + } + n && (r -= 256); + for (var h = new m(r), a = t + 1; a < e; ++a) h.mulAdd(256, this.get(a)); + return o + h.toString() + }, t.prototype.parseBitString = function (t, e, i) { + for (var r = this.get(t), n = "(" + ((e - t - 1 << 3) - r) + " bit)\n", s = "", o = t + 1; o < e; ++o) { + for (var h = this.get(o), a = o == e - 1 ? r : 0, u = 7; u >= a; --u) s += h >> u & 1 ? "1" : "0"; + if (s.length > i) return n + T(s, i) + } + return n + s + }, t.prototype.parseOctetString = function (t, e, i) { + if (this.isASCII(t, e)) return T(this.parseStringISO(t, e), i); + var r = e - t, n = "(" + r + " byte)\n"; + r > (i /= 2) && (e = t + i); + for (var s = t; s < e; ++s) n += this.hexByte(this.get(s)); + return r > i && (n += "…"), n + }, t.prototype.parseOID = function (t, e, i) { + for (var r = "", n = new m, s = 0, o = t; o < e; ++o) { + var h = this.get(o); + if (n.mulAdd(128, 127 & h), s += 7, !(128 & h)) { + if ("" === r) if ((n = n.simplify()) instanceof m) n.sub(80), r = "2." + n.toString(); else { + var a = n < 80 ? n < 40 ? 0 : 1 : 2; + r = a + "." + (n - 40 * a) + } else r += "." + n.toString(); + if (r.length > i) return T(r, i); + n = new m, s = 0 + } + } + return s > 0 && (r += ".incomplete"), r + }, t + }(), w = function () { + function t(t, e, i, r, n) { + if (!(r instanceof D)) throw new Error("Invalid tag value."); + this.stream = t, this.header = e, this.length = i, this.tag = r, this.sub = n + } + + return t.prototype.typeName = function () { + switch (this.tag.tagClass) { + case 0: + switch (this.tag.tagNumber) { + case 0: + return "EOC"; + case 1: + return "BOOLEAN"; + case 2: + return "INTEGER"; + case 3: + return "BIT_STRING"; + case 4: + return "OCTET_STRING"; + case 5: + return "NULL"; + case 6: + return "OBJECT_IDENTIFIER"; + case 7: + return "ObjectDescriptor"; + case 8: + return "EXTERNAL"; + case 9: + return "REAL"; + case 10: + return "ENUMERATED"; + case 11: + return "EMBEDDED_PDV"; + case 12: + return "UTF8String"; + case 16: + return "SEQUENCE"; + case 17: + return "SET"; + case 18: + return "NumericString"; + case 19: + return "PrintableString"; + case 20: + return "TeletexString"; + case 21: + return "VideotexString"; + case 22: + return "IA5String"; + case 23: + return "UTCTime"; + case 24: + return "GeneralizedTime"; + case 25: + return "GraphicString"; + case 26: + return "VisibleString"; + case 27: + return "GeneralString"; + case 28: + return "UniversalString"; + case 30: + return "BMPString" + } + return "Universal_" + this.tag.tagNumber.toString(); + case 1: + return "Application_" + this.tag.tagNumber.toString(); + case 2: + return "[" + this.tag.tagNumber.toString() + "]"; + case 3: + return "Private_" + this.tag.tagNumber.toString() + } + }, t.prototype.content = function (t) { + if (void 0 === this.tag) return null; + void 0 === t && (t = 1 / 0); + var e = this.posContent(), i = Math.abs(this.length); + if (!this.tag.isUniversal()) return null !== this.sub ? "(" + this.sub.length + " elem)" : this.stream.parseOctetString(e, e + i, t); + switch (this.tag.tagNumber) { + case 1: + return 0 === this.stream.get(e) ? "false" : "true"; + case 2: + return this.stream.parseInteger(e, e + i); + case 3: + return this.sub ? "(" + this.sub.length + " elem)" : this.stream.parseBitString(e, e + i, t); + case 4: + return this.sub ? "(" + this.sub.length + " elem)" : this.stream.parseOctetString(e, e + i, t); + case 6: + return this.stream.parseOID(e, e + i, t); + case 16: + case 17: + return null !== this.sub ? "(" + this.sub.length + " elem)" : "(no elem)"; + case 12: + return T(this.stream.parseStringUTF(e, e + i), t); + case 18: + case 19: + case 20: + case 21: + case 22: + case 26: + return T(this.stream.parseStringISO(e, e + i), t); + case 30: + return T(this.stream.parseStringBMP(e, e + i), t); + case 23: + case 24: + return this.stream.parseTime(e, e + i, 23 == this.tag.tagNumber) + } + return null + }, t.prototype.toString = function () { + return this.typeName() + "@" + this.stream.pos + "[header:" + this.header + ",length:" + this.length + ",sub:" + (null === this.sub ? "null" : this.sub.length) + "]" + }, t.prototype.toPrettyString = function (t) { + void 0 === t && (t = ""); + var e = t + this.typeName() + " @" + this.stream.pos; + if (this.length >= 0 && (e += "+"), e += this.length, this.tag.tagConstructed ? e += " (constructed)" : !this.tag.isUniversal() || 3 != this.tag.tagNumber && 4 != this.tag.tagNumber || null === this.sub || (e += " (encapsulates)"), e += "\n", null !== this.sub) { + t += " "; + for (var i = 0, r = this.sub.length; i < r; ++i) e += this.sub[i].toPrettyString(t) + } + return e + }, t.prototype.posStart = function () { + return this.stream.pos + }, t.prototype.posContent = function () { + return this.stream.pos + this.header + }, t.prototype.posEnd = function () { + return this.stream.pos + this.header + Math.abs(this.length) + }, t.prototype.toHexString = function () { + return this.stream.hexDump(this.posStart(), this.posEnd(), !0) + }, t.decodeLength = function (t) { + var e = t.get(), i = 127 & e; + if (i == e) return i; + if (i > 6) throw new Error("Length over 48 bits not supported at position " + (t.pos - 1)); + if (0 === i) return null; + e = 0; + for (var r = 0; r < i; ++r) e = 256 * e + t.get(); + return e + }, t.prototype.getHexStringValue = function () { + var t = this.toHexString(), e = 2 * this.header, i = 2 * this.length; + return t.substr(e, i) + }, t.decode = function (e) { + var i; + i = e instanceof E ? e : new E(e, 0); + var r = new E(i), n = new D(i), s = t.decodeLength(i), o = i.pos, h = o - r.pos, a = null, + u = function () { + var e = []; + if (null !== s) { + for (var r = o + s; i.pos < r;) e[e.length] = t.decode(i); + if (i.pos != r) throw new Error("Content size is not correct for container starting at offset " + o) + } else try { + for (; ;) { + var n = t.decode(i); + if (n.tag.isEOC()) break; + e[e.length] = n + } + s = o - i.pos + } catch (t) { + throw new Error("Exception while decoding undefined length content: " + t) + } + return e + }; + if (n.tagConstructed) a = u(); else if (n.isUniversal() && (3 == n.tagNumber || 4 == n.tagNumber)) try { + if (3 == n.tagNumber && 0 != i.get()) throw new Error("BIT STRINGs with unused bits cannot encapsulate."); + a = u(); + for (var c = 0; c < a.length; ++c) if (a[c].tag.isEOC()) throw new Error("EOC is not supposed to be actual content.") + } catch (t) { + a = null + } + if (null === a) { + if (null === s) throw new Error("We can't skip over an invalid tag with undefined length at offset " + o); + i.pos = o + Math.abs(s) + } + return new t(r, h, s, n, a) + }, t + }(), D = function () { + function t(t) { + var e = t.get(); + if (this.tagClass = e >> 6, this.tagConstructed = 0 != (32 & e), this.tagNumber = 31 & e, 31 == this.tagNumber) { + var i = new m; + do { + e = t.get(), i.mulAdd(128, 127 & e) + } while (128 & e); + this.tagNumber = i.simplify() + } + } + + return t.prototype.isUniversal = function () { + return 0 === this.tagClass + }, t.prototype.isEOC = function () { + return 0 === this.tagClass && 0 === this.tagNumber + }, t + }(), + x = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997], + R = (1 << 26) / x[x.length - 1], B = function () { + function t(t, e, i) { + null != t && ("number" == typeof t ? this.fromNumber(t, e, i) : null == e && "string" != typeof t ? this.fromString(t, 256) : this.fromString(t, e)) + } + + return t.prototype.toString = function (t) { + if (this.s < 0) return "-" + this.negate().toString(t); + var e; + if (16 == t) e = 4; else if (8 == t) e = 3; else if (2 == t) e = 1; else if (32 == t) e = 5; else { + if (4 != t) return this.toRadix(t); + e = 2 + } + var i, n = (1 << e) - 1, s = !1, o = "", h = this.t, a = this.DB - h * this.DB % e; + if (h-- > 0) for (a < this.DB && (i = this[h] >> a) > 0 && (s = !0, o = r(i)); h >= 0;) a < e ? (i = (this[h] & (1 << a) - 1) << e - a, i |= this[--h] >> (a += this.DB - e)) : (i = this[h] >> (a -= e) & n, a <= 0 && (a += this.DB, --h)), i > 0 && (s = !0), s && (o += r(i)); + return s ? o : "0" + }, t.prototype.negate = function () { + var e = N(); + return t.ZERO.subTo(this, e), e + }, t.prototype.abs = function () { + return this.s < 0 ? this.negate() : this + }, t.prototype.compareTo = function (t) { + var e = this.s - t.s; + if (0 != e) return e; + var i = this.t; + if (0 != (e = i - t.t)) return this.s < 0 ? -e : e; + for (; --i >= 0;) if (0 != (e = this[i] - t[i])) return e; + return 0 + }, t.prototype.bitLength = function () { + return this.t <= 0 ? 0 : this.DB * (this.t - 1) + F(this[this.t - 1] ^ this.s & this.DM) + }, t.prototype.mod = function (e) { + var i = N(); + return this.abs().divRemTo(e, null, i), this.s < 0 && i.compareTo(t.ZERO) > 0 && e.subTo(i, i), i + }, t.prototype.modPowInt = function (t, e) { + var i; + return i = t < 256 || e.isEven() ? new A(e) : new V(e), this.exp(t, i) + }, t.prototype.clone = function () { + var t = N(); + return this.copyTo(t), t + }, t.prototype.intValue = function () { + if (this.s < 0) { + if (1 == this.t) return this[0] - this.DV; + if (0 == this.t) return -1 + } else { + if (1 == this.t) return this[0]; + if (0 == this.t) return 0 + } + return (this[1] & (1 << 32 - this.DB) - 1) << this.DB | this[0] + }, t.prototype.byteValue = function () { + return 0 == this.t ? this.s : this[0] << 24 >> 24 + }, t.prototype.shortValue = function () { + return 0 == this.t ? this.s : this[0] << 16 >> 16 + }, t.prototype.signum = function () { + return this.s < 0 ? -1 : this.t <= 0 || 1 == this.t && this[0] <= 0 ? 0 : 1 + }, t.prototype.toByteArray = function () { + var t = this.t, e = []; + e[0] = this.s; + var i, r = this.DB - t * this.DB % 8, n = 0; + if (t-- > 0) for (r < this.DB && (i = this[t] >> r) != (this.s & this.DM) >> r && (e[n++] = i | this.s << this.DB - r); t >= 0;) r < 8 ? (i = (this[t] & (1 << r) - 1) << 8 - r, i |= this[--t] >> (r += this.DB - 8)) : (i = this[t] >> (r -= 8) & 255, r <= 0 && (r += this.DB, --t)), 0 != (128 & i) && (i |= -256), 0 == n && (128 & this.s) != (128 & i) && ++n, (n > 0 || i != this.s) && (e[n++] = i); + return e + }, t.prototype.equals = function (t) { + return 0 == this.compareTo(t) + }, t.prototype.min = function (t) { + return this.compareTo(t) < 0 ? this : t + }, t.prototype.max = function (t) { + return this.compareTo(t) > 0 ? this : t + }, t.prototype.and = function (t) { + var e = N(); + return this.bitwiseTo(t, n, e), e + }, t.prototype.or = function (t) { + var e = N(); + return this.bitwiseTo(t, s, e), e + }, t.prototype.xor = function (t) { + var e = N(); + return this.bitwiseTo(t, o, e), e + }, t.prototype.andNot = function (t) { + var e = N(); + return this.bitwiseTo(t, h, e), e + }, t.prototype.not = function () { + for (var t = N(), e = 0; e < this.t; ++e) t[e] = this.DM & ~this[e]; + return t.t = this.t, t.s = ~this.s, t + }, t.prototype.shiftLeft = function (t) { + var e = N(); + return t < 0 ? this.rShiftTo(-t, e) : this.lShiftTo(t, e), e + }, t.prototype.shiftRight = function (t) { + var e = N(); + return t < 0 ? this.lShiftTo(-t, e) : this.rShiftTo(t, e), e + }, t.prototype.getLowestSetBit = function () { + for (var t = 0; t < this.t; ++t) if (0 != this[t]) return t * this.DB + a(this[t]); + return this.s < 0 ? this.t * this.DB : -1 + }, t.prototype.bitCount = function () { + for (var t = 0, e = this.s & this.DM, i = 0; i < this.t; ++i) t += u(this[i] ^ e); + return t + }, t.prototype.testBit = function (t) { + var e = Math.floor(t / this.DB); + return e >= this.t ? 0 != this.s : 0 != (this[e] & 1 << t % this.DB) + }, t.prototype.setBit = function (t) { + return this.changeBit(t, s) + }, t.prototype.clearBit = function (t) { + return this.changeBit(t, h) + }, t.prototype.flipBit = function (t) { + return this.changeBit(t, o) + }, t.prototype.add = function (t) { + var e = N(); + return this.addTo(t, e), e + }, t.prototype.subtract = function (t) { + var e = N(); + return this.subTo(t, e), e + }, t.prototype.multiply = function (t) { + var e = N(); + return this.multiplyTo(t, e), e + }, t.prototype.divide = function (t) { + var e = N(); + return this.divRemTo(t, e, null), e + }, t.prototype.remainder = function (t) { + var e = N(); + return this.divRemTo(t, null, e), e + }, t.prototype.divideAndRemainder = function (t) { + var e = N(), i = N(); + return this.divRemTo(t, e, i), [e, i] + }, t.prototype.modPow = function (t, e) { + var i, r, n = t.bitLength(), s = C(1); + if (n <= 0) return s; + i = n < 18 ? 1 : n < 48 ? 3 : n < 144 ? 4 : n < 768 ? 5 : 6, r = n < 8 ? new A(e) : e.isEven() ? new I(e) : new V(e); + var o = [], h = 3, a = i - 1, u = (1 << i) - 1; + if (o[1] = r.convert(this), i > 1) { + var c = N(); + for (r.sqrTo(o[1], c); h <= u;) o[h] = N(), r.mulTo(c, o[h - 2], o[h]), h += 2 + } + var f, l, p = t.t - 1, g = !0, d = N(); + for (n = F(t[p]) - 1; p >= 0;) { + for (n >= a ? f = t[p] >> n - a & u : (f = (t[p] & (1 << n + 1) - 1) << a - n, p > 0 && (f |= t[p - 1] >> this.DB + n - a)), h = i; 0 == (1 & f);) f >>= 1, --h; + if ((n -= h) < 0 && (n += this.DB, --p), g) o[f].copyTo(s), g = !1; else { + for (; h > 1;) r.sqrTo(s, d), r.sqrTo(d, s), h -= 2; + h > 0 ? r.sqrTo(s, d) : (l = s, s = d, d = l), r.mulTo(d, o[f], s) + } + for (; p >= 0 && 0 == (t[p] & 1 << n);) r.sqrTo(s, d), l = s, s = d, d = l, --n < 0 && (n = this.DB - 1, --p) + } + return r.revert(s) + }, t.prototype.modInverse = function (e) { + var i = e.isEven(); + if (this.isEven() && i || 0 == e.signum()) return t.ZERO; + for (var r = e.clone(), n = this.clone(), s = C(1), o = C(0), h = C(0), a = C(1); 0 != r.signum();) { + for (; r.isEven();) r.rShiftTo(1, r), i ? (s.isEven() && o.isEven() || (s.addTo(this, s), o.subTo(e, o)), s.rShiftTo(1, s)) : o.isEven() || o.subTo(e, o), o.rShiftTo(1, o); + for (; n.isEven();) n.rShiftTo(1, n), i ? (h.isEven() && a.isEven() || (h.addTo(this, h), a.subTo(e, a)), h.rShiftTo(1, h)) : a.isEven() || a.subTo(e, a), a.rShiftTo(1, a); + r.compareTo(n) >= 0 ? (r.subTo(n, r), i && s.subTo(h, s), o.subTo(a, o)) : (n.subTo(r, n), i && h.subTo(s, h), a.subTo(o, a)) + } + return 0 != n.compareTo(t.ONE) ? t.ZERO : a.compareTo(e) >= 0 ? a.subtract(e) : a.signum() < 0 ? (a.addTo(e, a), a.signum() < 0 ? a.add(e) : a) : a + }, t.prototype.pow = function (t) { + return this.exp(t, new O) + }, t.prototype.gcd = function (t) { + var e = this.s < 0 ? this.negate() : this.clone(), i = t.s < 0 ? t.negate() : t.clone(); + if (e.compareTo(i) < 0) { + var r = e; + e = i, i = r + } + var n = e.getLowestSetBit(), s = i.getLowestSetBit(); + if (s < 0) return e; + for (n < s && (s = n), s > 0 && (e.rShiftTo(s, e), i.rShiftTo(s, i)); e.signum() > 0;) (n = e.getLowestSetBit()) > 0 && e.rShiftTo(n, e), (n = i.getLowestSetBit()) > 0 && i.rShiftTo(n, i), e.compareTo(i) >= 0 ? (e.subTo(i, e), e.rShiftTo(1, e)) : (i.subTo(e, i), i.rShiftTo(1, i)); + return s > 0 && i.lShiftTo(s, i), i + }, t.prototype.isProbablePrime = function (t) { + var e, i = this.abs(); + if (1 == i.t && i[0] <= x[x.length - 1]) { + for (e = 0; e < x.length; ++e) if (i[0] == x[e]) return !0; + return !1 + } + if (i.isEven()) return !1; + for (e = 1; e < x.length;) { + for (var r = x[e], n = e + 1; n < x.length && r < R;) r *= x[n++]; + for (r = i.modInt(r); e < n;) if (r % x[e++] == 0) return !1 + } + return i.millerRabin(t) + }, t.prototype.copyTo = function (t) { + for (var e = this.t - 1; e >= 0; --e) t[e] = this[e]; + t.t = this.t, t.s = this.s + }, t.prototype.fromInt = function (t) { + this.t = 1, this.s = t < 0 ? -1 : 0, t > 0 ? this[0] = t : t < -1 ? this[0] = t + this.DV : this.t = 0 + }, t.prototype.fromString = function (e, i) { + var r; + if (16 == i) r = 4; else if (8 == i) r = 3; else if (256 == i) r = 8; else if (2 == i) r = 1; else if (32 == i) r = 5; else { + if (4 != i) return void this.fromRadix(e, i); + r = 2 + } + this.t = 0, this.s = 0; + for (var n = e.length, s = !1, o = 0; --n >= 0;) { + var h = 8 == r ? 255 & +e[n] : H(e, n); + h < 0 ? "-" == e.charAt(n) && (s = !0) : (s = !1, 0 == o ? this[this.t++] = h : o + r > this.DB ? (this[this.t - 1] |= (h & (1 << this.DB - o) - 1) << o, this[this.t++] = h >> this.DB - o) : this[this.t - 1] |= h << o, (o += r) >= this.DB && (o -= this.DB)) + } + 8 == r && 0 != (128 & +e[0]) && (this.s = -1, o > 0 && (this[this.t - 1] |= (1 << this.DB - o) - 1 << o)), this.clamp(), s && t.ZERO.subTo(this, this) + }, t.prototype.clamp = function () { + for (var t = this.s & this.DM; this.t > 0 && this[this.t - 1] == t;) --this.t + }, t.prototype.dlShiftTo = function (t, e) { + var i; + for (i = this.t - 1; i >= 0; --i) e[i + t] = this[i]; + for (i = t - 1; i >= 0; --i) e[i] = 0; + e.t = this.t + t, e.s = this.s + }, t.prototype.drShiftTo = function (t, e) { + for (var i = t; i < this.t; ++i) e[i - t] = this[i]; + e.t = Math.max(this.t - t, 0), e.s = this.s + }, t.prototype.lShiftTo = function (t, e) { + for (var i = t % this.DB, r = this.DB - i, n = (1 << r) - 1, s = Math.floor(t / this.DB), o = this.s << i & this.DM, h = this.t - 1; h >= 0; --h) e[h + s + 1] = this[h] >> r | o, o = (this[h] & n) << i; + for (h = s - 1; h >= 0; --h) e[h] = 0; + e[s] = o, e.t = this.t + s + 1, e.s = this.s, e.clamp() + }, t.prototype.rShiftTo = function (t, e) { + e.s = this.s; + var i = Math.floor(t / this.DB); + if (i >= this.t) e.t = 0; else { + var r = t % this.DB, n = this.DB - r, s = (1 << r) - 1; + e[0] = this[i] >> r; + for (var o = i + 1; o < this.t; ++o) e[o - i - 1] |= (this[o] & s) << n, e[o - i] = this[o] >> r; + r > 0 && (e[this.t - i - 1] |= (this.s & s) << n), e.t = this.t - i, e.clamp() + } + }, t.prototype.subTo = function (t, e) { + for (var i = 0, r = 0, n = Math.min(t.t, this.t); i < n;) r += this[i] - t[i], e[i++] = r & this.DM, r >>= this.DB; + if (t.t < this.t) { + for (r -= t.s; i < this.t;) r += this[i], e[i++] = r & this.DM, r >>= this.DB; + r += this.s + } else { + for (r += this.s; i < t.t;) r -= t[i], e[i++] = r & this.DM, r >>= this.DB; + r -= t.s + } + e.s = r < 0 ? -1 : 0, r < -1 ? e[i++] = this.DV + r : r > 0 && (e[i++] = r), e.t = i, e.clamp() + }, t.prototype.multiplyTo = function (e, i) { + var r = this.abs(), n = e.abs(), s = r.t; + for (i.t = s + n.t; --s >= 0;) i[s] = 0; + for (s = 0; s < n.t; ++s) i[s + r.t] = r.am(0, n[s], i, s, 0, r.t); + i.s = 0, i.clamp(), this.s != e.s && t.ZERO.subTo(i, i) + }, t.prototype.squareTo = function (t) { + for (var e = this.abs(), i = t.t = 2 * e.t; --i >= 0;) t[i] = 0; + for (i = 0; i < e.t - 1; ++i) { + var r = e.am(i, e[i], t, 2 * i, 0, 1); + (t[i + e.t] += e.am(i + 1, 2 * e[i], t, 2 * i + 1, r, e.t - i - 1)) >= e.DV && (t[i + e.t] -= e.DV, t[i + e.t + 1] = 1) + } + t.t > 0 && (t[t.t - 1] += e.am(i, e[i], t, 2 * i, 0, 1)), t.s = 0, t.clamp() + }, t.prototype.divRemTo = function (e, i, r) { + var n = e.abs(); + if (!(n.t <= 0)) { + var s = this.abs(); + if (s.t < n.t) return null != i && i.fromInt(0), void (null != r && this.copyTo(r)); + null == r && (r = N()); + var o = N(), h = this.s, a = e.s, u = this.DB - F(n[n.t - 1]); + u > 0 ? (n.lShiftTo(u, o), s.lShiftTo(u, r)) : (n.copyTo(o), s.copyTo(r)); + var c = o.t, f = o[c - 1]; + if (0 != f) { + var l = f * (1 << this.F1) + (c > 1 ? o[c - 2] >> this.F2 : 0), p = this.FV / l, + g = (1 << this.F1) / l, d = 1 << this.F2, v = r.t, m = v - c, + y = null == i ? N() : i; + for (o.dlShiftTo(m, y), r.compareTo(y) >= 0 && (r[r.t++] = 1, r.subTo(y, r)), t.ONE.dlShiftTo(c, y), y.subTo(o, o); o.t < c;) o[o.t++] = 0; + for (; --m >= 0;) { + var b = r[--v] == f ? this.DM : Math.floor(r[v] * p + (r[v - 1] + d) * g); + if ((r[v] += o.am(0, b, r, m, 0, c)) < b) for (o.dlShiftTo(m, y), r.subTo(y, r); r[v] < --b;) r.subTo(y, r) + } + null != i && (r.drShiftTo(c, i), h != a && t.ZERO.subTo(i, i)), r.t = c, r.clamp(), u > 0 && r.rShiftTo(u, r), h < 0 && t.ZERO.subTo(r, r) + } + } + }, t.prototype.invDigit = function () { + if (this.t < 1) return 0; + var t = this[0]; + if (0 == (1 & t)) return 0; + var e = 3 & t; + return (e = (e = (e = (e = e * (2 - (15 & t) * e) & 15) * (2 - (255 & t) * e) & 255) * (2 - ((65535 & t) * e & 65535)) & 65535) * (2 - t * e % this.DV) % this.DV) > 0 ? this.DV - e : -e + }, t.prototype.isEven = function () { + return 0 == (this.t > 0 ? 1 & this[0] : this.s) + }, t.prototype.exp = function (e, i) { + if (e > 4294967295 || e < 1) return t.ONE; + var r = N(), n = N(), s = i.convert(this), o = F(e) - 1; + for (s.copyTo(r); --o >= 0;) if (i.sqrTo(r, n), (e & 1 << o) > 0) i.mulTo(n, s, r); else { + var h = r; + r = n, n = h + } + return i.revert(r) + }, t.prototype.chunkSize = function (t) { + return Math.floor(Math.LN2 * this.DB / Math.log(t)) + }, t.prototype.toRadix = function (t) { + if (null == t && (t = 10), 0 == this.signum() || t < 2 || t > 36) return "0"; + var e = this.chunkSize(t), i = Math.pow(t, e), r = C(i), n = N(), s = N(), o = ""; + for (this.divRemTo(r, n, s); n.signum() > 0;) o = (i + s.intValue()).toString(t).substr(1) + o, n.divRemTo(r, n, s); + return s.intValue().toString(t) + o + }, t.prototype.fromRadix = function (e, i) { + this.fromInt(0), null == i && (i = 10); + for (var r = this.chunkSize(i), n = Math.pow(i, r), s = !1, o = 0, h = 0, a = 0; a < e.length; ++a) { + var u = H(e, a); + u < 0 ? "-" == e.charAt(a) && 0 == this.signum() && (s = !0) : (h = i * h + u, ++o >= r && (this.dMultiply(n), this.dAddOffset(h, 0), o = 0, h = 0)) + } + o > 0 && (this.dMultiply(Math.pow(i, o)), this.dAddOffset(h, 0)), s && t.ZERO.subTo(this, this) + }, t.prototype.fromNumber = function (e, i, r) { + if ("number" == typeof i) if (e < 2) this.fromInt(1); else for (this.fromNumber(e, r), this.testBit(e - 1) || this.bitwiseTo(t.ONE.shiftLeft(e - 1), s, this), this.isEven() && this.dAddOffset(1, 0); !this.isProbablePrime(i);) this.dAddOffset(2, 0), this.bitLength() > e && this.subTo(t.ONE.shiftLeft(e - 1), this); else { + var n = [], o = 7 & e; + n.length = 1 + (e >> 3), i.nextBytes(n), o > 0 ? n[0] &= (1 << o) - 1 : n[0] = 0, this.fromString(n, 256) + } + }, t.prototype.bitwiseTo = function (t, e, i) { + var r, n, s = Math.min(t.t, this.t); + for (r = 0; r < s; ++r) i[r] = e(this[r], t[r]); + if (t.t < this.t) { + for (n = t.s & this.DM, r = s; r < this.t; ++r) i[r] = e(this[r], n); + i.t = this.t + } else { + for (n = this.s & this.DM, r = s; r < t.t; ++r) i[r] = e(n, t[r]); + i.t = t.t + } + i.s = e(this.s, t.s), i.clamp() + }, t.prototype.changeBit = function (e, i) { + var r = t.ONE.shiftLeft(e); + return this.bitwiseTo(r, i, r), r + }, t.prototype.addTo = function (t, e) { + for (var i = 0, r = 0, n = Math.min(t.t, this.t); i < n;) r += this[i] + t[i], e[i++] = r & this.DM, r >>= this.DB; + if (t.t < this.t) { + for (r += t.s; i < this.t;) r += this[i], e[i++] = r & this.DM, r >>= this.DB; + r += this.s + } else { + for (r += this.s; i < t.t;) r += t[i], e[i++] = r & this.DM, r >>= this.DB; + r += t.s + } + e.s = r < 0 ? -1 : 0, r > 0 ? e[i++] = r : r < -1 && (e[i++] = this.DV + r), e.t = i, e.clamp() + }, t.prototype.dMultiply = function (t) { + this[this.t] = this.am(0, t - 1, this, 0, 0, this.t), ++this.t, this.clamp() + }, t.prototype.dAddOffset = function (t, e) { + if (0 != t) { + for (; this.t <= e;) this[this.t++] = 0; + for (this[e] += t; this[e] >= this.DV;) this[e] -= this.DV, ++e >= this.t && (this[this.t++] = 0), ++this[e] + } + }, t.prototype.multiplyLowerTo = function (t, e, i) { + var r = Math.min(this.t + t.t, e); + for (i.s = 0, i.t = r; r > 0;) i[--r] = 0; + for (var n = i.t - this.t; r < n; ++r) i[r + this.t] = this.am(0, t[r], i, r, 0, this.t); + for (n = Math.min(t.t, e); r < n; ++r) this.am(0, t[r], i, r, 0, e - r); + i.clamp() + }, t.prototype.multiplyUpperTo = function (t, e, i) { + --e; + var r = i.t = this.t + t.t - e; + for (i.s = 0; --r >= 0;) i[r] = 0; + for (r = Math.max(e - this.t, 0); r < t.t; ++r) i[this.t + r - e] = this.am(e - r, t[r], i, 0, 0, this.t + r - e); + i.clamp(), i.drShiftTo(1, i) + }, t.prototype.modInt = function (t) { + if (t <= 0) return 0; + var e = this.DV % t, i = this.s < 0 ? t - 1 : 0; + if (this.t > 0) if (0 == e) i = this[0] % t; else for (var r = this.t - 1; r >= 0; --r) i = (e * i + this[r]) % t; + return i + }, t.prototype.millerRabin = function (e) { + var i = this.subtract(t.ONE), r = i.getLowestSetBit(); + if (r <= 0) return !1; + var n = i.shiftRight(r); + (e = e + 1 >> 1) > x.length && (e = x.length); + for (var s = N(), o = 0; o < e; ++o) { + s.fromInt(x[Math.floor(Math.random() * x.length)]); + var h = s.modPow(n, this); + if (0 != h.compareTo(t.ONE) && 0 != h.compareTo(i)) { + for (var a = 1; a++ < r && 0 != h.compareTo(i);) if (0 == (h = h.modPowInt(2, this)).compareTo(t.ONE)) return !1; + if (0 != h.compareTo(i)) return !1 + } + } + return !0 + }, t.prototype.square = function () { + var t = N(); + return this.squareTo(t), t + }, t.prototype.gcda = function (t, e) { + var i = this.s < 0 ? this.negate() : this.clone(), r = t.s < 0 ? t.negate() : t.clone(); + if (i.compareTo(r) < 0) { + var n = i; + i = r, r = n + } + var s = i.getLowestSetBit(), o = r.getLowestSetBit(); + if (o < 0) e(i); else { + s < o && (o = s), o > 0 && (i.rShiftTo(o, i), r.rShiftTo(o, r)); + var h = function () { + (s = i.getLowestSetBit()) > 0 && i.rShiftTo(s, i), (s = r.getLowestSetBit()) > 0 && r.rShiftTo(s, r), i.compareTo(r) >= 0 ? (i.subTo(r, i), i.rShiftTo(1, i)) : (r.subTo(i, r), r.rShiftTo(1, r)), i.signum() > 0 ? setTimeout(h, 0) : (o > 0 && r.lShiftTo(o, r), setTimeout((function () { + e(r) + }), 0)) + }; + setTimeout(h, 10) + } + }, t.prototype.fromNumberAsync = function (e, i, r, n) { + if ("number" == typeof i) if (e < 2) this.fromInt(1); else { + this.fromNumber(e, r), this.testBit(e - 1) || this.bitwiseTo(t.ONE.shiftLeft(e - 1), s, this), this.isEven() && this.dAddOffset(1, 0); + var o = this, h = function () { + o.dAddOffset(2, 0), o.bitLength() > e && o.subTo(t.ONE.shiftLeft(e - 1), o), o.isProbablePrime(i) ? setTimeout((function () { + n() + }), 0) : setTimeout(h, 0) + }; + setTimeout(h, 0) + } else { + var a = [], u = 7 & e; + a.length = 1 + (e >> 3), i.nextBytes(a), u > 0 ? a[0] &= (1 << u) - 1 : a[0] = 0, this.fromString(a, 256) + } + }, t + }(), O = function () { + function t() { + } + + return t.prototype.convert = function (t) { + return t + }, t.prototype.revert = function (t) { + return t + }, t.prototype.mulTo = function (t, e, i) { + t.multiplyTo(e, i) + }, t.prototype.sqrTo = function (t, e) { + t.squareTo(e) + }, t + }(), A = function () { + function t(t) { + this.m = t + } + + return t.prototype.convert = function (t) { + return t.s < 0 || t.compareTo(this.m) >= 0 ? t.mod(this.m) : t + }, t.prototype.revert = function (t) { + return t + }, t.prototype.reduce = function (t) { + t.divRemTo(this.m, null, t) + }, t.prototype.mulTo = function (t, e, i) { + t.multiplyTo(e, i), this.reduce(i) + }, t.prototype.sqrTo = function (t, e) { + t.squareTo(e), this.reduce(e) + }, t + }(), V = function () { + function t(t) { + this.m = t, this.mp = t.invDigit(), this.mpl = 32767 & this.mp, this.mph = this.mp >> 15, this.um = (1 << t.DB - 15) - 1, this.mt2 = 2 * t.t + } + + return t.prototype.convert = function (t) { + var e = N(); + return t.abs().dlShiftTo(this.m.t, e), e.divRemTo(this.m, null, e), t.s < 0 && e.compareTo(B.ZERO) > 0 && this.m.subTo(e, e), e + }, t.prototype.revert = function (t) { + var e = N(); + return t.copyTo(e), this.reduce(e), e + }, t.prototype.reduce = function (t) { + for (; t.t <= this.mt2;) t[t.t++] = 0; + for (var e = 0; e < this.m.t; ++e) { + var i = 32767 & t[e], + r = i * this.mpl + ((i * this.mph + (t[e] >> 15) * this.mpl & this.um) << 15) & t.DM; + for (t[i = e + this.m.t] += this.m.am(0, r, t, e, 0, this.m.t); t[i] >= t.DV;) t[i] -= t.DV, t[++i]++ + } + t.clamp(), t.drShiftTo(this.m.t, t), t.compareTo(this.m) >= 0 && t.subTo(this.m, t) + }, t.prototype.mulTo = function (t, e, i) { + t.multiplyTo(e, i), this.reduce(i) + }, t.prototype.sqrTo = function (t, e) { + t.squareTo(e), this.reduce(e) + }, t + }(), I = function () { + function t(t) { + this.m = t, this.r2 = N(), this.q3 = N(), B.ONE.dlShiftTo(2 * t.t, this.r2), this.mu = this.r2.divide(t) + } + + return t.prototype.convert = function (t) { + if (t.s < 0 || t.t > 2 * this.m.t) return t.mod(this.m); + if (t.compareTo(this.m) < 0) return t; + var e = N(); + return t.copyTo(e), this.reduce(e), e + }, t.prototype.revert = function (t) { + return t + }, t.prototype.reduce = function (t) { + for (t.drShiftTo(this.m.t - 1, this.r2), t.t > this.m.t + 1 && (t.t = this.m.t + 1, t.clamp()), this.mu.multiplyUpperTo(this.r2, this.m.t + 1, this.q3), this.m.multiplyLowerTo(this.q3, this.m.t + 1, this.r2); t.compareTo(this.r2) < 0;) t.dAddOffset(1, this.m.t + 1); + for (t.subTo(this.r2, t); t.compareTo(this.m) >= 0;) t.subTo(this.m, t) + }, t.prototype.mulTo = function (t, e, i) { + t.multiplyTo(e, i), this.reduce(i) + }, t.prototype.sqrTo = function (t, e) { + t.squareTo(e), this.reduce(e) + }, t + }(); + + function N() { + return new B(null) + } + + function P(t, e) { + return new B(t, e) + } + + var M = "undefined" != typeof navigator; + M && "Microsoft Internet Explorer" == navigator.appName ? (B.prototype.am = function (t, e, i, r, n, s) { + for (var o = 32767 & e, h = e >> 15; --s >= 0;) { + var a = 32767 & this[t], u = this[t++] >> 15, c = h * a + u * o; + n = ((a = o * a + ((32767 & c) << 15) + i[r] + (1073741823 & n)) >>> 30) + (c >>> 15) + h * u + (n >>> 30), i[r++] = 1073741823 & a + } + return n + }, S = 30) : M && "Netscape" != navigator.appName ? (B.prototype.am = function (t, e, i, r, n, s) { + for (; --s >= 0;) { + var o = e * this[t++] + i[r] + n; + n = Math.floor(o / 67108864), i[r++] = 67108863 & o + } + return n + }, S = 26) : (B.prototype.am = function (t, e, i, r, n, s) { + for (var o = 16383 & e, h = e >> 14; --s >= 0;) { + var a = 16383 & this[t], u = this[t++] >> 14, c = h * a + u * o; + n = ((a = o * a + ((16383 & c) << 14) + i[r] + n) >> 28) + (c >> 14) + h * u, i[r++] = 268435455 & a + } + return n + }, S = 28), B.prototype.DB = S, B.prototype.DM = (1 << S) - 1, B.prototype.DV = 1 << S, B.prototype.FV = Math.pow(2, 52), B.prototype.F1 = 52 - S, B.prototype.F2 = 2 * S - 52; + var j, q, L = []; + for (j = "0".charCodeAt(0), q = 0; q <= 9; ++q) L[j++] = q; + for (j = "a".charCodeAt(0), q = 10; q < 36; ++q) L[j++] = q; + for (j = "A".charCodeAt(0), q = 10; q < 36; ++q) L[j++] = q; + + function H(t, e) { + var i = L[t.charCodeAt(e)]; + return null == i ? -1 : i + } + + function C(t) { + var e = N(); + return e.fromInt(t), e + } + + function F(t) { + var e, i = 1; + return 0 != (e = t >>> 16) && (t = e, i += 16), 0 != (e = t >> 8) && (t = e, i += 8), 0 != (e = t >> 4) && (t = e, i += 4), 0 != (e = t >> 2) && (t = e, i += 2), 0 != (e = t >> 1) && (t = e, i += 1), i + } + + B.ZERO = C(0), B.ONE = C(1); + var U, K, k = function () { + function t() { + this.i = 0, this.j = 0, this.S = [] + } + + return t.prototype.init = function (t) { + var e, i, r; + for (e = 0; e < 256; ++e) this.S[e] = e; + for (i = 0, e = 0; e < 256; ++e) i = i + this.S[e] + t[e % t.length] & 255, r = this.S[e], this.S[e] = this.S[i], this.S[i] = r; + this.i = 0, this.j = 0 + }, t.prototype.next = function () { + var t; + return this.i = this.i + 1 & 255, this.j = this.j + this.S[this.i] & 255, t = this.S[this.i], this.S[this.i] = this.S[this.j], this.S[this.j] = t, this.S[t + this.S[this.i] & 255] + }, t + }(), _ = null; + if (null == _) { + _ = [], K = 0; + var z = void 0; + if (window.crypto && window.crypto.getRandomValues) { + var Z = new Uint32Array(256); + for (window.crypto.getRandomValues(Z), z = 0; z < Z.length; ++z) _[K++] = 255 & Z[z] + } + var G = 0, $ = function (t) { + if ((G = G || 0) >= 256 || K >= 256) window.removeEventListener ? window.removeEventListener("mousemove", $, !1) : window.detachEvent && window.detachEvent("onmousemove", $); else try { + var e = t.x + t.y; + _[K++] = 255 & e, G += 1 + } catch (t) { + } + }; + window.addEventListener ? window.addEventListener("mousemove", $, !1) : window.attachEvent && window.attachEvent("onmousemove", $) + } + + function Y() { + if (null == U) { + for (U = new k; K < 256;) { + var t = Math.floor(65536 * Math.random()); + _[K++] = 255 & t + } + for (U.init(_), K = 0; K < _.length; ++K) _[K] = 0; + K = 0 + } + return U.next() + } + + var J = function () { + function t() { + } + + return t.prototype.nextBytes = function (t) { + for (var e = 0; e < t.length; ++e) t[e] = Y() + }, t + }(), X = function () { + function t() { + this.n = null, this.e = 0, this.d = null, this.p = null, this.q = null, this.dmp1 = null, this.dmq1 = null, this.coeff = null + } + + return t.prototype.doPublic = function (t) { + return t.modPowInt(this.e, this.n) + }, t.prototype.doPrivate = function (t) { + if (null == this.p || null == this.q) return t.modPow(this.d, this.n); + for (var e = t.mod(this.p).modPow(this.dmp1, this.p), i = t.mod(this.q).modPow(this.dmq1, this.q); e.compareTo(i) < 0;) e = e.add(this.p); + return e.subtract(i).multiply(this.coeff).mod(this.p).multiply(this.q).add(i) + }, t.prototype.setPublic = function (t, e) { + null != t && null != e && t.length > 0 && e.length > 0 ? (this.n = P(t, 16), this.e = parseInt(e, 16)) : console.error("Invalid RSA public key") + }, t.prototype.encrypt = function (t) { + var e = function (t, e) { + if (e < t.length + 11) return console.error("Message too long for RSA"), null; + for (var i = [], r = t.length - 1; r >= 0 && e > 0;) { + var n = t.charCodeAt(r--); + n < 128 ? i[--e] = n : n > 127 && n < 2048 ? (i[--e] = 63 & n | 128, i[--e] = n >> 6 | 192) : (i[--e] = 63 & n | 128, i[--e] = n >> 6 & 63 | 128, i[--e] = n >> 12 | 224) + } + i[--e] = 0; + for (var s = new J, o = []; e > 2;) { + for (o[0] = 0; 0 == o[0];) s.nextBytes(o); + i[--e] = o[0] + } + return i[--e] = 2, i[--e] = 0, new B(i) + }(t, this.n.bitLength() + 7 >> 3); + if (null == e) return null; + var i = this.doPublic(e); + if (null == i) return null; + var r = i.toString(16); + return 0 == (1 & r.length) ? r : "0" + r + }, t.prototype.setPrivate = function (t, e, i) { + null != t && null != e && t.length > 0 && e.length > 0 ? (this.n = P(t, 16), this.e = parseInt(e, 16), this.d = P(i, 16)) : console.error("Invalid RSA private key") + }, t.prototype.setPrivateEx = function (t, e, i, r, n, s, o, h) { + null != t && null != e && t.length > 0 && e.length > 0 ? (this.n = P(t, 16), this.e = parseInt(e, 16), this.d = P(i, 16), this.p = P(r, 16), this.q = P(n, 16), this.dmp1 = P(s, 16), this.dmq1 = P(o, 16), this.coeff = P(h, 16)) : console.error("Invalid RSA private key") + }, t.prototype.generate = function (t, e) { + var i = new J, r = t >> 1; + this.e = parseInt(e, 16); + for (var n = new B(e, 16); ;) { + for (; this.p = new B(t - r, 1, i), 0 != this.p.subtract(B.ONE).gcd(n).compareTo(B.ONE) || !this.p.isProbablePrime(10);) ; + for (; this.q = new B(r, 1, i), 0 != this.q.subtract(B.ONE).gcd(n).compareTo(B.ONE) || !this.q.isProbablePrime(10);) ; + if (this.p.compareTo(this.q) <= 0) { + var s = this.p; + this.p = this.q, this.q = s + } + var o = this.p.subtract(B.ONE), h = this.q.subtract(B.ONE), a = o.multiply(h); + if (0 == a.gcd(n).compareTo(B.ONE)) { + this.n = this.p.multiply(this.q), this.d = n.modInverse(a), this.dmp1 = this.d.mod(o), this.dmq1 = this.d.mod(h), this.coeff = this.q.modInverse(this.p); + break + } + } + }, t.prototype.decrypt = function (t) { + var e = P(t, 16), i = this.doPrivate(e); + return null == i ? null : function (t, e) { + for (var i = t.toByteArray(), r = 0; r < i.length && 0 == i[r];) ++r; + if (i.length - r != e - 1 || 2 != i[r]) return null; + for (++r; 0 != i[r];) if (++r >= i.length) return null; + for (var n = ""; ++r < i.length;) { + var s = 255 & i[r]; + s < 128 ? n += String.fromCharCode(s) : s > 191 && s < 224 ? (n += String.fromCharCode((31 & s) << 6 | 63 & i[r + 1]), ++r) : (n += String.fromCharCode((15 & s) << 12 | (63 & i[r + 1]) << 6 | 63 & i[r + 2]), r += 2) + } + return n + }(i, this.n.bitLength() + 7 >> 3) + }, t.prototype.generateAsync = function (t, e, i) { + var r = new J, n = t >> 1; + this.e = parseInt(e, 16); + var s = new B(e, 16), o = this, h = function () { + var e = function () { + if (o.p.compareTo(o.q) <= 0) { + var t = o.p; + o.p = o.q, o.q = t + } + var e = o.p.subtract(B.ONE), r = o.q.subtract(B.ONE), n = e.multiply(r); + 0 == n.gcd(s).compareTo(B.ONE) ? (o.n = o.p.multiply(o.q), o.d = s.modInverse(n), o.dmp1 = o.d.mod(e), o.dmq1 = o.d.mod(r), o.coeff = o.q.modInverse(o.p), setTimeout((function () { + i() + }), 0)) : setTimeout(h, 0) + }, a = function () { + o.q = N(), o.q.fromNumberAsync(n, 1, r, (function () { + o.q.subtract(B.ONE).gcda(s, (function (t) { + 0 == t.compareTo(B.ONE) && o.q.isProbablePrime(10) ? setTimeout(e, 0) : setTimeout(a, 0) + })) + })) + }, u = function () { + o.p = N(), o.p.fromNumberAsync(t - n, 1, r, (function () { + o.p.subtract(B.ONE).gcda(s, (function (t) { + 0 == t.compareTo(B.ONE) && o.p.isProbablePrime(10) ? setTimeout(a, 0) : setTimeout(u, 0) + })) + })) + }; + setTimeout(u, 0) + }; + setTimeout(h, 0) + }, t.prototype.sign = function (t, e, i) { + var r = function (t, e) { + if (e < t.length + 22) return console.error("Message too long for RSA"), null; + for (var i = e - t.length - 6, r = "", n = 0; n < i; n += 2) r += "ff"; + return P("0001" + r + "00" + t, 16) + }((Q[i] || "") + e(t).toString(), this.n.bitLength() / 4); + if (null == r) return null; + var n = this.doPrivate(r); + if (null == n) return null; + var s = n.toString(16); + return 0 == (1 & s.length) ? s : "0" + s + }, t.prototype.verify = function (t, e, i) { + var r = P(e, 16), n = this.doPublic(r); + return null == n ? null : function (t) { + for (var e in Q) if (Q.hasOwnProperty(e)) { + var i = Q[e], r = i.length; + if (t.substr(0, r) == i) return t.substr(r) + } + return t + }(n.toString(16).replace(/^1f+00/, "")) == i(t).toString() + }, t + }(), Q = { + md2: "3020300c06082a864886f70d020205000410", + md5: "3020300c06082a864886f70d020505000410", + sha1: "3021300906052b0e03021a05000414", + sha224: "302d300d06096086480165030402040500041c", + sha256: "3031300d060960864801650304020105000420", + sha384: "3041300d060960864801650304020205000430", + sha512: "3051300d060960864801650304020305000440", + ripemd160: "3021300906052b2403020105000414" + }, W = {}; + W.lang = { + extend: function (t, e, i) { + if (!e || !t) throw new Error("YAHOO.lang.extend failed, please check that all dependencies are included."); + var r = function () { + }; + if (r.prototype = e.prototype, t.prototype = new r, t.prototype.constructor = t, t.superclass = e.prototype, e.prototype.constructor == Object.prototype.constructor && (e.prototype.constructor = e), i) { + var n; + for (n in i) t.prototype[n] = i[n]; + var s = function () { + }, o = ["toString", "valueOf"]; + try { + /MSIE/.test(navigator.userAgent) && (s = function (t, e) { + for (n = 0; n < o.length; n += 1) { + var i = o[n], r = e[i]; + "function" == typeof r && r != Object.prototype[i] && (t[i] = r) + } + }) + } catch (t) { + } + s(t.prototype, i) + } + } + }; + var tt = {}; + void 0 !== tt.asn1 && tt.asn1 || (tt.asn1 = {}), tt.asn1.ASN1Util = new function () { + this.integerToByteHex = function (t) { + var e = t.toString(16); + return e.length % 2 == 1 && (e = "0" + e), e + }, this.bigIntToMinTwosComplementsHex = function (t) { + var e = t.toString(16); + if ("-" != e.substr(0, 1)) e.length % 2 == 1 ? e = "0" + e : e.match(/^[0-7]/) || (e = "00" + e); else { + var i = e.substr(1).length; + i % 2 == 1 ? i += 1 : e.match(/^[0-7]/) || (i += 2); + for (var r = "", n = 0; n < i; n++) r += "f"; + e = new B(r, 16).xor(t).add(B.ONE).toString(16).replace(/^-/, "") + } + return e + }, this.getPEMStringFromHex = function (t, e) { + return hextopem(t, e) + }, this.newObject = function (t) { + var e = tt.asn1, i = e.DERBoolean, r = e.DERInteger, n = e.DERBitString, s = e.DEROctetString, + o = e.DERNull, h = e.DERObjectIdentifier, a = e.DEREnumerated, u = e.DERUTF8String, + c = e.DERNumericString, f = e.DERPrintableString, l = e.DERTeletexString, + p = e.DERIA5String, g = e.DERUTCTime, d = e.DERGeneralizedTime, v = e.DERSequence, + m = e.DERSet, y = e.DERTaggedObject, b = e.ASN1Util.newObject, T = Object.keys(t); + if (1 != T.length) throw"key of param shall be only one."; + var S = T[0]; + if (-1 == ":bool:int:bitstr:octstr:null:oid:enum:utf8str:numstr:prnstr:telstr:ia5str:utctime:gentime:seq:set:tag:".indexOf(":" + S + ":")) throw"undefined key: " + S; + if ("bool" == S) return new i(t[S]); + if ("int" == S) return new r(t[S]); + if ("bitstr" == S) return new n(t[S]); + if ("octstr" == S) return new s(t[S]); + if ("null" == S) return new o(t[S]); + if ("oid" == S) return new h(t[S]); + if ("enum" == S) return new a(t[S]); + if ("utf8str" == S) return new u(t[S]); + if ("numstr" == S) return new c(t[S]); + if ("prnstr" == S) return new f(t[S]); + if ("telstr" == S) return new l(t[S]); + if ("ia5str" == S) return new p(t[S]); + if ("utctime" == S) return new g(t[S]); + if ("gentime" == S) return new d(t[S]); + if ("seq" == S) { + for (var E = t[S], w = [], D = 0; D < E.length; D++) { + var x = b(E[D]); + w.push(x) + } + return new v({array: w}) + } + if ("set" == S) { + for (E = t[S], w = [], D = 0; D < E.length; D++) x = b(E[D]), w.push(x); + return new m({array: w}) + } + if ("tag" == S) { + var R = t[S]; + if ("[object Array]" === Object.prototype.toString.call(R) && 3 == R.length) { + var B = b(R[2]); + return new y({tag: R[0], explicit: R[1], obj: B}) + } + var O = {}; + if (void 0 !== R.explicit && (O.explicit = R.explicit), void 0 !== R.tag && (O.tag = R.tag), void 0 === R.obj) throw"obj shall be specified for 'tag'."; + return O.obj = b(R.obj), new y(O) + } + }, this.jsonToASN1HEX = function (t) { + return this.newObject(t).getEncodedHex() + } + }, tt.asn1.ASN1Util.oidHexToInt = function (t) { + for (var e = "", i = parseInt(t.substr(0, 2), 16), r = (e = Math.floor(i / 40) + "." + i % 40, ""), n = 2; n < t.length; n += 2) { + var s = ("00000000" + parseInt(t.substr(n, 2), 16).toString(2)).slice(-8); + r += s.substr(1, 7), "0" == s.substr(0, 1) && (e = e + "." + new B(r, 2).toString(10), r = "") + } + return e + }, tt.asn1.ASN1Util.oidIntToHex = function (t) { + var e = function (t) { + var e = t.toString(16); + return 1 == e.length && (e = "0" + e), e + }, i = function (t) { + var i = "", r = new B(t, 10).toString(2), n = 7 - r.length % 7; + 7 == n && (n = 0); + for (var s = "", o = 0; o < n; o++) s += "0"; + for (r = s + r, o = 0; o < r.length - 1; o += 7) { + var h = r.substr(o, 7); + o != r.length - 7 && (h = "1" + h), i += e(parseInt(h, 2)) + } + return i + }; + if (!t.match(/^[0-9.]+$/)) throw"malformed oid string: " + t; + var r = "", n = t.split("."), s = 40 * parseInt(n[0]) + parseInt(n[1]); + r += e(s), n.splice(0, 2); + for (var o = 0; o < n.length; o++) r += i(n[o]); + return r + }, tt.asn1.ASN1Object = function () { + this.getLengthHexFromValue = function () { + if (void 0 === this.hV || null == this.hV) throw"this.hV is null or undefined."; + if (this.hV.length % 2 == 1) throw"value hex must be even length: n=" + "".length + ",v=" + this.hV; + var t = this.hV.length / 2, e = t.toString(16); + if (e.length % 2 == 1 && (e = "0" + e), t < 128) return e; + var i = e.length / 2; + if (i > 15) throw"ASN.1 length too long to represent by 8x: n = " + t.toString(16); + return (128 + i).toString(16) + e + }, this.getEncodedHex = function () { + return (null == this.hTLV || this.isModified) && (this.hV = this.getFreshValueHex(), this.hL = this.getLengthHexFromValue(), this.hTLV = this.hT + this.hL + this.hV, this.isModified = !1), this.hTLV + }, this.getValueHex = function () { + return this.getEncodedHex(), this.hV + }, this.getFreshValueHex = function () { + return "" + } + }, tt.asn1.DERAbstractString = function (t) { + tt.asn1.DERAbstractString.superclass.constructor.call(this), this.getString = function () { + return this.s + }, this.setString = function (t) { + this.hTLV = null, this.isModified = !0, this.s = t, this.hV = stohex(this.s) + }, this.setStringHex = function (t) { + this.hTLV = null, this.isModified = !0, this.s = null, this.hV = t + }, this.getFreshValueHex = function () { + return this.hV + }, void 0 !== t && ("string" == typeof t ? this.setString(t) : void 0 !== t.str ? this.setString(t.str) : void 0 !== t.hex && this.setStringHex(t.hex)) + }, W.lang.extend(tt.asn1.DERAbstractString, tt.asn1.ASN1Object), tt.asn1.DERAbstractTime = function (t) { + tt.asn1.DERAbstractTime.superclass.constructor.call(this), this.localDateToUTC = function (t) { + return utc = t.getTime() + 6e4 * t.getTimezoneOffset(), new Date(utc) + }, this.formatDate = function (t, e, i) { + var r = this.zeroPadding, n = this.localDateToUTC(t), s = String(n.getFullYear()); + "utc" == e && (s = s.substr(2, 2)); + var o = s + r(String(n.getMonth() + 1), 2) + r(String(n.getDate()), 2) + r(String(n.getHours()), 2) + r(String(n.getMinutes()), 2) + r(String(n.getSeconds()), 2); + if (!0 === i) { + var h = n.getMilliseconds(); + if (0 != h) { + var a = r(String(h), 3); + o = o + "." + (a = a.replace(/[0]+$/, "")) + } + } + return o + "Z" + }, this.zeroPadding = function (t, e) { + return t.length >= e ? t : new Array(e - t.length + 1).join("0") + t + }, this.getString = function () { + return this.s + }, this.setString = function (t) { + this.hTLV = null, this.isModified = !0, this.s = t, this.hV = stohex(t) + }, this.setByDateValue = function (t, e, i, r, n, s) { + var o = new Date(Date.UTC(t, e - 1, i, r, n, s, 0)); + this.setByDate(o) + }, this.getFreshValueHex = function () { + return this.hV + } + }, W.lang.extend(tt.asn1.DERAbstractTime, tt.asn1.ASN1Object), tt.asn1.DERAbstractStructured = function (t) { + tt.asn1.DERAbstractString.superclass.constructor.call(this), this.setByASN1ObjectArray = function (t) { + this.hTLV = null, this.isModified = !0, this.asn1Array = t + }, this.appendASN1Object = function (t) { + this.hTLV = null, this.isModified = !0, this.asn1Array.push(t) + }, this.asn1Array = new Array, void 0 !== t && void 0 !== t.array && (this.asn1Array = t.array) + }, W.lang.extend(tt.asn1.DERAbstractStructured, tt.asn1.ASN1Object), tt.asn1.DERBoolean = function () { + tt.asn1.DERBoolean.superclass.constructor.call(this), this.hT = "01", this.hTLV = "0101ff" + }, W.lang.extend(tt.asn1.DERBoolean, tt.asn1.ASN1Object), tt.asn1.DERInteger = function (t) { + tt.asn1.DERInteger.superclass.constructor.call(this), this.hT = "02", this.setByBigInteger = function (t) { + this.hTLV = null, this.isModified = !0, this.hV = tt.asn1.ASN1Util.bigIntToMinTwosComplementsHex(t) + }, this.setByInteger = function (t) { + var e = new B(String(t), 10); + this.setByBigInteger(e) + }, this.setValueHex = function (t) { + this.hV = t + }, this.getFreshValueHex = function () { + return this.hV + }, void 0 !== t && (void 0 !== t.bigint ? this.setByBigInteger(t.bigint) : void 0 !== t.int ? this.setByInteger(t.int) : "number" == typeof t ? this.setByInteger(t) : void 0 !== t.hex && this.setValueHex(t.hex)) + }, W.lang.extend(tt.asn1.DERInteger, tt.asn1.ASN1Object), tt.asn1.DERBitString = function (t) { + if (void 0 !== t && void 0 !== t.obj) { + var e = tt.asn1.ASN1Util.newObject(t.obj); + t.hex = "00" + e.getEncodedHex() + } + tt.asn1.DERBitString.superclass.constructor.call(this), this.hT = "03", this.setHexValueIncludingUnusedBits = function (t) { + this.hTLV = null, this.isModified = !0, this.hV = t + }, this.setUnusedBitsAndHexValue = function (t, e) { + if (t < 0 || 7 < t) throw"unused bits shall be from 0 to 7: u = " + t; + var i = "0" + t; + this.hTLV = null, this.isModified = !0, this.hV = i + e + }, this.setByBinaryString = function (t) { + var e = 8 - (t = t.replace(/0+$/, "")).length % 8; + 8 == e && (e = 0); + for (var i = 0; i <= e; i++) t += "0"; + var r = ""; + for (i = 0; i < t.length - 1; i += 8) { + var n = t.substr(i, 8), s = parseInt(n, 2).toString(16); + 1 == s.length && (s = "0" + s), r += s + } + this.hTLV = null, this.isModified = !0, this.hV = "0" + e + r + }, this.setByBooleanArray = function (t) { + for (var e = "", i = 0; i < t.length; i++) 1 == t[i] ? e += "1" : e += "0"; + this.setByBinaryString(e) + }, this.newFalseArray = function (t) { + for (var e = new Array(t), i = 0; i < t; i++) e[i] = !1; + return e + }, this.getFreshValueHex = function () { + return this.hV + }, void 0 !== t && ("string" == typeof t && t.toLowerCase().match(/^[0-9a-f]+$/) ? this.setHexValueIncludingUnusedBits(t) : void 0 !== t.hex ? this.setHexValueIncludingUnusedBits(t.hex) : void 0 !== t.bin ? this.setByBinaryString(t.bin) : void 0 !== t.array && this.setByBooleanArray(t.array)) + }, W.lang.extend(tt.asn1.DERBitString, tt.asn1.ASN1Object), tt.asn1.DEROctetString = function (t) { + if (void 0 !== t && void 0 !== t.obj) { + var e = tt.asn1.ASN1Util.newObject(t.obj); + t.hex = e.getEncodedHex() + } + tt.asn1.DEROctetString.superclass.constructor.call(this, t), this.hT = "04" + }, W.lang.extend(tt.asn1.DEROctetString, tt.asn1.DERAbstractString), tt.asn1.DERNull = function () { + tt.asn1.DERNull.superclass.constructor.call(this), this.hT = "05", this.hTLV = "0500" + }, W.lang.extend(tt.asn1.DERNull, tt.asn1.ASN1Object), tt.asn1.DERObjectIdentifier = function (t) { + var e = function (t) { + var e = t.toString(16); + return 1 == e.length && (e = "0" + e), e + }, i = function (t) { + var i = "", r = new B(t, 10).toString(2), n = 7 - r.length % 7; + 7 == n && (n = 0); + for (var s = "", o = 0; o < n; o++) s += "0"; + for (r = s + r, o = 0; o < r.length - 1; o += 7) { + var h = r.substr(o, 7); + o != r.length - 7 && (h = "1" + h), i += e(parseInt(h, 2)) + } + return i + }; + tt.asn1.DERObjectIdentifier.superclass.constructor.call(this), this.hT = "06", this.setValueHex = function (t) { + this.hTLV = null, this.isModified = !0, this.s = null, this.hV = t + }, this.setValueOidString = function (t) { + if (!t.match(/^[0-9.]+$/)) throw"malformed oid string: " + t; + var r = "", n = t.split("."), s = 40 * parseInt(n[0]) + parseInt(n[1]); + r += e(s), n.splice(0, 2); + for (var o = 0; o < n.length; o++) r += i(n[o]); + this.hTLV = null, this.isModified = !0, this.s = null, this.hV = r + }, this.setValueName = function (t) { + var e = tt.asn1.x509.OID.name2oid(t); + if ("" === e) throw"DERObjectIdentifier oidName undefined: " + t; + this.setValueOidString(e) + }, this.getFreshValueHex = function () { + return this.hV + }, void 0 !== t && ("string" == typeof t ? t.match(/^[0-2].[0-9.]+$/) ? this.setValueOidString(t) : this.setValueName(t) : void 0 !== t.oid ? this.setValueOidString(t.oid) : void 0 !== t.hex ? this.setValueHex(t.hex) : void 0 !== t.name && this.setValueName(t.name)) + }, W.lang.extend(tt.asn1.DERObjectIdentifier, tt.asn1.ASN1Object), tt.asn1.DEREnumerated = function (t) { + tt.asn1.DEREnumerated.superclass.constructor.call(this), this.hT = "0a", this.setByBigInteger = function (t) { + this.hTLV = null, this.isModified = !0, this.hV = tt.asn1.ASN1Util.bigIntToMinTwosComplementsHex(t) + }, this.setByInteger = function (t) { + var e = new B(String(t), 10); + this.setByBigInteger(e) + }, this.setValueHex = function (t) { + this.hV = t + }, this.getFreshValueHex = function () { + return this.hV + }, void 0 !== t && (void 0 !== t.int ? this.setByInteger(t.int) : "number" == typeof t ? this.setByInteger(t) : void 0 !== t.hex && this.setValueHex(t.hex)) + }, W.lang.extend(tt.asn1.DEREnumerated, tt.asn1.ASN1Object), tt.asn1.DERUTF8String = function (t) { + tt.asn1.DERUTF8String.superclass.constructor.call(this, t), this.hT = "0c" + }, W.lang.extend(tt.asn1.DERUTF8String, tt.asn1.DERAbstractString), tt.asn1.DERNumericString = function (t) { + tt.asn1.DERNumericString.superclass.constructor.call(this, t), this.hT = "12" + }, W.lang.extend(tt.asn1.DERNumericString, tt.asn1.DERAbstractString), tt.asn1.DERPrintableString = function (t) { + tt.asn1.DERPrintableString.superclass.constructor.call(this, t), this.hT = "13" + }, W.lang.extend(tt.asn1.DERPrintableString, tt.asn1.DERAbstractString), tt.asn1.DERTeletexString = function (t) { + tt.asn1.DERTeletexString.superclass.constructor.call(this, t), this.hT = "14" + }, W.lang.extend(tt.asn1.DERTeletexString, tt.asn1.DERAbstractString), tt.asn1.DERIA5String = function (t) { + tt.asn1.DERIA5String.superclass.constructor.call(this, t), this.hT = "16" + }, W.lang.extend(tt.asn1.DERIA5String, tt.asn1.DERAbstractString), tt.asn1.DERUTCTime = function (t) { + tt.asn1.DERUTCTime.superclass.constructor.call(this, t), this.hT = "17", this.setByDate = function (t) { + this.hTLV = null, this.isModified = !0, this.date = t, this.s = this.formatDate(this.date, "utc"), this.hV = stohex(this.s) + }, this.getFreshValueHex = function () { + return void 0 === this.date && void 0 === this.s && (this.date = new Date, this.s = this.formatDate(this.date, "utc"), this.hV = stohex(this.s)), this.hV + }, void 0 !== t && (void 0 !== t.str ? this.setString(t.str) : "string" == typeof t && t.match(/^[0-9]{12}Z$/) ? this.setString(t) : void 0 !== t.hex ? this.setStringHex(t.hex) : void 0 !== t.date && this.setByDate(t.date)) + }, W.lang.extend(tt.asn1.DERUTCTime, tt.asn1.DERAbstractTime), tt.asn1.DERGeneralizedTime = function (t) { + tt.asn1.DERGeneralizedTime.superclass.constructor.call(this, t), this.hT = "18", this.withMillis = !1, this.setByDate = function (t) { + this.hTLV = null, this.isModified = !0, this.date = t, this.s = this.formatDate(this.date, "gen", this.withMillis), this.hV = stohex(this.s) + }, this.getFreshValueHex = function () { + return void 0 === this.date && void 0 === this.s && (this.date = new Date, this.s = this.formatDate(this.date, "gen", this.withMillis), this.hV = stohex(this.s)), this.hV + }, void 0 !== t && (void 0 !== t.str ? this.setString(t.str) : "string" == typeof t && t.match(/^[0-9]{14}Z$/) ? this.setString(t) : void 0 !== t.hex ? this.setStringHex(t.hex) : void 0 !== t.date && this.setByDate(t.date), !0 === t.millis && (this.withMillis = !0)) + }, W.lang.extend(tt.asn1.DERGeneralizedTime, tt.asn1.DERAbstractTime), tt.asn1.DERSequence = function (t) { + tt.asn1.DERSequence.superclass.constructor.call(this, t), this.hT = "30", this.getFreshValueHex = function () { + for (var t = "", e = 0; e < this.asn1Array.length; e++) t += this.asn1Array[e].getEncodedHex(); + return this.hV = t, this.hV + } + }, W.lang.extend(tt.asn1.DERSequence, tt.asn1.DERAbstractStructured), tt.asn1.DERSet = function (t) { + tt.asn1.DERSet.superclass.constructor.call(this, t), this.hT = "31", this.sortFlag = !0, this.getFreshValueHex = function () { + for (var t = new Array, e = 0; e < this.asn1Array.length; e++) { + var i = this.asn1Array[e]; + t.push(i.getEncodedHex()) + } + return 1 == this.sortFlag && t.sort(), this.hV = t.join(""), this.hV + }, void 0 !== t && void 0 !== t.sortflag && 0 == t.sortflag && (this.sortFlag = !1) + }, W.lang.extend(tt.asn1.DERSet, tt.asn1.DERAbstractStructured), tt.asn1.DERTaggedObject = function (t) { + tt.asn1.DERTaggedObject.superclass.constructor.call(this), this.hT = "a0", this.hV = "", this.isExplicit = !0, this.asn1Object = null, this.setASN1Object = function (t, e, i) { + this.hT = e, this.isExplicit = t, this.asn1Object = i, this.isExplicit ? (this.hV = this.asn1Object.getEncodedHex(), this.hTLV = null, this.isModified = !0) : (this.hV = null, this.hTLV = i.getEncodedHex(), this.hTLV = this.hTLV.replace(/^../, e), this.isModified = !1) + }, this.getFreshValueHex = function () { + return this.hV + }, void 0 !== t && (void 0 !== t.tag && (this.hT = t.tag), void 0 !== t.explicit && (this.isExplicit = t.explicit), void 0 !== t.obj && (this.asn1Object = t.obj, this.setASN1Object(this.isExplicit, this.hT, this.asn1Object))) + }, W.lang.extend(tt.asn1.DERTaggedObject, tt.asn1.ASN1Object); + var et, it = (et = function (t, e) { + return (et = Object.setPrototypeOf || {__proto__: []} instanceof Array && function (t, e) { + t.__proto__ = e + } || function (t, e) { + for (var i in e) Object.prototype.hasOwnProperty.call(e, i) && (t[i] = e[i]) + })(t, e) + }, function (t, e) { + function i() { + this.constructor = t + } + + et(t, e), t.prototype = null === e ? Object.create(e) : (i.prototype = e.prototype, new i) + }), rt = function (t) { + function e(i) { + var r = t.call(this) || this; + return i && ("string" == typeof i ? r.parseKey(i) : (e.hasPrivateKeyProperty(i) || e.hasPublicKeyProperty(i)) && r.parsePropertiesFrom(i)), r + } + + return it(e, t), e.prototype.parseKey = function (t) { + try { + var e = 0, i = 0, r = /^\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\s*)+$/.test(t) ? function (t) { + var e; + if (void 0 === c) { + var i = "0123456789ABCDEF", r = " \f\n\r\t \u2028\u2029"; + for (c = {}, e = 0; e < 16; ++e) c[i.charAt(e)] = e; + for (i = i.toLowerCase(), e = 10; e < 16; ++e) c[i.charAt(e)] = e; + for (e = 0; e < r.length; ++e) c[r.charAt(e)] = -1 + } + var n = [], s = 0, o = 0; + for (e = 0; e < t.length; ++e) { + var h = t.charAt(e); + if ("=" == h) break; + if (-1 != (h = c[h])) { + if (void 0 === h) throw new Error("Illegal character at offset " + e); + s |= h, ++o >= 2 ? (n[n.length] = s, s = 0, o = 0) : s <<= 4 + } + } + if (o) throw new Error("Hex encoding incomplete: 4 bits missing"); + return n + }(t) : d.unarmor(t), n = w.decode(r); + if (3 === n.sub.length && (n = n.sub[2].sub[0]), 9 === n.sub.length) { + e = n.sub[1].getHexStringValue(), this.n = P(e, 16), i = n.sub[2].getHexStringValue(), this.e = parseInt(i, 16); + var s = n.sub[3].getHexStringValue(); + this.d = P(s, 16); + var o = n.sub[4].getHexStringValue(); + this.p = P(o, 16); + var h = n.sub[5].getHexStringValue(); + this.q = P(h, 16); + var a = n.sub[6].getHexStringValue(); + this.dmp1 = P(a, 16); + var u = n.sub[7].getHexStringValue(); + this.dmq1 = P(u, 16); + var f = n.sub[8].getHexStringValue(); + this.coeff = P(f, 16) + } else { + if (2 !== n.sub.length) return !1; + var l = n.sub[1].sub[0]; + e = l.sub[0].getHexStringValue(), this.n = P(e, 16), i = l.sub[1].getHexStringValue(), this.e = parseInt(i, 16) + } + return !0 + } catch (t) { + return !1 + } + }, e.prototype.getPrivateBaseKey = function () { + var t = {array: [new tt.asn1.DERInteger({int: 0}), new tt.asn1.DERInteger({bigint: this.n}), new tt.asn1.DERInteger({int: this.e}), new tt.asn1.DERInteger({bigint: this.d}), new tt.asn1.DERInteger({bigint: this.p}), new tt.asn1.DERInteger({bigint: this.q}), new tt.asn1.DERInteger({bigint: this.dmp1}), new tt.asn1.DERInteger({bigint: this.dmq1}), new tt.asn1.DERInteger({bigint: this.coeff})]}; + return new tt.asn1.DERSequence(t).getEncodedHex() + }, e.prototype.getPrivateBaseKeyB64 = function () { + return l(this.getPrivateBaseKey()) + }, e.prototype.getPublicBaseKey = function () { + var t = new tt.asn1.DERSequence({array: [new tt.asn1.DERObjectIdentifier({oid: "1.2.840.113549.1.1.1"}), new tt.asn1.DERNull]}), + e = new tt.asn1.DERSequence({array: [new tt.asn1.DERInteger({bigint: this.n}), new tt.asn1.DERInteger({int: this.e})]}), + i = new tt.asn1.DERBitString({hex: "00" + e.getEncodedHex()}); + return new tt.asn1.DERSequence({array: [t, i]}).getEncodedHex() + }, e.prototype.getPublicBaseKeyB64 = function () { + return l(this.getPublicBaseKey()) + }, e.wordwrap = function (t, e) { + if (!t) return t; + var i = "(.{1," + (e = e || 64) + "})( +|$\n?)|(.{1," + e + "})"; + return t.match(RegExp(i, "g")).join("\n") + }, e.prototype.getPrivateKey = function () { + var t = "-----BEGIN RSA PRIVATE KEY-----\n"; + return (t += e.wordwrap(this.getPrivateBaseKeyB64()) + "\n") + "-----END RSA PRIVATE KEY-----" + }, e.prototype.getPublicKey = function () { + var t = "-----BEGIN PUBLIC KEY-----\n"; + return (t += e.wordwrap(this.getPublicBaseKeyB64()) + "\n") + "-----END PUBLIC KEY-----" + }, e.hasPublicKeyProperty = function (t) { + return (t = t || {}).hasOwnProperty("n") && t.hasOwnProperty("e") + }, e.hasPrivateKeyProperty = function (t) { + return (t = t || {}).hasOwnProperty("n") && t.hasOwnProperty("e") && t.hasOwnProperty("d") && t.hasOwnProperty("p") && t.hasOwnProperty("q") && t.hasOwnProperty("dmp1") && t.hasOwnProperty("dmq1") && t.hasOwnProperty("coeff") + }, e.prototype.parsePropertiesFrom = function (t) { + this.n = t.n, this.e = t.e, t.hasOwnProperty("d") && (this.d = t.d, this.p = t.p, this.q = t.q, this.dmp1 = t.dmp1, this.dmq1 = t.dmq1, this.coeff = t.coeff) + }, e + }(X); + const nt = function () { + function t(t) { + t = t || {}, this.default_key_size = t.default_key_size ? parseInt(t.default_key_size, 10) : 1024, this.default_public_exponent = t.default_public_exponent || "010001", this.log = t.log || !1, this.key = null + } + + return t.prototype.setKey = function (t) { + this.log && this.key && console.warn("A key was already set, overriding existing."), this.key = new rt(t) + }, t.prototype.setPrivateKey = function (t) { + this.setKey(t) + }, t.prototype.setPublicKey = function (t) { + this.setKey(t) + }, t.prototype.decrypt = function (t) { + try { + return this.getKey().decrypt(p(t)) + } catch (t) { + return !1 + } + }, t.prototype.encrypt = function (t) { + try { + return l(this.getKey().encrypt(t)) + } catch (t) { + return !1 + } + }, t.prototype.sign = function (t, e, i) { + try { + return l(this.getKey().sign(t, e, i)) + } catch (t) { + return !1 + } + }, t.prototype.verify = function (t, e, i) { + try { + return this.getKey().verify(t, p(e), i) + } catch (t) { + return !1 + } + }, t.prototype.getKey = function (t) { + if (!this.key) { + if (this.key = new rt, t && "[object Function]" === {}.toString.call(t)) return void this.key.generateAsync(this.default_key_size, this.default_public_exponent, t); + this.key.generate(this.default_key_size, this.default_public_exponent) + } + return this.key + }, t.prototype.getPrivateKey = function () { + return this.getKey().getPrivateKey() + }, t.prototype.getPrivateKeyB64 = function () { + return this.getKey().getPrivateBaseKeyB64() + }, t.prototype.getPublicKey = function () { + return this.getKey().getPublicKey() + }, t.prototype.getPublicKeyB64 = function () { + return this.getKey().getPublicBaseKeyB64() + }, t.version = "3.0.0-rc.2", t + }() + } + }, e = {}; + + function i(r) { + if (e[r]) return e[r].exports; + var n = e[r] = {exports: {}}; + return t[r](n, n.exports, i), n.exports + } + + return i.d = (t, e) => { + for (var r in e) i.o(e, r) && !i.o(t, r) && Object.defineProperty(t, r, {enumerable: !0, get: e[r]}) + }, i.o = (t, e) => Object.prototype.hasOwnProperty.call(t, e), i(771) + })().default +})); \ No newline at end of file diff --git a/src/main/resources/static/js/lay-module/common/common.js b/src/main/resources/static/js/lay-module/common/common.js index 7fab1e5..79dae95 100644 --- a/src/main/resources/static/js/lay-module/common/common.js +++ b/src/main/resources/static/js/lay-module/common/common.js @@ -54,7 +54,7 @@ layui.define(['form','table'], function (exports) { //提示:模块也可以 submitPostReq, formListenFun: function (layFilter, type, path, resultId, reqType) { form.on(`submit(${layFilter})`, function (data) { - var value = data.field.content; + var value = data.field.payload; // 定义白名单正则表达式 var whitelistRegex = /^[a-zA-Z0-9_\s]+$/; diff --git a/src/main/resources/static/js/md5.min.js b/src/main/resources/static/js/md5.min.js new file mode 100644 index 0000000..b74f9e7 --- /dev/null +++ b/src/main/resources/static/js/md5.min.js @@ -0,0 +1,109 @@ +/** + * [js-md5]{@link https://github.com/emn178/js-md5} + * + * @namespace md5 + * @version 0.7.3 + * @author Chen, Yi-Cyuan [emn178@gmail.com] + * @copyright Chen, Yi-Cyuan 2014-2017 + * @license MIT + */ +!function () { + "use strict"; + + function t(t) { + if (t) d[0] = d[16] = d[1] = d[2] = d[3] = d[4] = d[5] = d[6] = d[7] = d[8] = d[9] = d[10] = d[11] = d[12] = d[13] = d[14] = d[15] = 0, this.blocks = d, this.buffer8 = l; else if (a) { + var r = new ArrayBuffer(68); + this.buffer8 = new Uint8Array(r), this.blocks = new Uint32Array(r) + } else this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + this.h0 = this.h1 = this.h2 = this.h3 = this.start = this.bytes = this.hBytes = 0, this.finalized = this.hashed = !1, this.first = !0 + } + + var r = "input is invalid type", e = "object" == typeof window, i = e ? window : {}; + i.JS_MD5_NO_WINDOW && (e = !1); + var s = !e && "object" == typeof self, + h = !i.JS_MD5_NO_NODE_JS && "object" == typeof process && process.versions && process.versions.node; + h ? i = global : s && (i = self); + var f = !i.JS_MD5_NO_COMMON_JS && "object" == typeof module && module.exports, + o = "function" == typeof define && define.amd, + a = !i.JS_MD5_NO_ARRAY_BUFFER && "undefined" != typeof ArrayBuffer, n = "0123456789abcdef".split(""), + u = [128, 32768, 8388608, -2147483648], y = [0, 8, 16, 24], + c = ["hex", "array", "digest", "buffer", "arrayBuffer", "base64"], + p = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(""), d = [], l; + if (a) { + var A = new ArrayBuffer(68); + l = new Uint8Array(A), d = new Uint32Array(A) + } + !i.JS_MD5_NO_NODE_JS && Array.isArray || (Array.isArray = function (t) { + return "[object Array]" === Object.prototype.toString.call(t) + }), !a || !i.JS_MD5_NO_ARRAY_BUFFER_IS_VIEW && ArrayBuffer.isView || (ArrayBuffer.isView = function (t) { + return "object" == typeof t && t.buffer && t.buffer.constructor === ArrayBuffer + }); + var b = function (r) { + return function (e) { + return new t(!0).update(e)[r]() + } + }, v = function () { + var r = b("hex"); + h && (r = w(r)), r.create = function () { + return new t + }, r.update = function (t) { + return r.create().update(t) + }; + for (var e = 0; e < c.length; ++e) { + var i = c[e]; + r[i] = b(i) + } + return r + }, w = function (t) { + var e = eval("require('crypto')"), i = eval("require('buffer').Buffer"), s = function (s) { + if ("string" == typeof s) return e.createHash("md5").update(s, "utf8").digest("hex"); + if (null === s || void 0 === s) throw r; + return s.constructor === ArrayBuffer && (s = new Uint8Array(s)), Array.isArray(s) || ArrayBuffer.isView(s) || s.constructor === i ? e.createHash("md5").update(new i(s)).digest("hex") : t(s) + }; + return s + }; + t.prototype.update = function (t) { + if (!this.finalized) { + var e, i = typeof t; + if ("string" !== i) { + if ("object" !== i) throw r; + if (null === t) throw r; + if (a && t.constructor === ArrayBuffer) t = new Uint8Array(t); else if (!(Array.isArray(t) || a && ArrayBuffer.isView(t))) throw r; + e = !0 + } + for (var s, h, f = 0, o = t.length, n = this.blocks, u = this.buffer8; f < o;) { + if (this.hashed && (this.hashed = !1, n[0] = n[16], n[16] = n[1] = n[2] = n[3] = n[4] = n[5] = n[6] = n[7] = n[8] = n[9] = n[10] = n[11] = n[12] = n[13] = n[14] = n[15] = 0), e) if (a) for (h = this.start; f < o && h < 64; ++f) u[h++] = t[f]; else for (h = this.start; f < o && h < 64; ++f) n[h >> 2] |= t[f] << y[3 & h++]; else if (a) for (h = this.start; f < o && h < 64; ++f) (s = t.charCodeAt(f)) < 128 ? u[h++] = s : s < 2048 ? (u[h++] = 192 | s >> 6, u[h++] = 128 | 63 & s) : s < 55296 || s >= 57344 ? (u[h++] = 224 | s >> 12, u[h++] = 128 | s >> 6 & 63, u[h++] = 128 | 63 & s) : (s = 65536 + ((1023 & s) << 10 | 1023 & t.charCodeAt(++f)), u[h++] = 240 | s >> 18, u[h++] = 128 | s >> 12 & 63, u[h++] = 128 | s >> 6 & 63, u[h++] = 128 | 63 & s); else for (h = this.start; f < o && h < 64; ++f) (s = t.charCodeAt(f)) < 128 ? n[h >> 2] |= s << y[3 & h++] : s < 2048 ? (n[h >> 2] |= (192 | s >> 6) << y[3 & h++], n[h >> 2] |= (128 | 63 & s) << y[3 & h++]) : s < 55296 || s >= 57344 ? (n[h >> 2] |= (224 | s >> 12) << y[3 & h++], n[h >> 2] |= (128 | s >> 6 & 63) << y[3 & h++], n[h >> 2] |= (128 | 63 & s) << y[3 & h++]) : (s = 65536 + ((1023 & s) << 10 | 1023 & t.charCodeAt(++f)), n[h >> 2] |= (240 | s >> 18) << y[3 & h++], n[h >> 2] |= (128 | s >> 12 & 63) << y[3 & h++], n[h >> 2] |= (128 | s >> 6 & 63) << y[3 & h++], n[h >> 2] |= (128 | 63 & s) << y[3 & h++]); + this.lastByteIndex = h, this.bytes += h - this.start, h >= 64 ? (this.start = h - 64, this.hash(), this.hashed = !0) : this.start = h + } + return this.bytes > 4294967295 && (this.hBytes += this.bytes / 4294967296 << 0, this.bytes = this.bytes % 4294967296), this + } + }, t.prototype.finalize = function () { + if (!this.finalized) { + this.finalized = !0; + var t = this.blocks, r = this.lastByteIndex; + t[r >> 2] |= u[3 & r], r >= 56 && (this.hashed || this.hash(), t[0] = t[16], t[16] = t[1] = t[2] = t[3] = t[4] = t[5] = t[6] = t[7] = t[8] = t[9] = t[10] = t[11] = t[12] = t[13] = t[14] = t[15] = 0), t[14] = this.bytes << 3, t[15] = this.hBytes << 3 | this.bytes >>> 29, this.hash() + } + }, t.prototype.hash = function () { + var t, r, e, i, s, h, f = this.blocks; + this.first ? r = ((r = ((t = ((t = f[0] - 680876937) << 7 | t >>> 25) - 271733879 << 0) ^ (e = ((e = (-271733879 ^ (i = ((i = (-1732584194 ^ 2004318071 & t) + f[1] - 117830708) << 12 | i >>> 20) + t << 0) & (-271733879 ^ t)) + f[2] - 1126478375) << 17 | e >>> 15) + i << 0) & (i ^ t)) + f[3] - 1316259209) << 22 | r >>> 10) + e << 0 : (t = this.h0, r = this.h1, e = this.h2, r = ((r += ((t = ((t += ((i = this.h3) ^ r & (e ^ i)) + f[0] - 680876936) << 7 | t >>> 25) + r << 0) ^ (e = ((e += (r ^ (i = ((i += (e ^ t & (r ^ e)) + f[1] - 389564586) << 12 | i >>> 20) + t << 0) & (t ^ r)) + f[2] + 606105819) << 17 | e >>> 15) + i << 0) & (i ^ t)) + f[3] - 1044525330) << 22 | r >>> 10) + e << 0), r = ((r += ((t = ((t += (i ^ r & (e ^ i)) + f[4] - 176418897) << 7 | t >>> 25) + r << 0) ^ (e = ((e += (r ^ (i = ((i += (e ^ t & (r ^ e)) + f[5] + 1200080426) << 12 | i >>> 20) + t << 0) & (t ^ r)) + f[6] - 1473231341) << 17 | e >>> 15) + i << 0) & (i ^ t)) + f[7] - 45705983) << 22 | r >>> 10) + e << 0, r = ((r += ((t = ((t += (i ^ r & (e ^ i)) + f[8] + 1770035416) << 7 | t >>> 25) + r << 0) ^ (e = ((e += (r ^ (i = ((i += (e ^ t & (r ^ e)) + f[9] - 1958414417) << 12 | i >>> 20) + t << 0) & (t ^ r)) + f[10] - 42063) << 17 | e >>> 15) + i << 0) & (i ^ t)) + f[11] - 1990404162) << 22 | r >>> 10) + e << 0, r = ((r += ((t = ((t += (i ^ r & (e ^ i)) + f[12] + 1804603682) << 7 | t >>> 25) + r << 0) ^ (e = ((e += (r ^ (i = ((i += (e ^ t & (r ^ e)) + f[13] - 40341101) << 12 | i >>> 20) + t << 0) & (t ^ r)) + f[14] - 1502002290) << 17 | e >>> 15) + i << 0) & (i ^ t)) + f[15] + 1236535329) << 22 | r >>> 10) + e << 0, r = ((r += ((i = ((i += (r ^ e & ((t = ((t += (e ^ i & (r ^ e)) + f[1] - 165796510) << 5 | t >>> 27) + r << 0) ^ r)) + f[6] - 1069501632) << 9 | i >>> 23) + t << 0) ^ t & ((e = ((e += (t ^ r & (i ^ t)) + f[11] + 643717713) << 14 | e >>> 18) + i << 0) ^ i)) + f[0] - 373897302) << 20 | r >>> 12) + e << 0, r = ((r += ((i = ((i += (r ^ e & ((t = ((t += (e ^ i & (r ^ e)) + f[5] - 701558691) << 5 | t >>> 27) + r << 0) ^ r)) + f[10] + 38016083) << 9 | i >>> 23) + t << 0) ^ t & ((e = ((e += (t ^ r & (i ^ t)) + f[15] - 660478335) << 14 | e >>> 18) + i << 0) ^ i)) + f[4] - 405537848) << 20 | r >>> 12) + e << 0, r = ((r += ((i = ((i += (r ^ e & ((t = ((t += (e ^ i & (r ^ e)) + f[9] + 568446438) << 5 | t >>> 27) + r << 0) ^ r)) + f[14] - 1019803690) << 9 | i >>> 23) + t << 0) ^ t & ((e = ((e += (t ^ r & (i ^ t)) + f[3] - 187363961) << 14 | e >>> 18) + i << 0) ^ i)) + f[8] + 1163531501) << 20 | r >>> 12) + e << 0, r = ((r += ((i = ((i += (r ^ e & ((t = ((t += (e ^ i & (r ^ e)) + f[13] - 1444681467) << 5 | t >>> 27) + r << 0) ^ r)) + f[2] - 51403784) << 9 | i >>> 23) + t << 0) ^ t & ((e = ((e += (t ^ r & (i ^ t)) + f[7] + 1735328473) << 14 | e >>> 18) + i << 0) ^ i)) + f[12] - 1926607734) << 20 | r >>> 12) + e << 0, r = ((r += ((h = (i = ((i += ((s = r ^ e) ^ (t = ((t += (s ^ i) + f[5] - 378558) << 4 | t >>> 28) + r << 0)) + f[8] - 2022574463) << 11 | i >>> 21) + t << 0) ^ t) ^ (e = ((e += (h ^ r) + f[11] + 1839030562) << 16 | e >>> 16) + i << 0)) + f[14] - 35309556) << 23 | r >>> 9) + e << 0, r = ((r += ((h = (i = ((i += ((s = r ^ e) ^ (t = ((t += (s ^ i) + f[1] - 1530992060) << 4 | t >>> 28) + r << 0)) + f[4] + 1272893353) << 11 | i >>> 21) + t << 0) ^ t) ^ (e = ((e += (h ^ r) + f[7] - 155497632) << 16 | e >>> 16) + i << 0)) + f[10] - 1094730640) << 23 | r >>> 9) + e << 0, r = ((r += ((h = (i = ((i += ((s = r ^ e) ^ (t = ((t += (s ^ i) + f[13] + 681279174) << 4 | t >>> 28) + r << 0)) + f[0] - 358537222) << 11 | i >>> 21) + t << 0) ^ t) ^ (e = ((e += (h ^ r) + f[3] - 722521979) << 16 | e >>> 16) + i << 0)) + f[6] + 76029189) << 23 | r >>> 9) + e << 0, r = ((r += ((h = (i = ((i += ((s = r ^ e) ^ (t = ((t += (s ^ i) + f[9] - 640364487) << 4 | t >>> 28) + r << 0)) + f[12] - 421815835) << 11 | i >>> 21) + t << 0) ^ t) ^ (e = ((e += (h ^ r) + f[15] + 530742520) << 16 | e >>> 16) + i << 0)) + f[2] - 995338651) << 23 | r >>> 9) + e << 0, r = ((r += ((i = ((i += (r ^ ((t = ((t += (e ^ (r | ~i)) + f[0] - 198630844) << 6 | t >>> 26) + r << 0) | ~e)) + f[7] + 1126891415) << 10 | i >>> 22) + t << 0) ^ ((e = ((e += (t ^ (i | ~r)) + f[14] - 1416354905) << 15 | e >>> 17) + i << 0) | ~t)) + f[5] - 57434055) << 21 | r >>> 11) + e << 0, r = ((r += ((i = ((i += (r ^ ((t = ((t += (e ^ (r | ~i)) + f[12] + 1700485571) << 6 | t >>> 26) + r << 0) | ~e)) + f[3] - 1894986606) << 10 | i >>> 22) + t << 0) ^ ((e = ((e += (t ^ (i | ~r)) + f[10] - 1051523) << 15 | e >>> 17) + i << 0) | ~t)) + f[1] - 2054922799) << 21 | r >>> 11) + e << 0, r = ((r += ((i = ((i += (r ^ ((t = ((t += (e ^ (r | ~i)) + f[8] + 1873313359) << 6 | t >>> 26) + r << 0) | ~e)) + f[15] - 30611744) << 10 | i >>> 22) + t << 0) ^ ((e = ((e += (t ^ (i | ~r)) + f[6] - 1560198380) << 15 | e >>> 17) + i << 0) | ~t)) + f[13] + 1309151649) << 21 | r >>> 11) + e << 0, r = ((r += ((i = ((i += (r ^ ((t = ((t += (e ^ (r | ~i)) + f[4] - 145523070) << 6 | t >>> 26) + r << 0) | ~e)) + f[11] - 1120210379) << 10 | i >>> 22) + t << 0) ^ ((e = ((e += (t ^ (i | ~r)) + f[2] + 718787259) << 15 | e >>> 17) + i << 0) | ~t)) + f[9] - 343485551) << 21 | r >>> 11) + e << 0, this.first ? (this.h0 = t + 1732584193 << 0, this.h1 = r - 271733879 << 0, this.h2 = e - 1732584194 << 0, this.h3 = i + 271733878 << 0, this.first = !1) : (this.h0 = this.h0 + t << 0, this.h1 = this.h1 + r << 0, this.h2 = this.h2 + e << 0, this.h3 = this.h3 + i << 0) + }, t.prototype.hex = function () { + this.finalize(); + var t = this.h0, r = this.h1, e = this.h2, i = this.h3; + return n[t >> 4 & 15] + n[15 & t] + n[t >> 12 & 15] + n[t >> 8 & 15] + n[t >> 20 & 15] + n[t >> 16 & 15] + n[t >> 28 & 15] + n[t >> 24 & 15] + n[r >> 4 & 15] + n[15 & r] + n[r >> 12 & 15] + n[r >> 8 & 15] + n[r >> 20 & 15] + n[r >> 16 & 15] + n[r >> 28 & 15] + n[r >> 24 & 15] + n[e >> 4 & 15] + n[15 & e] + n[e >> 12 & 15] + n[e >> 8 & 15] + n[e >> 20 & 15] + n[e >> 16 & 15] + n[e >> 28 & 15] + n[e >> 24 & 15] + n[i >> 4 & 15] + n[15 & i] + n[i >> 12 & 15] + n[i >> 8 & 15] + n[i >> 20 & 15] + n[i >> 16 & 15] + n[i >> 28 & 15] + n[i >> 24 & 15] + }, t.prototype.toString = t.prototype.hex, t.prototype.digest = function () { + this.finalize(); + var t = this.h0, r = this.h1, e = this.h2, i = this.h3; + return [255 & t, t >> 8 & 255, t >> 16 & 255, t >> 24 & 255, 255 & r, r >> 8 & 255, r >> 16 & 255, r >> 24 & 255, 255 & e, e >> 8 & 255, e >> 16 & 255, e >> 24 & 255, 255 & i, i >> 8 & 255, i >> 16 & 255, i >> 24 & 255] + }, t.prototype.array = t.prototype.digest, t.prototype.arrayBuffer = function () { + this.finalize(); + var t = new ArrayBuffer(16), r = new Uint32Array(t); + return r[0] = this.h0, r[1] = this.h1, r[2] = this.h2, r[3] = this.h3, t + }, t.prototype.buffer = t.prototype.arrayBuffer, t.prototype.base64 = function () { + for (var t, r, e, i = "", s = this.array(), h = 0; h < 15;) t = s[h++], r = s[h++], e = s[h++], i += p[t >>> 2] + p[63 & (t << 4 | r >>> 4)] + p[63 & (r << 2 | e >>> 6)] + p[63 & e]; + return t = s[h], i += p[t >>> 2] + p[t << 4 & 63] + "==" + }; + var _ = v(); + f ? module.exports = _ : (i.md5 = _, o && define(function () { + return _ + })) +}(); \ No newline at end of file diff --git a/src/main/resources/static/js/staticcode.js b/src/main/resources/static/js/staticcode.js index afad491..cdd8fe0 100644 --- a/src/main/resources/static/js/staticcode.js +++ b/src/main/resources/static/js/staticcode.js @@ -163,29 +163,56 @@ const safe1StoreEntityEscape = "// 表格数据渲染\n" + "// 方法三、jQuery的text()方法\n" + "$('#element').text(htmlContent);\n" -const vul1DomRaw = "// innerHTML\n" + +const vul1DomRaw = "// 1. innerHTML XSS\n" + "form.on('submit(vul1-dom-raw)', function (data) {\n" + " var userInput = document.getElementById('vul1-dom-raw-input').value;\n" + " var outputDiv = document.getElementById('vul-dom-raw-result');\n" + - " outputDiv.innerHTML = userInput;\n" + + " outputDiv.innerHTML = userInput; // 漏洞点:直接使用innerHTML插入用户输入\n" + " return false;\n" + "});\n" + "\n" + - "// href跳转场景\n" + + "// 2. LocalStorage XSS\n" + + "form.on('submit(vul3-dom-raw-submit)', function (data) {\n" + + " localStorage.setItem('vul4-dom-raw', document.getElementById('vul4-dom-raw-input').value);\n" + + " var storedData = localStorage.getItem('vul4-dom-raw');\n" + + " document.getElementById('vul-dom-raw-result').innerHTML = storedData; // 漏洞点:从存储读取后直接插入\n" + + " return false;\n" + + "});\n" + + "\n" + + "// 3. href跳转XSS\n" + "var hash = location.hash;\n" + "if(hash){\n" + - " var url = hash.substring(ueditor);\n" + + " var url = hash.substring(1); // 去掉#号\n" + " console.log(url);\n" + - " location.href = url;\n" + + " location.href = url; // 漏洞点:直接使用hash部分作为跳转URL\n" + "}\n" + "\n" + - "// DOM存储注入\n" + - "form.on('submit(vul3-dom-raw-submit)', function (data) {\n" + - " localStorage.setItem('vul4-dom-raw', document.getElementById('vul4-dom-raw-input').value);\n" + - " var storedData = localStorage.getItem('vul4-dom-raw');\n" + - " document.getElementById('vul-dom-raw-result').innerHTML = storedData;\n" + + "// 4. Location对象XSS\n" + + "form.on('submit(location-xss)', function(data) {\n" + + " var payload = data.field.locationPayload;\n" + + " window.location = payload; // 漏洞点:直接使用用户输入修改location\n" + + " return false;\n" + + "});\n" + + "\n" + + "// 5. Eval执行XSS\n" + + "form.on('submit(eval-xss)', function(data) {\n" + + " var payload = data.field.evalPayload;\n" + + " eval(payload); // 漏洞点:直接执行用户输入的JavaScript代码\n" + + " return false;\n" + + "});\n" + + "\n" + + "// 6. Document对象XSS\n" + + "form.on('submit(document-write)', function(data) {\n" + + " var payload = data.field.documentPayload;\n" + + " document.write(payload); // 漏洞点:直接写入用户输入的HTML\n" + + " document.close();\n" + + " return false;\n" + + "});\n" + + "form.on('submit(document-domain)', function(data) {\n" + + " var payload = data.field.documentPayload;\n" + + " document.domain = payload; // 漏洞点:直接修改document.domain\n" + " return false;\n" + - "})" + "});" const vul1OtherUpload = "public String uploadFile(MultipartFile file, String suffix,String path) throws IOException {\n" + " String uploadFolderPath = sysConstant.getUploadFolder();\n" + @@ -234,6 +261,22 @@ const vul3SCMSec = "// jQuery依赖\n" + "\n" + "// Ueditor编辑器未做任何限制 抓上传数据包后,可以上传任意类型文件"; +const vulHtml5 = "1、WebSocket XSS\n" + + "// 接收端:直接使用innerHTML插入消息\n" + + "window.addEventListener('message', function(event) {\n" + + " // 故意不验证origin\n" + + " document.getElementById('messageContainer').innerHTML = event.data;\n" + + "});\n" + + "// 客户端:直接使用innerHTML插入消息\n" + + "ws.onmessage = function(event) {\n" + + " document.getElementById('wsMessageContainer').innerHTML = event.data;\n" + + "};\n" + + "2、PostMessage XSS\n" + + "// 服务端:直接广播用户输入\n" + + "protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {\n" + + " broadcast(message.getPayload());\n" + + "}" + const vul1RawJoint = "// 原生sql语句动态拼接 参数未进行任何处理\n" + "public R vul1(String type,String id,String username,String password) {\n" + " //注册数据库驱动类\n" + diff --git a/src/main/resources/static/lib/custom-icon/demo_index.html b/src/main/resources/static/lib/custom-icon/demo_index.html index e0c9f9f..d51334c 100644 --- a/src/main/resources/static/lib/custom-icon/demo_index.html +++ b/src/main/resources/static/lib/custom-icon/demo_index.html @@ -54,6 +54,24 @@