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
22 changes: 22 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## Goal
<!-- What is the purpose of this PR? Link to the lab/task if relevant. -->
-

## Changes
<!-- What did you change? Keep it bullet-pointed and concrete. -->
-

## Testing
<!-- How did you verify it works? Commands, screenshots, manual checks. -->
-

## Artifacts & Screenshots
<!-- Links to files in the repo (e.g., labs/submission1.md) and any screenshots/API snippets. -->
-

---

### Checklist
- [ ] PR title is clear and descriptive
- [ ] Docs/readme updated if needed
- [ ] No secrets, credentials, or large temporary files included
23 changes: 23 additions & 0 deletions labs/lab5/analysis/correlation.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
=== SAST/DAST Correlation Report ===

Security Testing Results Summary:

SAST (Semgrep): 25 code-level findings
DAST (ZAP authenticated): 0 alerts
DAST (Nuclei): 0 template matches
DAST (Nikto): 14 server issues
DAST (SQLmap): 1 SQL injection vulnerabilities

Key Insights:

SAST (Static Analysis):
- Finds code-level vulnerabilities before deployment
- Detects: hardcoded secrets, SQL injection patterns, insecure crypto
- Fast feedback in development phase

DAST (Dynamic Analysis):
- Finds runtime configuration and deployment issues
- Detects: missing security headers, authentication flaws, server misconfigs
- Authenticated scanning reveals much more attack surface

Recommendation: Use BOTH approaches for comprehensive security coverage
7 changes: 7 additions & 0 deletions labs/lab5/analysis/dast-matrix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
| Tool | Findings | Severity Breakdown | Best Use Case |
|---|---:|---|---|
| ZAP (auth) | 0 | High:0 Med:0 Low:0 Info:0 | Comprehensive scan + auth + active/passive |
| ZAP (noauth) | 26 | High:0 Med:4 Low:10 Info:12 | Public surface baseline |
| Nuclei | 0 | n/a | Fast template-based checks (known issues/CVEs) |
| Nikto | 14 | n/a | Server misconfig/headers/default files |
| SQLmap | 1 | n/a | Deep SQLi confirmation + extraction |
10 changes: 10 additions & 0 deletions labs/lab5/analysis/dast-summary.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
=== DAST Summary ===

ZAP (noauth): Total=26 High=0 Med=4 Low=10 Info=12
ZAP (auth): Total=0 High=0 Med=0 Low=0 Info=0

Nuclei: Total matches=0

Nikto: server issues=14
SQLmap: findings(rows in results-*.csv)=1
CSV: C:\Users\Admin\Desktop\Code\DevSecOps-Intro\labs\lab5\sqlmap\results-03052026_1101pm.csv
2 changes: 2 additions & 0 deletions labs/lab5/analysis/sast-analysis.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
=== SAST Analysis Report ===
25
7 changes: 7 additions & 0 deletions labs/lab5/analysis/semgrep-top5.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
| # | Rule | Severity | File:Line | Message |
|---:|---|---|---|---|
| 1 | javascript.sequelize.security.audit.sequelize-injection-express.express-sequelize-injection | **ERROR** | /src/data/static/codefixes/dbSchemaChallenge_1.ts:5 | Detected a sequelize statement that is tainted by user-input. This could lead to SQL injection if the variable is user-controlled and is not properly sanitiz... |
| 2 | javascript.sequelize.security.audit.sequelize-injection-express.express-sequelize-injection | **ERROR** | /src/data/static/codefixes/dbSchemaChallenge_3.ts:11 | Detected a sequelize statement that is tainted by user-input. This could lead to SQL injection if the variable is user-controlled and is not properly sanitiz... |
| 3 | javascript.sequelize.security.audit.sequelize-injection-express.express-sequelize-injection | **ERROR** | /src/data/static/codefixes/unionSqlInjectionChallenge_1.ts:6 | Detected a sequelize statement that is tainted by user-input. This could lead to SQL injection if the variable is user-controlled and is not properly sanitiz... |
| 4 | javascript.sequelize.security.audit.sequelize-injection-express.express-sequelize-injection | **ERROR** | /src/data/static/codefixes/unionSqlInjectionChallenge_3.ts:10 | Detected a sequelize statement that is tainted by user-input. This could lead to SQL injection if the variable is user-controlled and is not properly sanitiz... |
| 5 | javascript.sequelize.security.audit.sequelize-injection-express.express-sequelize-injection | **ERROR** | /src/routes/login.ts:34 | Detected a sequelize statement that is tainted by user-input. This could lead to SQL injection if the variable is user-controlled and is not properly sanitiz... |
12 changes: 12 additions & 0 deletions labs/lab5/analysis/zap-compare.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
=== ZAP Auth vs No-Auth Comparison ===

No-Auth:
URLs discovered (from log): 95
Alerts (HTML): Total=26 High=0 Med=4 Low=10 Info=12

Auth:
Spider URLs (from log): 112
AJAX Spider URLs (from log): 545
Alerts (HTML): Total=0 High=0 Med=0 Low=0 Info=0

