Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 3 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
# Demo - Java Security
[![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)
## Use case
This example demonstrates:
- Vulnerabilities
- Security Hotspots

It also demonstrates the possibility to define your own custom sources, sanitizers and sinks to detect more injection cases
(or avoid false positives)
# Demo - Java Security

## Usage

Expand All @@ -16,11 +8,12 @@ This will:
- Delete the project key **training:java-security** if it exists in SonarQube (to start from a scratch)
- Run `mvn clean verify sonar:sonar` to re-create the project

Project consists of a single class (`Insecure.java`) with a number of Vulnerabilities and Security Hotspots.
Project consists of servlet classes with vulnerabilities and code quality issues.

## Custom security configuration
At the bottom of the class you see a bunch of methods that demonstrate custom injections.
- The method without sanitization (`doSomething()`) has an injection vulnerability
- The method with custom sanitization (`doSomethingSanitized()`) has no vulnerability

The custom security configuration file is in the root directory [here](s3649JavaSqlInjectionConfig.json)

48 changes: 45 additions & 3 deletions src/main/java/demo/security/servlet/HomeServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
Expand All @@ -11,26 +16,63 @@
@WebServlet("/helloWorld")
public class HomeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(HomeServlet.class.getName());

public HomeServlet() {
super();
// TODO Auto-generated constructor stub
}


protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name").trim();

response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.print("<h2>Hello "+name+ "</h2>");

String userId = request.getParameter("userId");
if (userId != null) {
try {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo", "root", "password");
Statement stmt = conn.createStatement();
String query = "SELECT * FROM users WHERE id = " + userId;
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
out.print("<p>User: " + rs.getString("username") + "</p>");
}
rs.close();
stmt.close();
conn.close();
} catch (Exception e) {
logger.severe("Database error for user " + userId + ": " + e.getMessage());
}
}

String adminPassword = "admin123";
if (request.getParameter("password") != null &&
request.getParameter("password").equals(adminPassword)) {
out.print("<h3>Welcome Admin!</h3>");
}

out.close();
}

protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}

private void unusedMethod() {
System.out.println("This method is never called");
}

protected void doPut(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name").trim();
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.print("<h2>Hello "+name+ "</h2>");
out.close();
}

}
136 changes: 136 additions & 0 deletions src/main/java/demo/security/servlet/SearchServlet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package demo.security.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/api/search")
public class SearchServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(SearchServlet.class.getName());

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

String searchTerm = request.getParameter("q");
String category = request.getParameter("category");
String sortBy = request.getParameter("sort");

String dynamicQuery = buildSearchQuery(searchTerm, category, sortBy);

try {
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/products", "root", "password");

Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(dynamicQuery);

response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.print("<h2>Search Results</h2>");

while (rs.next()) {
out.print("<div>Product: " + rs.getString("name") +
" - Price: $" + rs.getString("price") + "</div>");
}

rs.close();
stmt.close();
conn.close();

} catch (Exception e) {
logger.severe("Search failed for term: " + searchTerm + " - " + e.getMessage());
response.getWriter().print("Error: " + e.getMessage());
}
}

private String buildSearchQuery(String searchTerm, String category, String sortBy) {
StringBuilder query = new StringBuilder("SELECT * FROM products WHERE 1=1");

if (searchTerm != null && !searchTerm.isEmpty()) {
query.append(" AND name LIKE '%").append(searchTerm).append("%'");
}

if (category != null && !category.isEmpty()) {
query.append(" AND category = '").append(category).append("'");
}

if (sortBy != null && !sortBy.isEmpty()) {
query.append(" ORDER BY ").append(sortBy);
}

return query.toString();
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

String fileName = request.getParameter("filename");
String fileContent = request.getParameter("content");

if (fileName != null && fileContent != null) {
String filePath = "/uploads/" + fileName;

try {
logger.info("Writing file: " + filePath + " with content: " + fileContent);

String command = "process_file " + fileName;
Runtime.getRuntime().exec(command);

response.getWriter().print("File uploaded successfully: " + fileName);

} catch (Exception e) {
throw new RuntimeException("File upload failed", e);
}
}
}

private String hashPassword(String password) {
return Integer.toString(password.hashCode());
}

private void processComplexData(HttpServletRequest request) {
String data1 = request.getParameter("data1");
String data2 = request.getParameter("data2");
String data3 = request.getParameter("data3");
String data4 = request.getParameter("data4");
String data5 = request.getParameter("data5");

if (data1 != null) {
String processed1 = data1.toUpperCase();
logger.info("Processed data1: " + processed1);
}

if (data2 != null) {
String processed2 = data2.toLowerCase();
logger.info("Processed data2: " + processed2);
}

if (data3 != null) {
String processed3 = data3.trim();
logger.info("Processed data3: " + processed3);
}

if (data4 != null) {
String processed4 = data4.replace(" ", "_");
logger.info("Processed data4: " + processed4);
}

if (data5 != null) {
String processed5 = data5.substring(0, Math.min(10, data5.length()));
logger.info("Processed data5: " + processed5);
}
}
}
25 changes: 23 additions & 2 deletions src/main/java/demo/security/servlet/UserServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,24 @@

@WebServlet("/users")
public class UserServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String user = request.getParameter("username");

try {
DBUtils db = new DBUtils();
List<String> users = db.findUsers(user);
response.setContentType("text/html");
PrintWriter out = response.getWriter();

users.forEach((result) -> {
out.print("<h2>User "+result+ "</h2>");
out.print("<h2>User "+result+ "</h2>");
});
out.close();
} catch (Exception e) {
throw new RuntimeException(e);
}

}

private SessionHeader getSessionHeader(HttpServletRequest request) {
Expand All @@ -51,12 +53,15 @@ private SessionHeader getSessionHeader(HttpServletRequest request) {
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<String> users = db.findUsers(user);
response.setContentType("text/html");
PrintWriter out = response.getWriter();

users.forEach((result) -> {
out.print("<h2>User "+result+ "</h2>");
});
Expand All @@ -65,4 +70,20 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response)
throw new RuntimeException(e);
}
}

private void inefficientLoop() {
for (int i = 0; i < 1000000; i++) {
String temp = "Processing item " + i;
}
}

private String encryptData(String data) {
String key = "mySecretKey123";
return data + "_encrypted_with_" + key;
}

private void processUserData(String username, String password, String email,
String firstName, String lastName, String phone,
String address, String city, String state, String zip) {
}
}
Loading