Main content
Introduction
Modern web applications are exposed to constant risk. Every login form, API endpoint, file upload, payment flow, admin panel, and third-party integration can become an entry point if it is not tested properly.
Penetration testing helps identify real security weaknesses before attackers can exploit them. It is not only about running tools or finding common vulnerabilities. A good pentest follows a structured process: understand the target, map the attack surface, test safely, validate issues, document evidence, and guide the development team toward practical fixes.
This checklist gives a clear, production-grade process for testing modern web applications, especially applications built with frameworks like Django, Laravel, Express, Next.js, and React-based frontends.
1. Define the Scope First
Before testing begins, the scope must be clear. Without scope, even a useful security test can become risky or legally problematic.
A proper scope should define:
- Which domains and subdomains are allowed
- Which IP addresses or environments are allowed
- Whether testing is allowed on production or staging
- Which user roles are available for testing
- Whether brute force testing is allowed
- Whether payment, email, file upload, or admin features can be tested
- Testing time window and rate limits
- Emergency contact if something breaks
Example scope:
Allowed:
- https://example.com
- https://api.example.com
- Staging admin panel
Not allowed:
- Third-party payment provider attacks
- Denial-of-service testing
- Social engineering
- Physical attacks
Scope protects both the tester and the business.
2. Reconnaissance
Reconnaissance is the information-gathering phase. The goal is to understand the application, its infrastructure, technologies, exposed endpoints, and possible weak points.
Useful checks include:
- Domain and subdomain discovery
- Technology stack identification
- Public GitHub or code leak checks
- Exposed admin panels
- Public API documentation
- Search engine indexed sensitive paths
- JavaScript file analysis
- Old staging or testing domains
- Cloud storage bucket exposure
- Public error messages
Common findings in this phase include forgotten test pages, exposed .env files, old subdomains, debug panels, and unprotected API documentation.
For web apps, JavaScript files are especially useful because they often reveal API routes, feature flags, internal endpoint names, and frontend validation logic.
3. Attack Surface Mapping
After reconnaissance, create a clear map of the application’s attack surface.
Important areas to map:
- Login and registration
- Password reset
- Email verification
- User profile update
- File upload
- Search and filters
- Contact forms
- Payment or checkout flow
- Admin dashboard
- API endpoints
- Webhooks
- Role-based pages
- Third-party integrations
For each feature, ask:
Who can access this?
What data does it accept?
What data does it return?
Can another user access it?
Can it be abused with unexpected input?
This step helps avoid random testing and makes the pentest more complete.
4. Authentication Testing
Authentication is one of the most important parts of any web application. A weak login or password reset flow can compromise the whole system.
Test for:
- Weak password policy
- Login brute force protection
- Account enumeration
- Password reset token expiration
- Password reset token reuse
- Email verification bypass
- Session invalidation after password change
- Multi-factor authentication bypass, if MFA exists
- Login rate limiting
- Secure error messages
Bad example:
This email does not exist.
Better example:
If this email exists, we have sent reset instructions.
Authentication errors should not reveal whether an account exists.
5. Session and Cookie Security
Sessions are responsible for keeping users logged in safely. Weak session handling can lead to account takeover.
Check that cookies use:
HttpOnly
Secure
SameSite=Lax or SameSite=Strict
Also test:
- Session fixation
- Session reuse after logout
- Session reuse after password change
- Long-lived sessions without refresh
- Missing CSRF protection
- Token stored in localStorage when not needed
- Multiple sessions not visible to user
- Admin sessions not protected strongly enough
For Django applications, make sure production settings include secure cookies, HTTPS-only sessions, CSRF protection, and proper trusted origins.
6. Authorization and Access Control
Authentication answers: “Who are you?”
Authorization answers: “What are you allowed to do?”
Access control bugs are very common in real applications.
Test for:
- IDOR vulnerabilities
- Horizontal privilege escalation
- Vertical privilege escalation
- User accessing another user’s files
- Normal user accessing admin endpoints
- Hidden frontend routes still accessible through API
- Changing user ID, project ID, invoice ID, or order ID in requests
- Missing ownership checks in backend views
Example risky request:
GET /api/projects/102/
If user A can change 102 to 103 and see user B’s project, that is an IDOR vulnerability.
The backend must always verify ownership. Frontend hiding is not security.
7. Input Validation and Injection Testing
Any input accepted by the application should be tested.
Test areas:
- Search fields
- Login fields
- Contact forms
- Project request forms
- File names
- URL parameters
- JSON body fields
- Headers
- Webhook payloads
- Admin inputs
Common vulnerabilities include:
- SQL injection
- Command injection
- Server-side template injection
- HTML injection
- Stored XSS
- Reflected XSS
- NoSQL injection
- LDAP injection
- Path traversal
Even if a framework protects against many injection types, custom raw queries, unsafe template rendering, and third-party packages can still introduce risk.
8. File Upload Testing
File upload features are high-risk because attackers can try to upload malicious files, oversized files, scripts, or disguised content.
Test for:
- Allowed file extensions
- MIME type validation
- File size limit
- File name sanitization
- Malware scanning if needed
- Upload path exposure
- Direct execution of uploaded files
- Public vs private file access
- SVG upload risks
- Image metadata exposure
- Duplicate file handling
Dangerous files include:
.php
.jsp
.html
.svg
.exe
.sh
.py
For production applications, uploaded files should usually be stored outside the application codebase, preferably in object storage such as S3, Cloudflare R2, or similar.
9. API Security Testing
Modern web applications often depend heavily on APIs. The API must be tested separately from the frontend.
Check for:
- Missing authentication
- Broken object-level authorization
- Excessive data exposure
- Mass assignment
- Missing rate limits
- Weak CORS configuration
- Insecure direct object references
- Verb tampering
- Missing request validation
- Sensitive data in responses
- Debug information in API errors
Example mass assignment risk:
{
"name": "User",
"email": "[email protected]",
"is_admin": true
}
If the backend accepts is_admin from a normal user request, the application has a serious security flaw.
10. Business Logic Testing
Business logic flaws are often missed by automated scanners. These issues happen when the application works as coded but the logic can be abused.
Examples:
- Applying discount multiple times
- Skipping payment step
- Reusing expired payment links
- Accepting proposal without payment
- Accessing delivery files before payment
- Submitting duplicate project requests
- Changing invoice amount from frontend
- Marking order as paid without real payment verification
- Bypassing required approval steps
- Creating unlimited free resources
For business applications, business logic testing is critical because attackers often target money flow, status changes, and permissions.
11. Payment Flow Testing
Payment features need special care. Never trust the frontend to confirm payment.
Test for:
- Fake payment success response
- Client-side price manipulation
- Reused transaction ID
- Payment made to wrong merchant account
- Webhook signature not verified
- Order marked paid before provider confirmation
- Currency mismatch
- Amount mismatch
- Sandbox credentials accidentally used in production
- Live credentials exposed in frontend
For PayPal or Stripe, the backend should verify:
Correct transaction ID
Correct amount
Correct currency
Correct receiver/merchant account
Correct payment status
Webhook authenticity
Only after backend verification should the order or project be marked as paid.
12. Security Headers
Security headers help reduce browser-based attacks.
Recommended headers include:
Content-Security-Policy
X-Content-Type-Options
X-Frame-Options
Referrer-Policy
Permissions-Policy
Strict-Transport-Security
For production, HTTPS should be enforced and HSTS should be enabled only after confirming the domain and subdomains are ready for HTTPS.
A good Content Security Policy can reduce XSS impact, but it must be configured carefully to avoid breaking scripts, analytics, or frontend assets.
13. Error Handling and Debug Exposure
Production applications should never expose detailed stack traces, environment variables, secret keys, database errors, or internal file paths.
Check for:
- Debug mode enabled in production
- Stack traces shown to users
- Secret values in logs
- API errors leaking internal details
- Verbose database errors
- Public admin error pages
- Unhandled exceptions
- Missing custom 404 and 500 pages
For Django applications, DEBUG=False must be used in production. Logs should be collected safely and monitored using tools such as Sentry or server logs.
14. Rate Limiting and Abuse Protection
Attackers often abuse normal features at high volume.
Test rate limits on:
- Login
- Password reset
- Signup
- Email verification resend
- Contact forms
- Search endpoints
- File uploads
- Payment creation
- API endpoints
- Admin login
Without rate limiting, attackers can brute force accounts, spam emails, overload the server, or abuse paid API resources.
15. Reporting and Remediation
A good pentest is only useful if the results are clear and actionable.
Each finding should include:
- Title
- Severity
- Affected URL or endpoint
- Clear impact
- Steps to reproduce
- Evidence
- Risk explanation
- Recommended fix
- Retest status
Example severity levels:
Critical: immediate business or system compromise
High: serious account/data/payment risk
Medium: exploitable but limited impact
Low: security weakness with limited direct risk
Informational: improvement or hardening note
The final report should help developers fix issues quickly, not just list vulnerabilities.
16. Retesting
After fixes are deployed, retesting confirms whether vulnerabilities are actually resolved.
Retesting should check:
- Original issue no longer works
- Fix did not break normal functionality
- Similar endpoints are also protected
- Logs and alerts behave correctly
- No new bypass was introduced
Security testing should be a continuous process, not a one-time task.
Final Checklist
Before marking a web application secure enough for production, verify:
- Scope is clearly defined
- Authentication is tested
- Password reset is secure
- Sessions and cookies are protected
- Authorization checks are enforced on the backend
- File uploads are restricted
- APIs are tested directly
- Payment verification happens server-side
- Security headers are configured
- Debug mode is disabled
- Sensitive data is not leaked
- Rate limits are applied
- Logs and alerts are working
- Vulnerabilities are reported clearly
- Fixes are retested
Conclusion
Web application penetration testing is not only about finding vulnerabilities. It is about understanding how the application works, how users interact with it, and how attackers might abuse it.
A strong pentest combines technical testing, business logic review, secure development knowledge, and clear reporting. When done properly, it helps teams ship safer applications, protect users, and reduce the risk of real-world attacks.
At A2TDEV, we focus on building secure, maintainable, and production-ready web applications. Security is not something added at the end — it should be part of the development process from the beginning.
Comments
Join the conversation
Please login to comment on this article.