diff --git a/.github/scripts/fortify-wait-fpr.js b/.github/scripts/fortify-wait-fpr.js new file mode 100644 index 0000000..47b761c --- /dev/null +++ b/.github/scripts/fortify-wait-fpr.js @@ -0,0 +1,63 @@ +const fs = require('node:fs'); +const timers = require('node:timers/promises'); + +const scanId = process.argv[2]; +const FORTIFY_USER = process.env.FORTIFY_USER; +const FORTIFY_TOKEN = process.env.FORTIFY_TOKEN; +const FORTIFY_TENANT = process.env.FORTIFY_TENANT; + +async function main() { + const tokenData = await fetch('https://api.ams.fortify.com/oauth/token', { + method: 'POST', + headers: {'content-type': 'application/x-www-form-urlencoded'}, + body: `grant_type=password&scope=api-tenant&username=${FORTIFY_TENANT}\\${FORTIFY_USER}&password=${FORTIFY_TOKEN}&security_code=` + }).then(r => r.json()); + + if (!tokenData || !tokenData.access_token) { + throw new Error("Can't authenticate, check credentials."); + } + + const token = tokenData.access_token; + + while (true) { + const summaryResponse = await fetch(`https://api.ams.fortify.com/api/v3/scans/${scanId}/summary`, { + headers: {Authorization: `Bearer ${token}`} + }); + + if (summaryResponse.status === 200) { + const summaryData = await summaryResponse.json(); + + if (summaryData.analysisStatusType === 'Completed') { + break; + } + console.log(`Scan status: ${summaryData.analysisStatusType}...`); + } else { + console.log(`Scan API status: ${summaryResponse.status}...`); + } + await timers.setTimeout(5000); + } + + let buffer; + + while (true) { + const fileResponse = await fetch(`https://api.ams.fortify.com/api/v3/scans/${scanId}/fpr`, { + headers: {Authorization: `Bearer ${token}`} + }); + + if (fileResponse.status === 200) { + buffer = await fileResponse.arrayBuffer(); + break; + } + + if ([202, 429].includes(fileResponse.status)) { + console.log(`Waiting FRP file...`); + await timers.setTimeout(5000); + } else { + throw new Error(`Unexpected status code from fpr endpoint: ${fileResponse.status}.`); + } + } + + fs.writeFileSync('./scandata.fpr', Buffer.from(buffer)); +} + +main().catch(console.error); diff --git a/.github/workflows/fortify.yml b/.github/workflows/fortify.yml new file mode 100644 index 0000000..9036fc7 --- /dev/null +++ b/.github/workflows/fortify.yml @@ -0,0 +1,70 @@ +on: [pull_request] +permissions: + actions: write + checks: write + contents: write + pull-requests: write + statuses: write + +jobs: + test_fortify: + runs-on: ubuntu-latest + steps: + - name: Setup Java on this machine + uses: actions/setup-java@v3 + with: + distribution: "oracle" + java-version: "19" + - name: Setup Maven on this machine + uses: stCarolas/setup-maven@v4.5 + with: + maven-version: 3.8.6 + - name: Setup Node on this machine + uses: actions/setup-node@v3.6.0 + with: + node-version: 18 + - name: Install sed + run: sudo apt-get update && sudo apt-get install -y sed + + - name: Checkout repo to get code + uses: actions/checkout@v3 + + - name: Download Fortify uploader CLI + run: | + wget https://tools.fortify.com/scancentral/Fortify_ScanCentral_Client_21.2.0_x64.zip -O fcs.zip + unzip fcs.zip + chmod +x bin/scancentral + wget https://github.com/fod-dev/fod-uploader-java/releases/download/v5.4.0/FodUpload.jar -O FodUpload.jar + + - name: Run Fortify SAST scan + run: | + ./bin/scancentral package -bt mvn -o fortify_package.zip + + UPLOAD_OUTPUT=$(java -jar FodUpload.jar \ + -z fortify_package.zip \ + -ep SingleScanOnly \ + -portalurl https://ams.fortify.com/ \ + -apiurl https://api.ams.fortify.com/ \ + -userCredentials ${{ secrets.FORTIFY_USER }} ${{ secrets.FORTIFY_TOKEN }} \ + -tenantCode ${{ secrets.FORTIFY_TENANT }} \ + -releaseId ${{ secrets.FORTIFY_RELEASE_ID }} \ + -pp Queue) + SCAN_ID=$(echo "$UPLOAD_OUTPUT" | sed -n 's/Scan \([0-9]*\).*$/\1/p') + + FORTIFY_USER=${{ secrets.FORTIFY_USER }} FORTIFY_TOKEN=${{ secrets.FORTIFY_TOKEN }} FORTIFY_TENANT=${{ secrets.FORTIFY_TENANT }} node .github/scripts/fortify-wait-fpr.js "$SCAN_ID" + - name: Archive fpr + if: always() + uses: actions/upload-artifact@v3 + with: + name: fpr + path: scandata.fpr + + - name: Run Mobb on the findings and get fixes + if: always() + uses: mobb-dev/action/review@v1.1 + with: + report-file: "scandata.fpr" + api-key: ${{ secrets.MOBB_API_TOKEN }} + github-token: ${{ secrets.GITHUB_TOKEN }} + scanner: fortify + mobb-project-name: Action diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 5a3246f..0000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,28 +0,0 @@ -on: [pull_request] -permissions: - contents: read - checks: write - actions: write - statuses: write - - -jobs: - test_job: - runs-on: ubuntu-latest - steps: - - name: Checkout repo to get code - uses: actions/checkout@v3 - - name: Run Snyk SAST scan - run: - npx snyk auth ${{ secrets.SNYK_API_KEY }} - - npx snyk code test --sarif-file-output=/home/runner/report.json ./ - - shell: bash -l {0} - - name: Mobb action step - if: failure() - uses: mobb-dev/action@v1 - with: - report-file: "/home/runner/report.json" - api-key: ${{ secrets.MOBB_API_TOKEN }} - github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..bc805e6 --- /dev/null +++ b/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + testgroup + testartifact + 1.0-SNAPSHOT + jar + testproj + + + true + UTF-8 + + + + + javax.servlet + javax.servlet-api + 3.0.1 + provided + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.5.1 + + 17 + 17 + + + + + diff --git a/src/main/java/SQLInjectionExample.java b/src/main/java/SQLInjectionExample.java index 16fca15..751f7b6 100644 --- a/src/main/java/SQLInjectionExample.java +++ b/src/main/java/SQLInjectionExample.java @@ -1,14 +1,22 @@ -import java.sql.*; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.Statement; -public class SQLInjectionExample { - public static void main(String[] args) throws SQLException { - String userInputA = args[1]; +public class SQLInjectionExample extends HttpServlet { + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { + try { + Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/db"); - Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/db"); - + String query = "SELECT * FROM users WHERE username = '" + request.getParameter("username") + "';"; + Statement stmt = con.createStatement(); - String query = "SELECT * FROM users WHERE username = '" + userInputA + "';"; - Statement stmt = con.createStatement(); - ResultSet rs = stmt.executeQuery(query); + stmt.executeQuery(query); + } catch (Exception e) { + throw new ServletException(e); + } } }