100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Web Application Security
50 minintermediate

Remediating Findings and Re-Testing Fixes

What You'll Build

In this phase you will fix the vulnerabilities you confirmed, applying the root-cause remediations taught throughout the course, and then re-test each one to prove it is closed. The deliverable is a set of code fixes plus documented re-test results showing every finding now fails to exploit. This closes the loop from discovery to verified resolution.

Analogy🏏Cricket
💪 Think of it like fitness: Assessment day is when the training gets tested for real, you take the map of your programme and put each targeted lift under load to see which strengths hold and which weaknesses are genuine, recording every number. Just as the measured test turns a plan into proven results, using your attack-surface map to probe injection, authentication, and API authorization, and confirming each real flaw with captured evidence, turns recon into demonstrated findings. This reveals where knowledge becomes proof: you deliberately load each mapped weakness and record exactly what gives way.

The aim is to fix at the root, not to paper over symptoms, and to prove closure rather than assume it. For each finding you will apply the structural fix, parameterisation, output encoding, authorization checks, pinned JWT algorithms, rate limits, then re-run the exact exploit that previously worked and confirm it now fails. Documented re-testing is what turns a claimed fix into a verified one.

Analogy🏏Cricket
🏏 Think of it like cricket: A disciplined bowling attack does not spray deliveries everywhere and hope; guided by the scouting report, it targets each batter's flagged weakness, confirms the ball is doing what was planned, and records every dismissal for the analysts. Just as that planned, evidence-backed attack turns a dossier into wickets rather than wasted overs, working your test plan area by area, confirming each real flaw by safely triggering it, and documenting it rigorously turns recon into evidenced findings. This reveals the method: targeted, confirmed, and recorded beats spray-and-pray every time.

Prerequisites

  • The confirmed, evidenced findings list from Lesson 33, plus access to the capstone application's source code to apply fixes.
  • Completion of the Modules 2–4 readings, whose root-cause remediations — parameterisation, encoding, authorization, JWT hardening — you will apply here.
  • Your engagement log open, ready to record each fix applied and each re-test result as evidence of closure.
  • An understanding that all work targets your local capstone app, and that these techniques apply only to systems you are authorised to test.

Setup & Project Structure

Work through your findings list one finding at a time, applying the root-cause fix in the source and then re-testing. For each, record the vulnerability, the fix applied with a code reference, and the re-test result showing the previous exploit now fails. Keep fixes minimal and targeted so each maps clearly to one finding, making the remediation section of your report easy to follow and verify.

Analogy🏏Cricket
📷 Think of it like photography: A professional does not trust memory on a shoot; every frame is captured with its settings, the aperture, the shutter, the exact scene, so the shot can be reproduced and proven later. Just as that per-frame metadata makes each image a self-contained, repeatable record, working your test plan area by area and capturing the exact request, the response that proves impact, the reproduction steps, and the affected endpoint makes each finding a self-contained record. This reveals the discipline: evidence recorded at the moment of capture is what makes a finding stand up in the report.
bash
# Remediate finding-by-finding, documenting fix + re-test each time.
# For each finding, record in remediation.md:
#   - finding id + vuln class
#   - root-cause fix (file + change summary)
#   - re-test: the exact previous exploit, now returning a safe result
# Apply fixes in the capstone source, restart the app, and re-run exploits
# against http://localhost:3000 (your machine only).

Step 1 — Foundation: Fix Injection at the Root

Start with the injection findings. Replace concatenated SQL with parameterised queries so input can never alter the command, and apply contextual output encoding so reflected input renders as text rather than executing. These are the structural fixes from Module 2, not input filters. After applying each, restart the app and move to re-testing to confirm the exploit no longer works.

Analogy🏏Cricket
✈️ Think of it like travel: A safe border does not rely on a guard eyeballing each traveller for anything suspicious; it separates identity documents from the person's story so a convincing lie cannot be waved through as fact. Just as keeping data and credentials in strictly separate channels is structural rather than a hopeful glance, parameterised queries keep input as data so it can never become command, and contextual output encoding makes reflected input render as text rather than execute. This reveals why root fixes beat filters: structure closes the whole class, not just the one payload you happened to see.
javascript
// Injection remediations (root-cause, from Module 2)
// SQLi: parameterise the search query
const rows = db.prepare('SELECT * FROM items WHERE name LIKE ?').all(`%${q}%`);
//   (q is bound as data; ' OR '1'='1 becomes a literal string)

// Reflected XSS: encode output for the HTML context
res.send(`<p>Results for: ${escapeHtml(q)}</p>`);  // tags rendered as text
// Restart the app, then re-test in Step 4-style verification below.

Step 2 — Core Logic: Harden Authentication

Next, fix the authentication and session findings. Pin the JWT verification algorithm and reject none so forged tokens fail, and replace any weak secret with a strong one. Regenerate the session identifier at login and set secure cookie flags. Add a rate limiter to the login endpoint. Each fix maps to a Module 3 lesson and directly neutralises a confirmed finding, ready for re-testing.

