diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..d93a40e
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,8 @@
+FROM maven:3.8-jdk-8 as builder
+COPY . /usr/src/easybuggy/
+WORKDIR /usr/src/easybuggy/
+RUN mvn -B package
+
+FROM openjdk:8-slim
+COPY --from=builder /usr/src/easybuggy/target/easybuggy.jar /
+CMD ["java", "-XX:MaxMetaspaceSize=128m", "-Xloggc:logs/gc_%p_%t.log", "-Xmx256m", "-XX:MaxDirectMemorySize=90m", "-XX:+UseSerialGC", "-XX:+PrintHeapAtGC", "-XX:+PrintGCDetails", "-XX:+PrintGCDateStamps", "-XX:+UseGCLogFileRotation", "-XX:NumberOfGCLogFiles=5", "-XX:GCLogFileSize=10M", "-XX:GCTimeLimit=15", "-XX:GCHeapFreeLimit=50", "-XX:+HeapDumpOnOutOfMemoryError", "-XX:HeapDumpPath=logs/", "-XX:ErrorFile=logs/hs_err_pid%p.log", "-agentlib:jdwp=transport=dt_socket,server=y,address=9009,suspend=n", "-Dderby.stream.error.file=logs/derby.log", "-Dderby.infolog.append=true", "-Dderby.language.logStatementText=true", "-Dderby.locks.deadlockTrace=true", "-Dderby.locks.monitor=true", "-Dderby.storage.rowLocking=true", "-Dcom.sun.management.jmxremote", "-Dcom.sun.management.jmxremote.port=7900", "-Dcom.sun.management.jmxremote.ssl=false", "-Dcom.sun.management.jmxremote.authenticate=false", "-ea", "-jar", "easybuggy.jar"]
diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 0000000..1910e2a
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,21 @@
+pipeline {
+ agent any
+ tools {
+ maven 'Maven_3_5_2'
+ }
+ stages{
+ stage('CompileandRunSonarAnalysis') {
+ steps {
+ sh 'mvn clean verify sonar:sonar -Dsonar.projectKey=asgbuggywebapp -Dsonar.organization=asgbuggywebapp -Dsonar.host.url=https://sonarcloud.io -Dsonar.login=932558e169d66a8f1d1adf470b908a46156f5844'
+ }
+ }
+
+ stage('RunSCAAnalysisUsingSnyk') {
+ steps {
+ withCredentials([string(credentialsId: 'SNYK_TOKEN', variable: 'SNYK_TOKEN')]) {
+ sh 'mvn snyk:test -fn'
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..93d6997
--- /dev/null
+++ b/README.md
@@ -0,0 +1,138 @@
+[![Build Status](https://travis-ci.org/k-tamura/easybuggy.svg?branch=master)](https://travis-ci.org/k-tamura/easybuggy)
+[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
+[![GitHub release](https://img.shields.io/github/release/k-tamura/easybuggy.svg)](https://github.com/k-tamura/easybuggy/releases/latest)
+
+EasyBuggy Vulnerable Web App Modified by A Security Guru :baby_symbol:
+=
+
+EasyBuggy is a broken web application in order to understand behavior of bugs and vulnerabilities, for example, [memory leak, deadlock, JVM crash, SQL injection and so on](https://github.com/k-tamura/easybuggy#clock4-easybuggy-can-reproduce).
+
+![logo](https://raw.githubusercontent.com/wiki/k-tamura/easybuggy/images/mov_eb.gif)
+
+:clock4: Quick Start
+-
+
+ $ mvn clean install
+
+( or ``` java -jar easybuggy.jar ``` or deploy ROOT.war on your servlet container with [the JVM options](https://github.com/k-tamura/easybuggy/blob/master/pom.xml#L204). )
+
+Access to
+
+ http://localhost:8080
+
+:clock4: Quick Start(Docker)
+-
+
+ $ docker build . -t easybuggy:local # Build container image
+ $ docker run -p 8080:8080 easybuggy:local # Start easybuggy
+
+Access to
+
+ http://localhost:8080
+
+### To stop:
+
+ Use CTRL+C ( or access to: http://localhost:8080/exit )
+
+:clock4: For more detail
+-
+
+See [the wiki page](https://github.com/k-tamura/easybuggy/wiki).
+
+:clock4: Demo
+-
+
+This demo shows: Start up -> Infinite Loop -> LDAP Injection -> UnsatisfiedLinkError -> BufferOverflowException -> Deadlock -> Memory Leak -> JVM Crash (Shut down)
+
+![demo](https://github.com/k-tamura/easybuggy/blob/master/demo_eb.gif)
+
+:clock4: EasyBuggy can reproduce:
+-
+
+* Troubles
+
+ * Memory Leak (Java heap space)
+ * Memory Leak (PermGen space)
+ * Memory Leak (C heap space)
+ * Deadlock (Java)
+ * Deadlock (SQL)
+ * Endless Waiting Process
+ * Infinite Loop
+ * Redirect Loop
+ * Forward Loop
+ * JVM Crash
+ * Network Socket Leak
+ * Database Connection Leak
+ * File Descriptor Leak
+ * Thread Leak
+ * Mojibake
+ * Integer Overflow
+ * Round Off Error
+ * Truncation Error
+ * Loss of Trailing Digits
+
+* Vulnerabilities
+
+ * XSS (Cross-Site Scripting)
+ * SQL Injection
+ * LDAP Injection
+ * Code Injection
+ * OS Command Injection (OGNL Expression Injection)
+ * Mail Header Injection
+ * Null Byte Injection
+ * Extension Unrestricted File Upload
+ * Size Unrestricted File Upload
+ * Open Redirect
+ * Brute-force Attack
+ * Session Fixation Attacks
+ * Verbose Login Error Messages
+ * Dangerous File Inclusion
+ * Directory Traversal
+ * Unintended File Disclosure
+ * CSRF (Cross-Site Request Forgery)
+ * XEE (XML Entity Expansion)
+ * XXE (XML eXternal Entity)
+ * Clickjacking
+
+* Performance Degradation
+
+ * Slow Regular Expression Parsing
+ * Delay of creating string due to +(plus) operator
+ * Delay due to unnecessary object creation
+
+* Errors
+
+ * AssertionError
+ * ExceptionInInitializerError
+ * FactoryConfigurationError
+ * GenericSignatureFormatError
+ * NoClassDefFoundError
+ * OutOfMemoryError (Java heap space)
+ * OutOfMemoryError (Requested array size exceeds VM limit)
+ * OutOfMemoryError (unable to create new native thread)
+ * OutOfMemoryError (GC overhead limit exceeded)
+ * OutOfMemoryError (PermGen space)
+ * OutOfMemoryError (Direct buffer memory)
+ * StackOverflowError
+ * TransformerFactoryConfigurationError
+ * UnsatisfiedLinkError
+
+:clock4: EasyBuggy clones:
+-
+* [EasyBuggy Boot](https://github.com/k-tamura/easybuggy4sb)
+
+ EasyBuggy clone build on Spring Boot
+
+ ![logo](https://raw.githubusercontent.com/wiki/k-tamura/easybuggy/images/mov_ebsb.gif)
+
+* [EasyBuggy Bootlin](https://github.com/k-tamura/easybuggy4kt)
+
+ EasyBuggy clone build on Spring Boot and written in Kotlin
+
+ ![logo](https://raw.githubusercontent.com/wiki/k-tamura/easybuggy/images/mov_ebkt.gif)
+
+* [EasyBuggy Django](https://github.com/k-tamura/easybuggy4django)
+
+ EasyBuggy clone build on Django 2 and written in Python
+
+ ![logo](https://github.com/k-tamura/easybuggy4django/blob/master/static/easybuggy.png)
diff --git a/catalina.policy b/catalina.policy
new file mode 100644
index 0000000..7eb7086
--- /dev/null
+++ b/catalina.policy
@@ -0,0 +1,34 @@
+grant {
+ permission java.io.FilePermission "<>", "write, read, execute, delete";
+ permission java.io.SerializablePermission "*" ;
+ permission java.lang.management.ManagementPermission "monitor";
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+ permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.comet";
+ permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.websocket";
+ permission java.lang.RuntimePermission "accessClassInPackage.org.apache.jasper.el";
+ permission java.lang.RuntimePermission "accessClassInPackage.org.apache.jasper.runtime";
+ permission java.lang.RuntimePermission "accessClassInPackage.org.apache.jasper.runtime.*";
+ permission java.lang.RuntimePermission "accessClassInPackage.org.apache.tomcat";
+ permission java.lang.RuntimePermission "accessClassInPackage.org.apache.tomcat.websocket";
+ permission java.lang.RuntimePermission "accessClassInPackage.org.apache.tomcat.websocket.server";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect";
+ permission java.lang.RuntimePermission "accessDeclaredMembers";
+ permission java.lang.RuntimePermission "createClassLoader";
+ permission java.lang.RuntimePermission "exitVM";
+ permission java.lang.RuntimePermission "getClassLoader";
+ permission java.lang.RuntimePermission "setContextClassLoader";
+ permission java.lang.RuntimePermission "setFactory";
+ permission java.lang.RuntimePermission "shutdownHooks";
+ permission java.net.NetPermission "*";
+ permission java.net.PropertyPermission "*", "read, write";
+ permission java.net.SocketPermission "*", "accept, listen, connect, resolve";
+ permission java.security.SecurityPermission "*";
+ permission java.util.PropertyPermission "*", "read, write";
+ permission javax.management.MBeanPermission "*", "*";
+ permission javax.management.MBeanServerPermission "createMBeanServer";
+ permission javax.management.MBeanServerPermission "findMBeanServer";
+ permission javax.management.MBeanTrustPermission "register";
+ permission javax.security.auth.AuthPermission "*";
+ permission ognl.OgnlInvokePermission "*";
+};
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..69f8a02
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,351 @@
+
+
+
+ 4.0.0
+ org.t246osslab.easybuggy
+ easybuggy
+ 1-SNAPSHOT
+ war
+
+
+ UTF-8
+ 8080
+
+ -XX:MaxPermSize=128m
+ -Xloggc:logs/gc.log
+ -XX:+PrintHeapAtGC
+ -XX:+PrintGCDetails
+ -XX:+PrintGCDateStamps
+ -XX:+UseGCLogFileRotation
+ -XX:NumberOfGCLogFiles=5
+ -XX:GCLogFileSize=10M
+
+
+
+
+ JDK8-Switch
+
+ 1.8
+
+
+ -XX:MaxMetaspaceSize=128m
+ -Xloggc:logs/gc_%p_%t.log
+
+
+
+ JDK11-Switch
+
+ 11
+
+
+ -XX:MaxMetaspaceSize=128m
+ -Xlog:gc*:logs/gc_%p_%t.log:time,level,tags:filecount=5,filesize=10M
+
+ -Dummy=Dummy
+ -Dummy=Dummy
+ -Dummy=Dummy
+ -Dummy=Dummy
+ -Dummy=Dummy
+ -Dummy=Dummy
+
+
+
+
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.0.1
+ provided
+
+
+ javax.servlet.jsp
+ jsp-api
+ 2.2
+ provided
+
+
+ javax.servlet
+ jstl
+ 1.2
+
+
+ org.apache.derby
+ derby
+ 10.8.3.0
+
+
+ javassist
+ javassist
+ 3.12.1.GA
+
+
+ org.openjdk.jol
+ jol-core
+ 0.6
+
+
+ mysql
+ mysql-connector-java
+ 5.1.25
+
+
+ org.slf4j
+ slf4j-api
+ 1.5.0
+
+
+ org.slf4j
+ slf4j-log4j12
+ 1.5.0
+
+
+ org.apache.directory.server
+ apacheds-all
+ 1.5.5
+
+
+ org.apache.directory.shared
+ shared-ldap
+
+
+
+
+ org.owasp.esapi
+ esapi
+ 2.1.0.1
+
+
+ ognl
+ ognl
+ 3.0.17
+
+
+ com.sun.mail
+ javax.mail
+ 1.5.1
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 2.3.2
+
+
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ 1.1.1
+
+
+ enforce-java
+
+ enforce
+
+
+
+
+ [3.0.0,)
+
+
+ [1.6,)
+ [ERROR] OLD JDK [${java.version}] in use.
+ EasyBuggy requires JDK 1.6 or later
+
+
+
+
+
+
+
+ org.owasp
+ dependency-check-maven
+ 6.1.6
+
+ ALL
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+
+
+ create-empty-directory-and-english-properties
+ process-classes
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+ maven-war-plugin
+ 3.3.1
+
+ false
+ ROOT
+
+
+
+ org.apache.tomcat.maven
+ tomcat7-maven-plugin
+ 2.1
+
+
+ tomcat-run
+
+ exec-war-only
+
+ package
+
+ /
+ true
+ easybuggy.jar
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.2
+
+
+ startup-uber-start
+ install
+
+ exec
+
+
+ test
+ java
+
+ ${jvm.args.perm.size}
+ ${jvm.args.gc.log.path}
+ -Xmx256m
+ -XX:MaxDirectMemorySize=90m
+ -XX:+UseSerialGC
+ ${jvm.args.print.heap.at.gc}
+ ${jvm.args.print.gc.details}
+ ${jvm.args.print.gc.date.stamps}
+ ${jvm.args.gc.log.file.rotation}
+ ${jvm.args.number.of.gc.log.files}
+ ${jvm.args.gc.log.file.size}
+ -XX:GCTimeLimit=15
+ -XX:GCHeapFreeLimit=50
+ -XX:+HeapDumpOnOutOfMemoryError
+ -XX:HeapDumpPath=logs/
+ -XX:ErrorFile=logs/hs_err_pid%p.log
+
+
+
+
+
+
+
+
+
+
+ -agentlib:jdwp=transport=dt_socket,server=y,address=9009,suspend=n
+ -Dderby.stream.error.file=logs/derby.log
+ -Dderby.infolog.append=true
+ -Dderby.language.logStatementText=true
+ -Dderby.locks.deadlockTrace=true
+ -Dderby.locks.monitor=true
+ -Dderby.storage.rowLocking=true
+ -Dcom.sun.management.jmxremote
+ -Dcom.sun.management.jmxremote.port=7900
+ -Dcom.sun.management.jmxremote.ssl=false
+ -Dcom.sun.management.jmxremote.authenticate=false
+
+
+ -ea
+ -jar
+ target/easybuggy.jar
+ -httpPort=${easybuggy-port}
+
+
+
+
+
+
+
+ io.snyk
+ snyk-maven-plugin
+ 2.0.0
+ false
+
+ asecurityguru
+
+
+
+
+
+
+
+
+ org.eclipse.m2e
+ lifecycle-mapping
+ 1.0.0
+
+
+
+
+
+
+ org.apache.maven.plugins
+
+
+ maven-antrun-plugin
+
+ [1.3,)
+
+ run
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/org/t246osslab/easybuggy/core/dao/DBClient.java b/src/main/java/org/t246osslab/easybuggy/core/dao/DBClient.java
new file mode 100644
index 0000000..19e2a9f
--- /dev/null
+++ b/src/main/java/org/t246osslab/easybuggy/core/dao/DBClient.java
@@ -0,0 +1,92 @@
+package org.t246osslab.easybuggy.core.dao;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.t246osslab.easybuggy.core.utils.ApplicationUtils;
+import org.t246osslab.easybuggy.core.utils.Closer;
+
+/**
+ * Database client to provide database connections.
+ */
+public final class DBClient {
+
+ private static final Logger log = LoggerFactory.getLogger(DBClient.class);
+
+ static {
+ Statement stmt = null;
+ Connection conn= null;
+ try {
+ conn = getConnection();
+ stmt = conn.createStatement();
+
+ // create a user table and insert sample users
+ createUsersTable(stmt);
+
+ } catch (SQLException e) {
+ log.error("SQLException occurs: ", e);
+ } finally {
+ Closer.close(stmt);
+ Closer.close(conn);
+ }
+ }
+
+ // squid:S1118: Utility classes should not have public constructors
+ private DBClient() {
+ throw new IllegalAccessError("This class should not be instantiated.");
+ }
+
+ /**
+ * Returns a database connection to connect a database.
+ *
+ * @return A database connection
+ */
+ public static Connection getConnection() throws SQLException {
+ final String dbDriver = ApplicationUtils.getDatabaseDriver();
+ final String dbUrl = ApplicationUtils.getDatabaseURL();
+ if (!StringUtils.isBlank(dbDriver)) {
+ try {
+ Class.forName(dbDriver);
+ } catch (ClassNotFoundException e) {
+ log.error("ClassNotFoundException occurs: ", e);
+ }
+ }
+ return DriverManager.getConnection(dbUrl);
+ }
+
+ private static void createUsersTable(Statement stmt) throws SQLException {
+ try {
+ stmt.executeUpdate("drop table users");
+ } catch (SQLException e) {
+ // ignore exception if existing the table
+ log.debug("SQLException occurs: ", e);
+ }
+ // create users table
+ stmt.executeUpdate("create table users (id varchar(10) primary key, name varchar(30), password varchar(30), " +
+ "secret varchar(100), ispublic varchar(5), phone varchar(20), mail varchar(100))");
+
+ // insert private (invisible) user records
+ stmt.executeUpdate("insert into users values ('admin','admin','password','" + RandomStringUtils.randomNumeric(10) + "','false', '', '')");
+ stmt.executeUpdate("insert into users values ('admin02','admin02','pas2w0rd','" + RandomStringUtils.randomNumeric(10) + "','false', '', '')");
+ stmt.executeUpdate("insert into users values ('admin03','admin03','pa33word','" + RandomStringUtils.randomNumeric(10) + "','false', '', '')");
+ stmt.executeUpdate("insert into users values ('admin04','admin04','pathwood','" + RandomStringUtils.randomNumeric(10) + "','false', '', '')");
+
+ // insert public (test) user records
+ stmt.executeUpdate("insert into users values ('user00','Mark','password','" + RandomStringUtils.randomNumeric(10) + "','true', '', '')");
+ stmt.executeUpdate("insert into users values ('user01','David','pa32w0rd','" + RandomStringUtils.randomNumeric(10) + "','true', '', '')");
+ stmt.executeUpdate("insert into users values ('user02','Peter','pa23word','" + RandomStringUtils.randomNumeric(10) + "','true', '', '')");
+ stmt.executeUpdate("insert into users values ('user03','James','patwired','" + RandomStringUtils.randomNumeric(10) + "','true', '', '')");
+ stmt.executeUpdate("insert into users values ('user04','Benjamin','password','" + RandomStringUtils.randomNumeric(10) + "','true', '', '')");
+ stmt.executeUpdate("insert into users values ('user05','Eric','pas2w0rd','" + RandomStringUtils.randomNumeric(10) + "','true', '', '')");
+ stmt.executeUpdate("insert into users values ('user06','Sharon','pa3world','" + RandomStringUtils.randomNumeric(10) + "','true', '', '')");
+ stmt.executeUpdate("insert into users values ('user07','Pamela','pathwood','" + RandomStringUtils.randomNumeric(10) + "','true', '', '')");
+ stmt.executeUpdate("insert into users values ('user08','Jacqueline','password','" + RandomStringUtils.randomNumeric(10) + "','true', '', '')");
+ stmt.executeUpdate("insert into users values ('user09','Michelle','pas2w0rd','" + RandomStringUtils.randomNumeric(10) + "','true', '', '')");
+ }
+}
diff --git a/src/main/java/org/t246osslab/easybuggy/core/dao/EmbeddedADS.java b/src/main/java/org/t246osslab/easybuggy/core/dao/EmbeddedADS.java
new file mode 100644
index 0000000..d4e8c3b
--- /dev/null
+++ b/src/main/java/org/t246osslab/easybuggy/core/dao/EmbeddedADS.java
@@ -0,0 +1,129 @@
+package org.t246osslab.easybuggy.core.dao;
+
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.directory.server.constants.ServerDNConstants;
+import org.apache.directory.server.core.CoreSession;
+import org.apache.directory.server.core.DefaultDirectoryService;
+import org.apache.directory.server.core.DirectoryService;
+import org.apache.directory.server.core.entry.ServerEntry;
+import org.apache.directory.server.core.partition.Partition;
+import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Embedded Apache Directory Server.
+ */
+public final class EmbeddedADS {
+
+ private static final String ROOT_PARTITION_NAME = "t246osslab";
+
+ private static final String ROOT_DN = "dc=t246osslab,dc=org";
+
+ private static final String PEOPLE_CONTAINER_DN = "ou=people," + ROOT_DN;
+
+ private static final Logger log = LoggerFactory.getLogger(EmbeddedADS.class);
+
+ /** The directory service */
+ private static DirectoryService service;
+
+ /*
+ * Create an instance of EmbeddedADS and initialize it.
+ */
+ static {
+ try {
+ service = new DefaultDirectoryService();
+
+ // Disable the ChangeLog system
+ service.getChangeLog().setEnabled(false);
+ service.setDenormalizeOpAttrsEnabled(true);
+
+ // Add system partition
+ Partition systemPartition;
+ systemPartition = addPartition("system", ServerDNConstants.SYSTEM_DN);
+ service.setSystemPartition(systemPartition);
+
+ // Add root partition
+ Partition t246osslabPartition = addPartition(ROOT_PARTITION_NAME, ROOT_DN);
+
+ // Start up the service
+ service.startup();
+
+ // Add the root entry if it does not exist
+ addRootEntry(t246osslabPartition);
+
+ // Add the people entries
+ LdapDN peopleDn = new LdapDN(PEOPLE_CONTAINER_DN);
+ if (!service.getAdminSession().exists(peopleDn)) {
+ ServerEntry e = service.newEntry(peopleDn);
+ e.add("objectClass", "organizationalUnit");
+ e.add("ou", "people");
+ service.getAdminSession().add(e);
+ }
+
+ // Add sample users
+ addUser("admin", "password", RandomStringUtils.randomNumeric(10));
+ addUser("admin2", "pas2w0rd", RandomStringUtils.randomNumeric(10));
+ addUser("admin3", "pa33word", RandomStringUtils.randomNumeric(10));
+ addUser("admin4", "pathwood", RandomStringUtils.randomNumeric(10));
+ } catch (Exception e) {
+ log.error("Exception occurs: ", e);
+ }
+ }
+
+ private static void addRootEntry(Partition t246osslabPartition) throws Exception {
+ try {
+ service.getAdminSession().lookup(t246osslabPartition.getSuffixDn());
+ } catch (Exception e) {
+ log.debug("Exception occurs: ", e);
+ LdapDN dnBar = new LdapDN(ROOT_DN);
+ ServerEntry entryBar = service.newEntry(dnBar);
+ entryBar.add("objectClass", "dcObject", "organization");
+ entryBar.add("o", ROOT_PARTITION_NAME);
+ entryBar.add("dc", ROOT_PARTITION_NAME);
+ service.getAdminSession().add(entryBar);
+ }
+ }
+
+ // squid:S1118: Utility classes should not have public constructors
+ private EmbeddedADS() {
+ throw new IllegalAccessError("This class should not be instantiated.");
+ }
+
+ /**
+ * Returns the admin session to connect Embedded Apache Directory Server.
+ *
+ * @return The admin session
+ */
+ public static CoreSession getAdminSession() throws Exception{
+ return service.getAdminSession();
+ }
+
+ // Add a partition to the server
+ private static Partition addPartition(String partitionId, String partitionDn) throws Exception {
+ // Create a new partition named
+ Partition partition = new JdbmPartition();
+ partition.setId(partitionId);
+ partition.setSuffix(partitionDn);
+ service.addPartition(partition);
+ return partition;
+ }
+
+ // Add a user to the server
+ private static void addUser(String username, String passwd, String secretNumber) throws Exception {
+ LdapDN dn = new LdapDN("uid=" + username + "," + PEOPLE_CONTAINER_DN);
+ if (!service.getAdminSession().exists(dn)) {
+ ServerEntry e = service.newEntry(dn);
+ e.add("objectClass", "person", "inetOrgPerson");
+ e.add("uid", username);
+ e.add("displayName", username);
+ e.add("userPassword", passwd.getBytes());
+ e.add("employeeNumber", secretNumber);
+ e.add("sn", "Not use");
+ e.add("cn", "Not use");
+ e.add("givenName", username);
+ service.getAdminSession().add(e);
+ }
+ }
+}
diff --git a/src/main/java/org/t246osslab/easybuggy/core/filters/AuthenticationFilter.java b/src/main/java/org/t246osslab/easybuggy/core/filters/AuthenticationFilter.java
new file mode 100644
index 0000000..6b357dc
--- /dev/null
+++ b/src/main/java/org/t246osslab/easybuggy/core/filters/AuthenticationFilter.java
@@ -0,0 +1,80 @@
+package org.t246osslab.easybuggy.core.filters;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+/**
+ * Servlet Filter for authentication
+ */
+@WebFilter(urlPatterns = { "/*" })
+public class AuthenticationFilter implements Filter {
+
+ /**
+ * Intercept unauthenticated requests for specific URLs and redirect to login page.
+ *
+ * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
+ */
+ @Override
+ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
+ ServletException {
+
+ HttpServletRequest request = (HttpServletRequest) req;
+ HttpServletResponse response = (HttpServletResponse) res;
+ String target = request.getRequestURI();
+
+ if (target.startsWith("/admins") || "/uid/serverinfo.jsp".equals(target)) {
+ /* Login (authentication) is needed to access admin pages (under /admins). */
+
+ String loginType = request.getParameter("logintype");
+ String queryString = request.getQueryString();
+ if (queryString == null) {
+ queryString = "";
+ } else {
+ /* Remove "logintype" parameter from query string.
+ (* "logintype" specifies a login servlet) */
+ queryString = queryString.replace("logintype=" + loginType + "&", "");
+ queryString = queryString.replace("&logintype=" + loginType, "");
+ queryString = queryString.replace("logintype=" + loginType, "");
+ if (queryString.length() > 0) {
+ queryString = "?" + queryString;
+ }
+ }
+ HttpSession session = request.getSession(false);
+ if (session == null || session.getAttribute("authNMsg") == null
+ || !"authenticated".equals(session.getAttribute("authNMsg"))) {
+ /* Not authenticated yet */
+ session = request.getSession(true);
+ session.setAttribute("target", target);
+ if (loginType == null) {
+ response.sendRedirect(response.encodeRedirectURL("/login" + queryString));
+ } else if ("sessionfixation".equals(loginType)) {
+ response.sendRedirect(response.encodeRedirectURL("/" + loginType + "/login" + queryString));
+ } else {
+ response.sendRedirect("/" + loginType + "/login" + queryString);
+ }
+ return;
+ }
+ }
+ chain.doFilter(req, res);
+ }
+
+ @Override
+ public void destroy() {
+ // Do nothing
+ }
+
+ @Override
+ public void init(FilterConfig arg0) throws ServletException {
+ // Do nothing
+ }
+}
diff --git a/src/main/java/org/t246osslab/easybuggy/core/filters/EncodingFilter.java b/src/main/java/org/t246osslab/easybuggy/core/filters/EncodingFilter.java
new file mode 100644
index 0000000..2644861
--- /dev/null
+++ b/src/main/java/org/t246osslab/easybuggy/core/filters/EncodingFilter.java
@@ -0,0 +1,47 @@
+package org.t246osslab.easybuggy.core.filters;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Servlet Filter for encoding
+ */
+@WebFilter(urlPatterns = { "/*" })
+public class EncodingFilter implements Filter {
+
+ /**
+ * Set the encoding to use for requests.
+ * "Shift_JIS" is intentionally set to the request to /mojibake.
+ *
+ * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
+ */
+ @Override
+ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
+ throws IOException, ServletException {
+ HttpServletRequest request = (HttpServletRequest) req;
+ if (!"/mojibake".equals(request.getRequestURI())) {
+ /* Set the default character encoding and content type to UTF-8 (except under /mojibake) */
+ req.setCharacterEncoding("UTF-8");
+ res.setContentType("text/html; charset=UTF-8");
+ }
+ chain.doFilter(req, res);
+ }
+
+ @Override
+ public void destroy() {
+ // Do nothing
+ }
+
+ @Override
+ public void init(FilterConfig arg0) throws ServletException {
+ // Do nothing
+ }
+}
diff --git a/src/main/java/org/t246osslab/easybuggy/core/filters/SecurityFilter.java b/src/main/java/org/t246osslab/easybuggy/core/filters/SecurityFilter.java
new file mode 100644
index 0000000..7aae575
--- /dev/null
+++ b/src/main/java/org/t246osslab/easybuggy/core/filters/SecurityFilter.java
@@ -0,0 +1,56 @@
+package org.t246osslab.easybuggy.core.filters;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Servlet Filter for security
+ */
+@WebFilter(urlPatterns = { "/*" })
+public class SecurityFilter implements Filter {
+
+ /**
+ * Prevent several security vulnerabilities.
+ *
+ * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
+ */
+ @Override
+ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
+ ServletException {
+ HttpServletRequest request = (HttpServletRequest) req;
+ HttpServletResponse response = (HttpServletResponse) res;
+ String target = request.getRequestURI();
+
+ /* Prevent clickjacking if target is not /admins/clickjacking ... */
+ if (!target.startsWith("/admins/clickjacking")) {
+ response.addHeader("X-FRAME-OPTIONS", "DENY");
+ }
+ /* Prevent Content-Type sniffing */
+ response.addHeader("X-Content-Type-Options", "nosniff");
+
+ /* Prevent XSS if target is not /xss ... */
+ if (!target.startsWith("/xss")) {
+ response.addHeader("X-XSS-Protection", "1; mode=block");
+ }
+ chain.doFilter(req, res);
+ }
+
+ @Override
+ public void destroy() {
+ // Do nothing
+ }
+
+ @Override
+ public void init(FilterConfig arg0) throws ServletException {
+ // Do nothing
+ }
+}
diff --git a/src/main/java/org/t246osslab/easybuggy/core/listeners/InitializationListener.java b/src/main/java/org/t246osslab/easybuggy/core/listeners/InitializationListener.java
new file mode 100644
index 0000000..2ea28af
--- /dev/null
+++ b/src/main/java/org/t246osslab/easybuggy/core/listeners/InitializationListener.java
@@ -0,0 +1,46 @@
+package org.t246osslab.easybuggy.core.listeners;
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.annotation.WebListener;
+
+import org.owasp.esapi.ESAPI;
+import org.t246osslab.easybuggy.core.utils.Closer;
+
+@WebListener
+public class InitializationListener implements ServletContextListener {
+ public void contextInitialized(ServletContextEvent event) {
+
+ /*
+ * Suppress noisy messages output by the ESAPI library. For more detail:
+ * https://stackoverflow.com/questions/45857064/how-to-suppress-messages-output-by-esapi-library
+ */
+ PrintStream printStream = null;
+ OutputStream outputStream = null;
+ PrintStream original = System.out;
+ try {
+ outputStream = new OutputStream() {
+ public void write(int b) {
+ // Do nothing
+ }
+ };
+ printStream = new PrintStream(outputStream);
+ System.setOut(printStream);
+ System.setErr(printStream);
+ ESAPI.encoder();
+ } catch (Exception e) {
+ // Do nothing
+ } finally {
+ System.setOut(original);
+ Closer.close(printStream, outputStream);
+ }
+ }
+
+ @Override
+ public void contextDestroyed(ServletContextEvent sce) {
+ // Do nothing
+ }
+}
diff --git a/src/main/java/org/t246osslab/easybuggy/core/model/User.java b/src/main/java/org/t246osslab/easybuggy/core/model/User.java
new file mode 100644
index 0000000..71a32b5
--- /dev/null
+++ b/src/main/java/org/t246osslab/easybuggy/core/model/User.java
@@ -0,0 +1,88 @@
+package org.t246osslab.easybuggy.core.model;
+
+import java.io.Serializable;
+import java.util.Date;
+
+public class User implements Serializable{
+
+ private static final long serialVersionUID = 1L;
+ private String userId = null;
+ private String name = null;
+ private String password = null;
+ private String secret = null;
+ private String phone = null;
+ private String mail = null;
+ private int loginFailedCount = 0;
+ private Date lastLoginFailedTime = null;
+
+ @Override
+ public String toString() {
+ return "User [userId=" + userId + ", name=" + name + ", password=" + password + ", secret=" + secret
+ + ", phone=" + phone + ", mail=" + mail + ", loginFailedCount=" + loginFailedCount
+ + ", lastLoginFailedTime=" + lastLoginFailedTime + "]";
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getSecret() {
+ return secret;
+ }
+
+ public void setSecret(String secret) {
+ this.secret = secret;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ public String getMail() {
+ return mail;
+ }
+
+ public void setMail(String mail) {
+ this.mail = mail;
+ }
+
+ public int getLoginFailedCount() {
+ return loginFailedCount;
+ }
+
+ public void setLoginFailedCount(int loginFailedCount) {
+ this.loginFailedCount = loginFailedCount;
+ }
+
+ public Date getLastLoginFailedTime() {
+ return lastLoginFailedTime;
+ }
+
+ public void setLastLoginFailedTime(Date lastLoginFailedTime) {
+ this.lastLoginFailedTime = lastLoginFailedTime;
+ }
+}
diff --git a/src/main/java/org/t246osslab/easybuggy/core/servlets/AbstractServlet.java b/src/main/java/org/t246osslab/easybuggy/core/servlets/AbstractServlet.java
new file mode 100644
index 0000000..507ff97
--- /dev/null
+++ b/src/main/java/org/t246osslab/easybuggy/core/servlets/AbstractServlet.java
@@ -0,0 +1,191 @@
+package org.t246osslab.easybuggy.core.servlets;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.owasp.esapi.ESAPI;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.t246osslab.easybuggy.core.utils.Closer;
+
+import java.io.PrintWriter;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+@SuppressWarnings("serial")
+public abstract class AbstractServlet extends HttpServlet {
+
+ protected Logger log = LoggerFactory.getLogger(this.getClass());
+
+ /**
+ * Send an HTTP response to the client.
+ *
+ * @param req HTTP servlet request.
+ * @param res HTTP servlet response.
+ * @param htmlTitle Title of HTML page.
+ * @param htmlBody Body of HTML page.
+ */
+ protected void responseToClient(HttpServletRequest req, HttpServletResponse res, String htmlTitle, String htmlBody) {
+ PrintWriter writer = null;
+ HttpSession session = req.getSession();
+ String userid = (String) session.getAttribute("userid");
+ Locale locale = req.getLocale();
+ try {
+ writer = res.getWriter();
+ writer.write("");
+ writer.write("");
+ if (htmlTitle != null) {
+ writer.write("" + htmlTitle + "");
+ }
+ writer.write("");
+ writer.write("");
+ writer.write("");
+ writer.write("");
+ writer.write("");
+ writer.write("");
+ writer.write("");
+
+ writer.write("");
+ writer.write("");
+ writer.write("