Admin/authenticated endpoints examples: N/A
15 changes: 15 additions & 0 deletions labs/lab5/nikto/nikto-results.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
- Nikto v2.1.5/2.1.5
+ Target Host: host.docker.internal
+ Target Port: 3000
+ GET /: Server leaks inodes via ETags, header found with file /, fields: 0xW/124fa 0x19cc006165a
+ GET /: Uncommon header 'x-recruiting' found, with contents: /#/jobs
+ GET /: Uncommon header 'x-frame-options' found, with contents: SAMEORIGIN
+ GET /: Uncommon header 'access-control-allow-origin' found, with contents: *
+ GET /: Uncommon header 'feature-policy' found, with contents: payment 'self'
+ GET /: Uncommon header 'x-content-type-options' found, with contents: nosniff
+ GET //ftp/: File/dir '/ftp/' in robots.txt returned a non-forbidden or redirect HTTP code (200)
+ GET /robots.txt: "robots.txt" contains 1 entry which should be manually viewed.
+ OPTIONS *: Uncommon header 'access-control-allow-methods' found, with contents: GET,HEAD,PUT,PATCH,POST,DELETE
+ -3092: GET /css: /css: This might be interesting...
+ -3092: GET /ftp/: /ftp/: This might be interesting...
+ -3092: GET /public/: /public/: This might be interesting...
3,238 changes: 3,238 additions & 0 deletions labs/lab5/report-auth.html

Large diffs are not rendered by default.

81 changes: 81 additions & 0 deletions labs/lab5/scripts/compare_zap.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
$ErrorActionPreference = "Stop"

$Lab5Dir = Resolve-Path (Join-Path $PSScriptRoot "..")
$ZapDir = Join-Path $Lab5Dir "zap"
$AnaDir = Join-Path $Lab5Dir "analysis"
New-Item -ItemType Directory -Force -Path $AnaDir | Out-Null

$NoAuthLog = Join-Path $ZapDir "zap-noauth.log"
$AuthLog = Join-Path $ZapDir "zap-auth.log"
$NoAuthReport = Join-Path $ZapDir "report-noauth.html"
$AuthReport = Join-Path $ZapDir "report-auth.html"

function Get-TextOrEmpty([string]$p){ if(Test-Path $p){Get-Content -Raw -LiteralPath $p}else{""} }

function FirstInt([string]$t, [string[]]$pats){
foreach($p in $pats){
$m=[regex]::Match($t,$p,[Text.RegularExpressions.RegexOptions]::IgnoreCase)
if($m.Success){ return [int]$m.Groups[1].Value }
}
return $null
}

function ZapCounts([string]$htmlPath){
if(!(Test-Path $htmlPath)){ return @{High=0;Med=0;Low=0;Info=0;Total=0} }
$h=Get-Content -Raw -LiteralPath $htmlPath -Encoding UTF8
$high=[regex]::Matches($h,'class="risk-3"').Count
$med =[regex]::Matches($h,'class="risk-2"').Count
$low =[regex]::Matches($h,'class="risk-1"').Count
$info=[regex]::Matches($h,'class="risk-0"').Count
$high=[int]($high/2); $med=[int]($med/2); $low=[int]($low/2); $info=[int]($info/2)
return @{High=$high;Med=$med;Low=$low;Info=$info;Total=($high+$med+$low+$info)}
}

function AdminEndpoints([string]$htmlPath,[int]$max=10){
if(!(Test-Path $htmlPath)){ return @() }
$h=Get-Content -Raw -LiteralPath $htmlPath -Encoding UTF8
$ms=[regex]::Matches($h,'/rest/admin/[A-Za-z0-9\-\._~/%\?\=&]+')
$set=New-Object 'System.Collections.Generic.HashSet[string]'
foreach($m in $ms){ [void]$set.Add($m.Value) }
return $set | Select-Object -First $max
}

$noAuthText = Get-TextOrEmpty $NoAuthLog
$authText = Get-TextOrEmpty $AuthLog

$noAuthUrls = FirstInt $noAuthText @(
'Job spider found\s+(\d+)\s+URLs',
'found\s+(\d+)\s+URLs',
'Total of\s+(\d+)\s+URLs'
)
$authSpider = FirstInt $authText @('Job spider found\s+(\d+)\s+URLs')
$authAjax = FirstInt $authText @('Job spiderAjax found\s+(\d+)\s+URLs','AJAX spider.*found\s+(\d+)\s+URLs')

$noAuthAlerts = ZapCounts $NoAuthReport
$authAlerts = ZapCounts $AuthReport
$admin = AdminEndpoints $AuthReport 12

