diff --git a/README.md b/README.md index accea5de..43bf7426 100644 --- a/README.md +++ b/README.md @@ -13,20 +13,19 @@ This tutorial with use CodeQL Analysis with Code Scanning in order to search for ## Instructions
-Create repository using the template +Create repository fork

-Begin by [creating a new repository from this template](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template). +Begin by [creating a new repository from a fork (public)](https://docs.github.com/en/get-started/quickstart/fork-a-repo) or [cloning the repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository). -Where creating the template repository make sure to do the following: +Where creating the forked repository, make sure to -1. Create a name for your demo -2. Select `Include all branches` -3. Create the repository from the template - - +1. Select the correct org / user account +2. Create a name for your new repository +3. Disable main branch only cloning +4. Create the repository from the template

@@ -50,21 +49,23 @@ Click `Set up code scanning`. #### Setup Workflow -Click the `Setup this workflow` button by CodeQL Analysis. +Click the `Setup` dropdown and select the Default CodeQL Analysis. - +![image](https://github.com/user-attachments/assets/294a1d2a-b58a-4874-bced-c22a76fe315a) -This will create a GitHub Actions Workflow file with CodeQL already set up. Since Java is a compiled language you will need to setup the build in later steps. See the [documentation](https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/running-codeql-code-scanning-in-your-ci-system) if you would like to configure CodeQL Analysis with a 3rd party CI system instead of using GitHub Actions. +This will trigger a CodeQL Scan without needing a workflow file. Since Java is a compiled language the file will use our out-of-the-box [Autobuild action](https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages) but if your application requires more customizable compilation steps, you can switch to the advanced setup and create a workflow file where you can input your desired steps. See the [documentation](https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/running-codeql-code-scanning-in-your-ci-system) if you would like to configure CodeQL Analysis with a 3rd party CI system instead of using GitHub Actions.

-Actions Workflow file +Actions Workflow file (No need to do anything!)

#### Actions Workflow +As we're going with the Default Setup, this file is not necessary but in case you're curious, here how it looks like: + The Actions Workflow file contains a number of different sections including: 1. Checking out the repository 2. Initializing the CodeQL Action @@ -84,7 +85,12 @@ Click `Start Commit` -> `Commit this file` to commit the changes to _main_ branc #### Workflow triggers -There are a [number of events](https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows) that can trigger a GitHub Actions workflow. In this example, the workflow will be triggered on +There are a [number of events](https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows) that can trigger a GitHub Actions workflow. + +In this example, with the default setup the triggers will be: +![image](https://github.com/user-attachments/assets/6bcc8f35-8f04-45e3-aa1f-82fce86d60ae) + +Whereas with the workflow, it will be triggered on: @@ -165,9 +171,27 @@ Click `show paths` in order to see the dataflow path that resulted in this alert

+

Fix the Security Alert (with Copilot) +

+In order to fix this specific alert, we will need to ensure parameters used in the SQL query is validated and sanitized. We will solve this with the power of Copilot! +

+Open the file [`IndexController.java`](./src/main/java/com/github/hackathon/advancedsecurityjava/Controllers/IndexController.java) in the `Controllers` folder and select line 40. Once highlighted, select `Shift` on your keyboard and click line 53. Finally, click on the Copilot icon that appears to the side of the highlighted code. -Fix the Security Alert +![image](https://github.com/user-attachments/assets/2251deb3-2498-4f2f-a355-e35b37de58a4) + +Ask Copilot the following prompt or feel free to try with a prompt of your own! +- English: Rewrite this method to prevent a SQL injection +- Spanish: Reescribe este método para prevenir SQL injection +Integrate the suggested code in your Index Controller. Make sure to click [Edit](https://docs.github.com/en/free-pro-team@latest/github/managing-files-in-a-repository/editing-files-in-your-repository) on the file. + +Click `Create a new branch for this commit and start a pull request`, name the branch `fix-sql-injection`, and create the Pull Request. + +
+
+

+

Fix the Security Alert (without Copilot) +

In order to fix this specific alert, we will need to ensure parameters used in the SQL query is validated and sanitized. Click on the `Code` tab and [Edit](https://docs.github.com/en/free-pro-team@latest/github/managing-files-in-a-repository/editing-files-in-your-repository) the file [`IndexController.java`](./src/main/java/com/github/hackathon/advancedsecurityjava/Controllers/IndexController.java) in the `Controllers` folder, replace the content with the file [`fixme`](./fixme). @@ -176,6 +200,12 @@ Click on the `Code` tab and [Edit](https://docs.github.com/en/free-pro-team@late Click `Create a new branch for this commit and start a pull request`, name the branch `fix-sql-injection`, and create the Pull Request. +
+
+

+

Re-Scan your code after new changes +

+ #### Pull Request Status Check In the Pull Request, you will notice that the CodeQL Analysis has started as a status check. Wait until it completes. @@ -210,7 +240,85 @@ Click on the security alert and notice that it details when the fix was made, by

+ +
+Prevent new Alerts in a Pull Request +

+ +#### Create Pull Request from new feature Branch + +Now that we have setup CodeQL Analysis and have fix a security alert, we can try to introduce an alert into a Pull Request. + +Create a new Pull Request with the base branch as your `main` branch and the compare branch as the `new-feature` branch. + + + +Make sure that the base branch is set to your own repositories `main` branch versus the original repository's `main` branch. + + +#### Pull Request Status Check + +Once the Pull Request has been created, you will notice that the CodeQL Analysis has started as a status check. Wait until it completes. + +After the Workflow has completed, the `Code Scanning Results / CodeQL` status check will have failed. +Notice that Code Scanning has detected that this Pull Request introduces a new security alert. + + + + +#### Alert Centric Notifications + +Directly in the Pull Request, you will notice that GitHub Code Scanning bot has left a review of the Pull Request with the security alert details. +This will help developers to quickly identify security issues introduced in their Pull Requests. + + + + +This also allows for collaboration between developers and security teams to discuss the security alert and how to remediate it. + + + +#### Security Alert Details + +Click on `Show more details` by the new `Code Scanning Alert` to jump to the `Security` tab and view the security alert details. + + + +Notice that the security alert was found `In pull request` and not in the `main` branch (production). + + +

+
+
+

(Bonus) Enable Secret Scanning

+

+Click on `Settings` and select `Code Security` from the menu on the left. +![image](https://github.com/user-attachments/assets/d56f94fb-5623-481f-b850-291248104304) + +Find the options for Secret Scanning and Push Protection and make sure they are both Enabled. When they are it should say disabled, similar to this image: + +![image](https://github.com/user-attachments/assets/23f92127-bef0-4107-91e2-00a802daff47) + +

+
+
+

(Bonus) Try to introduce a Secret

+

+ +Find yourself a secret that matches any of the [supported secrets](https://docs.github.com/en/code-security/secret-scanning/introduction/supported-secret-scanning-patterns#supported-secrets) and try to commit the value to the Repo. You could commit it to any file! Refer to the previous activities to refresh how Edit and Commit a change. + +If you received an error, you've done it right!! + +If you didn't receive an error, this may be why: +1. The secret is not supported out-of-the-box. For secrets not in the [supported secrets](https://docs.github.com/en/code-security/secret-scanning/introduction/supported-secret-scanning-patterns#supported-secrets) list, you will need to [create a Custom Pattern](https://docs.github.com/en/enterprise-cloud@latest/code-security/secret-scanning/using-advanced-secret-scanning-and-push-protection-features/custom-patterns/defining-custom-patterns-for-secret-scanning) first. +2. The secret was already leaked and you already have an Open Alert in your Security page. Why cry over spilled milk?! +3. Check again that Push Protection is enabled on your Repo! + +

+
+ + ## Next Steps Ready to talk about advanced security features for GitHub Enterprise? [Contact Sales](https://enterprise.github.com/contact) for more information! diff --git a/src/main/java/com/github/hackathon/advancedsecurityjava/Controllers/IndexController.java b/src/main/java/com/github/hackathon/advancedsecurityjava/Controllers/IndexController.java index 2a8439e9..f4f8e9f3 100644 --- a/src/main/java/com/github/hackathon/advancedsecurityjava/Controllers/IndexController.java +++ b/src/main/java/com/github/hackathon/advancedsecurityjava/Controllers/IndexController.java @@ -2,9 +2,9 @@ import java.sql.Connection; import java.sql.DriverManager; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Statement; import java.util.ArrayList; import java.util.List; @@ -28,31 +28,41 @@ public List getBooks(@RequestParam(name = "name", required = false) String @RequestParam(name = "read", required = false) Boolean bookread) { List books = new ArrayList(); - Statement statement = null; + PreparedStatement statement = null; + List parameters = new ArrayList<>(); try { // Init connection to DB connection = DriverManager.getConnection(Application.connectionString); - statement = connection.createStatement(); String query = null; if (bookname != null) { // Filter by book name - query = "SELECT * FROM Books WHERE name LIKE '%" + bookname + "%'"; + query = "SELECT * FROM Books WHERE name LIKE ?"; + parameters.add("%" + bookname + "%"); } else if (bookauthor != null) { // Filter by book author - query = "SELECT * FROM Books WHERE author LIKE '%" + bookauthor + "%'"; + query = "SELECT * FROM Books WHERE author LIKE ?"; + parameters.add("%" + bookauthor + "%"); } else if (bookread != null) { // Filter by if the book has been read or not Integer read = bookread ? 1 : 0; - query = "SELECT * FROM Books WHERE read = '" + read.toString() + "'"; + query = "SELECT * FROM Books WHERE read = ?"; + parameters.add(read.toString()); } else { // All books query = "SELECT * FROM Books"; } - ResultSet results = statement.executeQuery(query); + statement = connection.prepareStatement(query); + int index = 1; + for (String parameter : parameters) { + statement.setString(index, parameter); + index += 1; + } + + ResultSet results = statement.executeQuery(); while (results.next()) { Book book = new Book(results.getString("name"), results.getString("author"), (results.getInt("read") == 1)); @@ -76,4 +86,4 @@ public List getBooks(@RequestParam(name = "name", required = false) String } return books; } -} \ No newline at end of file +} diff --git a/src/main/java/com/github/hackathon/advancedsecurityjava/Controllers/SearchController.java b/src/main/java/com/github/hackathon/advancedsecurityjava/Controllers/SearchController.java new file mode 100644 index 00000000..88d54d64 --- /dev/null +++ b/src/main/java/com/github/hackathon/advancedsecurityjava/Controllers/SearchController.java @@ -0,0 +1,50 @@ +package com.github.hackathon.advancedsecurityjava.Controllers; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +import com.github.hackathon.advancedsecurityjava.Application; +import com.github.hackathon.advancedsecurityjava.Models.Book; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + + +@Controller +public class SearchController { + + @GetMapping("/search") + @ResponseBody + public List searchBooks(@RequestParam(name = "q", required = true) String search) { + List books = new ArrayList(); + + Application.logger.info("Search query: {}", search); + + String query = "SELECT * FROM Books WHERE name LIKE '%" + search + "%' OR author LIKE '%" + search + "%'"; + try(Connection connection = DriverManager.getConnection(Application.connectionString)) + { + try (Statement statement = connection.createStatement()) { + ResultSet results = statement.executeQuery(query); + + while (results.next()) { + Book book = new Book(results.getString("name"), results.getString("author"), (results.getInt("read") == 1)); + + books.add(book); + } + } catch (SQLException error) { + error.printStackTrace(); + } + } catch (SQLException error) { + error.printStackTrace(); + } + + return books; + } +} \ No newline at end of file