I competed in PwC's Capture the Flag (CTF) competition in 2023 as part of a team, and it fundamentally changed how I think about application security. CTF competitions compress the attacker learning curve — you spend hours trying to exploit intentionally vulnerable systems, which gives you an adversarial perspective that no security checklist can replicate. I am not a penetration tester. I am a developer who now thinks like an attacker when I write code. The penetration testing basics in this post are what I use to test my own applications before release — not for ethical hacking engagements, but for developer-level security validation.
The most valuable thing CTF taught me is not a specific tool — it is a question: 'What did the developer assume that I can violate?' Every security vulnerability exists because a developer made an assumption the attacker can break. Assumed only admins can access /admin? Try it without auth. Assumed the price will always be positive? Send -1. Assumed the file extension tells you the file type? Upload a PHP file as avatar.jpg. Assumed the JWT is verified? Try alg:none. This adversarial questioning is what developers need to internalize, because no scanner or checklist will catch the assumptions you have not thought to question.
Before exploiting anything, attackers enumerate what is there. The tools I use for recon on my own applications: nmap for port scanning (what services are exposed), nmap --script scripts for service version detection, gobuster or ffuf for directory/endpoint enumeration (what paths exist beyond what the UI shows), curl for manual HTTP response analysis (what headers are returned, what information is leaked), and theHarvester for OSINT (what emails and subdomains are publicly visible). Running these against your own staging environment before launch is standard practice that catches exposed admin panels, debug endpoints, and infrastructure information disclosure.
# Developer security testing toolkit
# ONLY run against systems you own or have written authorization to test
# 1. Port scanning — what services are exposed?
nmap -sV -sC -p- yourdomain.com
# -sV: service version detection
# -sC: default scripts (identifies common misconfigs)
# -p-: all 65535 ports (slower but thorough)
# 2. Directory/endpoint enumeration
gobuster dir -u https://yourdomain.com -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
# or ffuf (faster):
ffuf -u https://yourdomain.com/FUZZ -w /usr/share/wordlists/dirb/common.txt -mc 200,301,302
# 3. Web server vulnerability scan
nikto -h https://yourdomain.com
# 4. OWASP ZAP automated scan (GUI or CLI)
docker run -t owasp/zap2docker-stable zap-baseline.py -t https://yourdomain.com
# 5. SQL injection test (against your own staging API)
sqlmap -u "https://staging.api.com/invoices?id=1" --cookie="Authorization=Bearer YOUR_TEST_TOKEN" --level=3 --risk=2 --batch --dbs
# 6. Check security headers
curl -I https://yourdomain.com | grep -E "X-Frame|X-Content|Strict|Content-Security|Referrer"
# 7. Test for common misconfigurations
curl -s https://yourdomain.com/.env # should be 404 or 403
curl -s https://yourdomain.com/.git/config # should be 404 or 403
curl -s https://yourdomain.com/admin # should require auth
curl -s https://yourdomain.com/api-docs # check if Swagger is exposed in prodFrom my PwC CTF experience: the vulnerabilities in CTF challenges are always obvious in retrospect — but invisible when you are in developer mode. Practice switching between developer mode (building features) and attacker mode (questioning every assumption). I do a brief attacker-mode review for every feature before merging: what can a user send that differs from what the UI normally sends? What assumptions does this code make about input that might not hold?
You do not need to become a penetration tester to use security testing tools. These are the ones I use regularly for developer-level security validation: Burp Suite Community Edition (free) for intercepting and modifying HTTP requests — essential for testing API security beyond what the UI allows. OWASP ZAP for automated web application scanning. sqlmap for SQL injection testing. nikto for web server vulnerability scanning. These tools are legal to use against systems you own or have explicit written permission to test.
Burp Suite is the most powerful tool for manually testing API security. Configure your browser or API client to proxy through Burp (127.0.0.1:8080), browse your application normally, and Burp captures all HTTP traffic in its Proxy History. From there, you can: send requests to Repeater to modify and resend, use Intruder to fuzz inputs systematically, use Scanner (Pro) or OWASP ZAP (free) for automated vulnerability detection. The key workflow: capture a legitimate authenticated request, modify the user_id or resource_id parameters, check if you get data you should not. This is the IDOR (Insecure Direct Object Reference) test that catches broken access control.
┌─────────────────────────────────────────────────────────────┐
│ Developer Security Testing Workflow │
│ │
│ Pre-release checklist for every significant feature: │
│ │
│ 1. Port scan (nmap) → verify only expected ports open │
│ └── Should see: 22 (SSH), 80 (HTTP), 443 (HTTPS) only │
│ │
│ 2. Directory enum (gobuster) → find exposed paths │
│ └── Check: /.env, /.git, /admin, /swagger, /api-docs │
│ │
│ 3. Burp Suite manual review → new API endpoints │
│ └── Test: IDOR (change resource IDs) │
│ └── Test: Auth bypass (remove Authorization header) │
│ └── Test: Mass assignment (add extra JSON fields) │
│ │
│ 4. sqlmap → endpoints with DB interaction │
│ └── Confirm: parameterized queries only │
│ │
│ 5. Security headers check (securityheaders.com) │
│ └── Target: A or A+ rating │
│ │
│ 6. SSL Labs scan (ssllabs.com) │
│ └── Target: A+ rating │
└─────────────────────────────────────────────────────────────┘Security testing tools are powerful and can cause damage. Only run penetration testing tools against systems you own or have explicit written authorization to test. Running nmap scans or Burp Suite against systems without permission is illegal in most jurisdictions — even if you discover a vulnerability and report it responsibly. 'Bug bounty programs' explicitly authorize testing within defined scopes. Before testing any third-party system, verify it has a bug bounty or vulnerability disclosure program and stay within the defined scope. Getting this wrong can result in criminal charges, not rewards.
My pre-release security testing workflow for every significant feature or API change: (1) nmap scan against staging to verify only expected ports are open. (2) gobuster scan to find any exposed paths not intended to be public. (3) Burp Suite manual review of new API endpoints — testing IDOR, authentication bypass, and input validation. (4) sqlmap against any new endpoints with database interaction. (5) OWASP ZAP automated scan for common web vulnerabilities. (6) Nikto scan for server misconfigurations. This takes 2-4 hours per major feature and catches vulnerabilities before they reach production. The cost is low compared to incident response.
The CTF challenges that appeared most in real code reviews after the competition: JWT with algorithm confusion (accepting any algorithm, including none), IDOR via sequential numeric IDs (use UUIDs instead), path traversal in file upload/download endpoints (never use user-provided filenames in filesystem paths), SSRF via URL fetch features (validate and restrict outbound URLs), race conditions in balance/inventory decrement operations (use database transactions with locking), and information disclosure in error messages (never return raw exceptions to clients). These are not theoretical — I have found each of these in production codebases.
Technical controls only go so far — security culture is what makes it stick. What I do: security review as a required checklist item in every PR template, monthly team sessions reviewing recent CVEs and breach reports, a shared 'security interesting' Slack channel for sharing findings from CTF competitions and security research, and a blameless post-mortem process for security incidents. Developers who feel psychologically safe reporting their own mistakes will report early, before incidents escalate. A culture where security is everyone's responsibility is more effective than any tool — including everything else in this post.