$out = @()
$out += "=== ZAP Auth vs No-Auth Comparison ==="
$out += ""
$out += "No-Auth:"
$out += (" URLs discovered (from log): {0}" -f ($(if($null -eq $noAuthUrls){"N/A"}else{$noAuthUrls})))
$out += (" Alerts (HTML): Total={0} High={1} Med={2} Low={3} Info={4}" -f $noAuthAlerts.Total,$noAuthAlerts.High,$noAuthAlerts.Med,$noAuthAlerts.Low,$noAuthAlerts.Info)
$out += ""
$out += "Auth:"
$out += (" Spider URLs (from log): {0}" -f ($(if($null -eq $authSpider){"N/A"}else{$authSpider})))
$out += (" AJAX Spider URLs (from log): {0}" -f ($(if($null -eq $authAjax){"N/A"}else{$authAjax})))
$out += (" Alerts (HTML): Total={0} High={1} Med={2} Low={3} Info={4}" -f $authAlerts.Total,$authAlerts.High,$authAlerts.Med,$authAlerts.Low,$authAlerts.Info)
$out += ""

if($admin.Count -gt 0){
$out += "Admin/authenticated endpoints examples:"
foreach($e in $admin){ $out += " - $e" }
}else{
$out += "Admin/authenticated endpoints examples: N/A"
}

$outPath = Join-Path $AnaDir "zap-compare.txt"
$out -join "`r`n" | Set-Content -LiteralPath $outPath -Encoding UTF8
$out -join "`r`n"
"Saved: $outPath"
75 changes: 75 additions & 0 deletions labs/lab5/scripts/correlation.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
$ErrorActionPreference = "Stop"

$Lab5Dir = Resolve-Path (Join-Path $PSScriptRoot "..")
$AnaDir = Join-Path $Lab5Dir "analysis"
New-Item -ItemType Directory -Force -Path $AnaDir | Out-Null

$Semgrep = Join-Path $Lab5Dir "semgrep\semgrep-results.json"
$ZapAuth = Join-Path $Lab5Dir "zap\report-auth.html"
$Nuclei = Join-Path $Lab5Dir "nuclei\nuclei-results.json"
$Nikto = Join-Path $Lab5Dir "nikto\nikto-results.txt"
$SqlmapDir = Join-Path $Lab5Dir "sqlmap"

function Count-Semgrep($p){
if(!(Test-Path $p)){ return 0 }
$o = Get-Content -Raw -LiteralPath $p -Encoding UTF8 | ConvertFrom-Json
return @($o.results).Count
}
function Count-Zap($p){
if(!(Test-Path $p)){ return 0 }
$h=Get-Content -Raw -LiteralPath $p -Encoding UTF8
$med=[regex]::Matches($h,'class="risk-2"').Count
$high=[regex]::Matches($h,'class="risk-3"').Count
return [int](($med/2)+($high/2))
}
function Count-Lines($p){
if(!(Test-Path $p)){ return 0 }
return (Get-Content -LiteralPath $p -Encoding UTF8 | Where-Object { $_.Trim().Length -gt 0 }).Count
}
function Count-Nikto($p){
if(!(Test-Path $p)){ return 0 }
return (Get-Content -LiteralPath $p -Encoding UTF8 | Where-Object { $_.StartsWith("+ ") }).Count
}
function Count-Sqlmap($root){
if(!(Test-Path $root)){ return 0 }
$csv = Get-ChildItem -Path $root -Recurse -Filter "results-*.csv" -ErrorAction SilentlyContinue | Select-Object -First 1
if(-not $csv){ return 0 }
$lines = Get-Content -LiteralPath $csv.FullName -Encoding UTF8 | Where-Object { $_.Trim().Length -gt 0 }
return [Math]::Max(0,$lines.Count-1)
}

$sast = Count-Semgrep $Semgrep
$zap = Count-Zap $ZapAuth
$nuc = Count-Lines $Nuclei
$nik = Count-Nikto $Nikto
$sql = Count-Sqlmap $SqlmapDir

$out = @()
$out += "=== SAST/DAST Correlation Report ==="
$out += ""
$out += "Security Testing Results Summary:"
$out += ""
$out += "SAST (Semgrep): $sast code-level findings"
$out += "DAST (ZAP authenticated): $zap alerts"
$out += "DAST (Nuclei): $nuc template matches"
$out += "DAST (Nikto): $nik server issues"
$out += "DAST (SQLmap): $sql SQL injection vulnerabilities"
$out += ""
$out += "Key Insights:"
$out += ""
$out += "SAST (Static Analysis):"
$out += " - Finds code-level vulnerabilities before deployment"
$out += " - Detects: hardcoded secrets, SQL injection patterns, insecure crypto"
$out += " - Fast feedback in development phase"
$out += ""
$out += "DAST (Dynamic Analysis):"
$out += " - Finds runtime configuration and deployment issues"
$out += " - Detects: missing security headers, authentication flaws, server misconfigs"
$out += " - Authenticated scanning reveals much more attack surface"
$out += ""
$out += "Recommendation: Use BOTH approaches for comprehensive security coverage"

$path = Join-Path $AnaDir "correlation.txt"
$out -join "`r`n" | Set-Content -LiteralPath $path -Encoding UTF8
$out -join "`r`n"
"Saved: $path"
Loading