Analogy🏏Cricket
📷 Think of it like photography: A studio does not trust anyone claiming to be the client; it checks credentials against a fixed reference, issues a fresh access badge at each visit, and limits how many times a wrong code can be tried at the door. Just as pinning identity to a trusted reference and reissuing badges keeps impostors out, pinning the JWT algorithm and rejecting none, using a strong secret, regenerating the session at login, setting secure cookie flags, and rate-limiting login shut down the confirmed auth flaws. This reveals the approach: each weakness gets its own precise control, not a blanket patch.
javascript
// Auth remediations (root-cause, from Module 3)
// Pin the JWT algorithm and use a strong secret -> defeats 'none' + weak signing
jwt.verify(token, process.env.JWT_SECRET, { algorithms: ['HS256'],
  issuer: 'capstone', audience: 'capstone' });

// Regenerate session at login + secure cookie flags
req.session.regenerate(() => { req.session.userId = user.id; });
res.cookie('sid', id, { httpOnly: true, secure: true, sameSite: 'lax' });

// Rate-limit login -> defeats brute force
app.post('/login', rateLimit({ windowMs: 15*60*1000, max: 5 }), handleLogin);

Step 3 — Integration & Enhancement: Enforce API Authorization

Now fix the API findings. Scope every object lookup to the authenticated caller so broken object level authorization is closed, add explicit role checks so privileged routes reject normal users, and project responses to safe fields so sensitive data is not exposed. These Module 4 remediations enforce authorization on the server for every request, which is exactly what the confirmed findings showed was missing.

Analogy🏏Cricket
🎮 Think of it like gaming: A well-built game never trusts the client to say what a player owns or may do; the server checks that this account actually holds that item and has the rank for that action before anything happens. Just as authoritative server-side checks stop players spawning gear they never earned, scoping every object lookup to the authenticated caller closes broken object level authorization, explicit role checks reject normal users on privileged routes, and projecting responses to safe fields prevents data exposure. This reveals the rule the findings exposed: authorization must be enforced on the server for every request.
javascript
// API remediations (root-cause, from Module 4)
// BOLA: scope object access to the caller
app.get('/api/orders/:id', requireAuth, async (req, res) => {
  const order = await db.orders.findOne({ id: req.params.id, ownerId: req.user.id });
  if (!order) return res.status(404).end();
  res.json(publicOrder(order));                 // projection -> no data exposure
});

// BFLA: explicit role check on privileged routes
app.post('/api/admin/refund', requireAuth, requireRole('admin'), issueRefund);

Step 4 — Testing & Verification: Re-Test Every Fix

Finally, re-test each finding by running the exact exploit that previously succeeded and confirming it now fails safely. Record the before-and-after for every finding: the previous impact and the new safe result. Any finding that still exploits returns to remediation, not the report as fixed. This documented re-test table is the proof of closure and a key section of your final report.

Analogy🏏Cricket
♟️ Think of it like chess: After studying a losing line, you do not just assume the fix works; you set the same position on the board and play the opponent's exact attack again to see whether your new move truly holds. Just as replaying the precise line is what proves the repair rather than hoping, re-running each finding's exact exploit and confirming it now fails safely, while recording the before-and-after, is what proves closure. This reveals the discipline of verification: any finding that still exploits goes back to remediation, never into the report as fixed.
markdown
# Re-test table (proof of closure) — remediation.md
#
# F1 SQLi     /search?q=x' OR '1'='1  before: extra rows  after: 0 rows (bound)  CLOSED
# F2 XSS      /search?q=<b>xss</b>    before: tag executes after: &lt;b&gt; text   CLOSED
# F3 JWT none /admin/config           before: 200 admin   after: 401 (alg pinned) CLOSED
# F4 BOLA     /api/orders/2 as user1  before: other order after: 404 (scoped)      CLOSED
# F5 BFLA     /api/admin/refund       before: succeeds    after: 403 (role check)  CLOSED
# F6 rate lim 6th login attempt       before: 200         after: 429 (limited)     CLOSED
#
# Any finding NOT closed returns to remediation before the report is written.

Warning: Apply and re-test all fixes only against your local capstone application. Re-running exploits to verify closure sends the same attack payloads, which is unauthorised against any system you do not own. Keep everything on localhost, and never verify a fix by testing against a live or third-party environment without explicit written permission.

Extension Challenge: Strengthen your remediation three ways. Add an automated regression test for each finding, in the style of earlier labs, so a future change cannot silently reopen a fixed flaw. Add a Content Security Policy as defence in depth behind the XSS fix, demonstrating layered protection. Finally, re-run the SAST/DAST tools from Module 5 against the fixed app and confirm the previously reported findings no longer appear.

  • Remediation fixes each confirmed finding at its root — parameterisation, encoding, authorization, JWT hardening, rate limits — not with symptom-level filters.
  • Each fix is kept minimal and targeted so it maps clearly to one finding, making the remediation report easy to follow and verify.
  • Injection is closed with parameterised queries and contextual output encoding; authentication with pinned JWT algorithms, session regeneration, cookie flags, and rate limits.
  • API flaws are closed by scoping object access to the caller, adding explicit role checks, and projecting responses to safe fields.
  • Every fix is re-tested by re-running the exact exploit that previously worked and confirming it now fails safely, with before-and-after recorded.
  • A finding is only 'fixed' once re-testing proves closure; any still-exploitable finding returns to remediation rather than being reported as resolved.
Lesson 34 of 35
0% complete