diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
new file mode 100644
index 0000000..6552b2d
--- /dev/null
+++ b/.github/workflows/maven.yml
@@ -0,0 +1,55 @@
+# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
+# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
+
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+
+name: SonarQube Analyze
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ types: [opened, synchronize, reopened]
+ workflow_dispatch:
+
+jobs:
+ build:
+ name: Build
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
+ - name: Set up JDK 17
+ uses: actions/setup-java@v3
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+ cache: maven
+ - name: Cache SonarQube packages
+ uses: actions/cache@v1
+ with:
+ path: ~/.sonar/cache
+ key: ${{ runner.os }}-sonar
+ restore-keys: ${{ runner.os }}-sonar
+ - name: Cache Maven packages
+ uses: actions/cache@v1
+ with:
+ path: ~/.m2
+ key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
+ restore-keys: ${{ runner.os }}-m2
+ - name: Build with Maven and analyze with SonarQube
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+ SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
+ run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=demo:java-security
+ #run: mvn -B package --file pom.xml
+
+ # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive
+ #- name: Update dependency graph
+ # uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6
diff --git a/.gitignore b/.gitignore
index 6a5b15a..a12c01a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,3 +26,4 @@ hs_err_pid*
#IDEs
.idea/
.vscode/
+java-security.iml
diff --git a/README.md b/README.md
index c9f5cde..f27ac69 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,9 @@
# Demo - Java Security
+SonarQube:
+[![Quality Gate Status](https://nautilus.sonarqube.org/api/project_badges/measure?project=demo%3Ajava-security&metric=alert_status&token=squ_1e4f3504bdc994f093721895e070abe7c11b1632)](https://nautilus.sonarqube.org/dashboard?id=demo%3Ajava-security) [![Maintainability Rating](https://nautilus.sonarqube.org/api/project_badges/measure?project=demo%3Ajava-security&metric=sqale_rating&token=squ_1e4f3504bdc994f093721895e070abe7c11b1632)](https://nautilus.sonarqube.org/dashboard?id=demo%3Ajava-security) [![Reliability Rating](https://nautilus.sonarqube.org/api/project_badges/measure?project=demo%3Ajava-security&metric=reliability_rating&token=squ_1e4f3504bdc994f093721895e070abe7c11b1632)](https://nautilus.sonarqube.org/dashboard?id=demo%3Ajava-security) [![Security Rating](https://nautilus.sonarqube.org/api/project_badges/measure?project=demo%3Ajava-security&metric=security_rating&token=squ_1e4f3504bdc994f093721895e070abe7c11b1632)](https://nautilus.sonarqube.org/dashboard?id=demo%3Ajava-security) [![Security Hotspots](https://nautilus.sonarqube.org/api/project_badges/measure?project=demo%3Ajava-security&metric=security_hotspots&token=squ_1e4f3504bdc994f093721895e070abe7c11b1632)](https://nautilus.sonarqube.org/dashboard?id=demo%3Ajava-security)
+
+SonarCloud:
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=SonarCloud-Demos_demo-java-security&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=SonarCloud-Demos_demo-java-security)
## Use case
diff --git a/credentials.properties b/credentials.properties
new file mode 100644
index 0000000..e86d368
--- /dev/null
+++ b/credentials.properties
@@ -0,0 +1,2 @@
+keyId=AKIA6HMXNBHDXXNYUMIX
+aws_secret_access_key=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
diff --git a/pom.xml b/pom.xml
index 6c17931..e90e298 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,6 +33,11 @@
commons-io
2.11.0
+
+ commons-codec
+ commons-codec
+ 1.16.0
+
javax.servlet
javax.servlet-api
@@ -50,6 +55,24 @@
junit
4.13.2
test
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+ maven-plugin
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.10.0
+ test
+
+
+ org.mockito
+ mockito-all
+ 1.10.19
+ test
@@ -78,6 +101,11 @@
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
@@ -86,6 +114,11 @@
sonar-maven-plugin
3.11.0.3922
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
diff --git a/src/main/java/demo/security/servlet/UserServlet.java b/src/main/java/demo/security/servlet/UserServlet.java
index 9159e35..66317ed 100644
--- a/src/main/java/demo/security/servlet/UserServlet.java
+++ b/src/main/java/demo/security/servlet/UserServlet.java
@@ -1,11 +1,15 @@
package demo.security.servlet;
import demo.security.util.DBUtils;
+import demo.security.util.SessionHeader;
+import org.apache.commons.codec.binary.Base64;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.ObjectInputStream;
import java.io.PrintWriter;
import java.util.List;
@@ -14,7 +18,6 @@ public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String user = request.getParameter("username");
- String query = "SELECT userid FROM users WHERE username = '" + user + "'";
try {
DBUtils db = new DBUtils();
List users = db.findUsers(user);
@@ -30,8 +33,36 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t
}
+ private SessionHeader getSessionHeader(HttpServletRequest request) {
+ String sessionAuth = request.getHeader("Session-Auth");
+ if (sessionAuth != null) {
+ try {
+ byte[] decoded = Base64.decodeBase64(sessionAuth);
+ ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(decoded));
+ return (SessionHeader) in.readObject();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ return null;
+ }
+
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
-
+ SessionHeader sessionHeader = getSessionHeader(request);
+ if (sessionHeader == null) return;
+ String user = sessionHeader.getUsername();
+ try {
+ DBUtils db = new DBUtils();
+ List users = db.findUsers(user);
+ response.setContentType("text/html");
+ PrintWriter out = response.getWriter();
+ users.forEach((result) -> {
+ out.print("User "+result+ "
");
+ });
+ out.close();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
}
}
diff --git a/src/main/java/demo/security/util/SessionHeader.java b/src/main/java/demo/security/util/SessionHeader.java
new file mode 100644
index 0000000..2a18331
--- /dev/null
+++ b/src/main/java/demo/security/util/SessionHeader.java
@@ -0,0 +1,14 @@
+package demo.security.util;
+import java.io.Serializable;
+public class SessionHeader implements Serializable {
+ private String username;
+ private String sessionId;
+ public SessionHeader(String username, String sessionId) {
+ this.username = username;
+ this.sessionId = sessionId;
+ }
+ public String getUsername() { return this.username; }
+ public void setUsername(String username) { this.username = username; }
+ public String getSessionId() { return this.sessionId; }
+ public void setSessionId(String sessionId) { this.sessionId = sessionId; }
+}
\ No newline at end of file
diff --git a/src/main/java/demo/security/util/Utils.java b/src/main/java/demo/security/util/Utils.java
index a73c6f5..c68b801 100644
--- a/src/main/java/demo/security/util/Utils.java
+++ b/src/main/java/demo/security/util/Utils.java
@@ -3,16 +3,18 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.FileUtils;
+import javax.crypto.Cipher;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.File;
import java.io.IOException;
+import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.nio.file.Paths;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
+import java.security.*;
public class Utils {
@@ -37,4 +39,14 @@ public static void executeJs(String input) throws ScriptException {
ScriptEngine engine = manager.getEngineByName("JavaScript");
engine.eval(input);
}
+
+ public static void encrypt(byte[] key, byte[] ptxt) throws Exception {
+ byte[] nonce = "7cVgr5cbdCZV".getBytes("UTF-8");
+
+ Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+ SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
+ GCMParameterSpec gcmSpec = new GCMParameterSpec(128, nonce);
+
+ cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmSpec); // Noncompliant
+ }
}
diff --git a/src/test/java/WebUtilsTest.java b/src/test/java/WebUtilsTest.java
new file mode 100644
index 0000000..02b60c2
--- /dev/null
+++ b/src/test/java/WebUtilsTest.java
@@ -0,0 +1,34 @@
+import demo.security.util.WebUtils;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import javax.servlet.http.HttpServletRequest;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.when;
+
+public class WebUtilsTest {
+
+ @Test
+ public void getSessionId_withValidRequest() {
+ HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
+ when(request.getRequestedSessionId()).thenReturn("validSessionId");
+
+ WebUtils.getSessionId(request);
+ }
+
+ @Test
+ public void getSessionId_withNullSessionId() {
+ HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
+ when(request.getRequestedSessionId()).thenReturn(null);
+
+ WebUtils.getSessionId(request);
+ }
+
+ @Test
+ public void getSessionId_withIOException() {
+ HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
+ when(request.getRequestedSessionId()).thenThrow(new RuntimeException());
+
+ assertThrows(RuntimeException.class, () -> WebUtils.getSessionId(request));
+ }
+}
\ No newline at end of file