Web applications remain the single largest attack surface for most organizations. Whether it is a customer-facing SaaS platform, an internal ERP system, or a public API, the browser-accessible perimeter is where adversaries focus first — and where defenders must be most vigilant. At A.KHAT, penetration testing of web applications accounts for the majority of our engagements, and the patterns we observe year after year tell a consistent story: the fundamentals still matter, even as the technology stack evolves.
This article draws on lessons from real penetration testing engagements conducted throughout 2025 and into 2026. We will walk through the most common vulnerability classes we encounter, explain why they persist, and provide actionable remediation guidance. Whether you are a developer, security engineer, or CTO preparing for your next pentest, this is the landscape you need to understand.
The OWASP Top 10 in 2025/2026: An Evolving Landscape
The OWASP Top 10 has been the de facto standard for classifying web application risks since its first release in 2003. The 2021 edition brought significant structural changes — elevating Broken Access Control to the number one position, introducing new categories like Insecure Design and Software and Data Integrity Failures, and consolidating older categories. In the years since, the threat landscape has continued to shift.
As of 2025-2026, several trends stand out. API security has become a distinct discipline, reflected in OWASP's dedicated API Security Top 10 project. Supply chain attacks have matured from theoretical risks to routine incidents. Server-Side Request Forgery (SSRF) has been amplified by cloud-native architectures. And the proliferation of AI-assisted development tools has introduced a new class of subtle bugs — code that looks correct but misses critical security boundaries.
Most Common Vulnerabilities We Find
The following vulnerability classes appear most frequently in our web application penetration testing engagements. They are ordered roughly by prevalence and impact.
1. Broken Access Control
Broken access control has been the number one web application vulnerability for years, and our testing confirms this remains the case in 2026. This category encompasses any scenario where a user can act outside their intended permissions.
The most common pattern we encounter is Insecure Direct Object References (IDOR). A typical example: an API endpoint like GET /api/invoices/1547 returns invoice data based solely on the numeric ID in the URL. By incrementing or decrementing this value, an attacker can access invoices belonging to other users or organizations. We see this in REST APIs, GraphQL queries, and even file download endpoints.
Other frequent findings include:
- Privilege escalation — A standard user modifies their role by tampering with a request parameter (e.g., changing
"role": "user"to"role": "admin"in a profile update request). - Missing function-level access control — Administrative endpoints like
/admin/usersor/api/configare accessible to authenticated but unauthorized users simply because the frontend hides the navigation link, but the server never checks permissions. - Path traversal in file operations — Endpoints that accept file paths or names without proper validation, allowing access to files outside the intended directory.
How to fix it: Implement authorization checks on the server side for every request. Never rely on client-side controls or security through obscurity. Adopt the principle of least privilege — deny by default and grant access explicitly. Use framework-provided authorization middleware (e.g., Spring Security's @PreAuthorize, Django's permission classes, or ASP.NET's [Authorize] attribute). For IDOR specifically, use indirect references (UUIDs instead of sequential IDs) and always validate that the requesting user owns the resource.
2. Injection (SQL, NoSQL, Command)
Injection vulnerabilities have been on the OWASP Top 10 since its inception, and they are far from extinct. While modern ORMs have reduced the incidence of classic SQL injection in new code, we still find injection flaws in legacy systems, custom query builders, and applications that use raw queries for complex operations.
Common patterns we encounter:
- ORM misuse — Developers using an ORM but bypassing it for "performance" with raw SQL that concatenates user input. We regularly find this in reporting features, search endpoints, and data export functions.
- NoSQL injection — MongoDB queries constructed from JSON input without validation, allowing operators like
$gt,$ne, or$regexto be injected. Example: a login form where submitting{"username": "admin", "password": {"$ne": ""}}bypasses authentication. - Command injection — Applications that shell out to system commands for tasks like PDF generation, image processing, or network diagnostics. Unsanitized input passed to
os.system(),subprocess.Popen(shell=True), orexec()can lead to full system compromise. - Server-Side Template Injection (SSTI) — Template engines like Jinja2, Twig, or Freemarker processing user-supplied strings, allowing arbitrary code execution. We have seen this in email template editors, CMS platforms, and reporting tools.
How to fix it: Use parameterized queries or prepared statements for all database interactions — no exceptions. For NoSQL databases, validate and sanitize input types rigorously; reject objects where strings are expected. Avoid shelling out to system commands; use language-native libraries instead. When system commands are unavoidable, use array-based invocation (e.g., subprocess.run(["convert", filename]) instead of os.system("convert " + filename)). For template engines, never render user-supplied strings as templates.
3. Authentication and Session Management Flaws
Authentication is the front door of every application, and we find it poorly secured with alarming regularity. Common issues include:
- Weak password policies — Applications that accept passwords like
123456orpasswordwithout any complexity requirements or breach-list checking. - Missing multi-factor authentication (MFA) — Particularly on administrative accounts and sensitive operations. In 2026, any application handling sensitive data without MFA on privileged accounts is an unacceptable risk.
- JWT misconfigurations — The
alg=noneattack (accepting unsigned tokens), weak HMAC secrets that can be brute-forced, failure to validate theissoraudclaims, and tokens with excessively long expiry times. We regularly use tools likejwt_toolto test for these weaknesses. - Session fixation — The application fails to regenerate the session ID after login, allowing an attacker who sets a known session ID pre-authentication to hijack the session post-authentication.
- Credential stuffing susceptibility — No rate limiting or account lockout on login endpoints, allowing automated attacks with breached credential lists.
How to fix it: Enforce strong password policies and check passwords against known breach databases (the HIBP Pwned Passwords API is free and effective). Implement MFA for all users, with enforcement for administrative and privileged accounts. For JWTs, use asymmetric algorithms (RS256/ES256), validate all claims, set short expiry times, and implement token refresh flows. Regenerate session IDs after authentication. Implement rate limiting and progressive delays on login endpoints.
4. Server-Side Request Forgery (SSRF)
SSRF has become one of the most impactful vulnerability classes in cloud-native environments. When an application fetches a URL provided by the user — for webhook delivery, URL preview generation, file import, or PDF rendering — an attacker can redirect those requests to internal services.
The canonical attack targets cloud metadata services. On AWS, a request to http://169.254.169.254/latest/meta-data/iam/security-credentials/ can yield temporary IAM credentials. Similar endpoints exist on Azure (http://169.254.169.254/metadata/instance) and GCP (http://metadata.google.internal/computeMetadata/v1/). We have successfully exploited this in multiple engagements to pivot from a web application vulnerability to cloud infrastructure access.
Beyond metadata services, SSRF enables internal service enumeration (scanning ports on 127.0.0.1 or internal network ranges), accessing internal APIs that lack authentication because they are assumed to be unreachable from the internet, and reading local files via file:// URIs.
How to fix it: Implement strict URL validation with allowlists of permitted domains and IP ranges. Block requests to private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16) and localhost. Use IMDSv2 on AWS (which requires a PUT request with a hop-limit token, mitigating most SSRF attacks). Run outbound HTTP requests through a forward proxy that enforces network policies. Disable unnecessary URL schemes (file://, gopher://, dict://).
5. Security Misconfiguration
Security misconfiguration is a broad category, but it is one of the most reliably exploitable. We find misconfigurations in virtually every engagement:
- Default credentials — Admin panels for databases, monitoring tools (Grafana, Kibana), message brokers (RabbitMQ), and application frameworks left with factory-default passwords. We maintain a database of default credentials and test them systematically.
- Exposed administrative interfaces — phpMyAdmin, Adminer, Spring Boot Actuator endpoints, Django admin, and cloud management consoles accessible from the internet without IP restrictions.
- Verbose error messages — Stack traces, SQL error messages, and debug information exposed in production, revealing internal paths, database schemas, library versions, and sometimes credentials.
- Missing security headers — Absent
Content-Security-Policy,X-Frame-Options,Strict-Transport-Security, andX-Content-Type-Optionsheaders, enabling clickjacking, MIME sniffing, and cross-site scripting attacks. - Debug mode in production — Django's
DEBUG=True, Flask's debug mode, Laravel'sAPP_DEBUG=true, and Spring Boot's DevTools active in production environments, exposing sensitive configuration data and enabling remote code execution in some cases. - Directory listing enabled — Web servers configured to display directory contents, revealing application structure and potentially sensitive files.
How to fix it: Establish and follow a hardening checklist for every component in the stack. Automate configuration auditing with tools like ScoutSuite for cloud environments, Lynis for Linux servers, and custom scripts for application-specific settings. Remove or restrict access to all administrative interfaces. Implement proper error handling that logs details server-side but returns generic messages to clients. Deploy comprehensive security headers — use a tool like securityheaders.com to validate. Never deploy with debug mode enabled in production.
6. Vulnerable and Outdated Dependencies
The Log4Shell vulnerability (CVE-2021-44228) was a watershed moment for software supply chain security, and its lessons remain critically relevant. In our 2025-2026 engagements, we routinely find applications running libraries with known, exploitable CVEs — sometimes years after patches were released.
Common findings include:
- Outdated JavaScript packages with known prototype pollution or XSS vulnerabilities (lodash, jQuery, Angular.js 1.x)
- Java applications using vulnerable versions of Apache Commons, Spring Framework, or Jackson
- Python applications with outdated versions of requests, urllib3, or Pillow
- Transitive dependencies — the application's direct dependencies are current, but their sub-dependencies contain vulnerabilities
Supply chain risks extend beyond known CVEs. We have observed typosquatting packages in npm and PyPI registries, compromised maintainer accounts, and malicious code injected into legitimate packages.
How to fix it: Integrate Software Composition Analysis (SCA) tools into your CI/CD pipeline — Snyk, Dependabot, Renovate, or OWASP Dependency-Check. Generate and maintain Software Bills of Materials (SBOMs) for all applications. Establish a policy for dependency updates: critical and high-severity CVEs should trigger immediate patching, while routine updates should follow a regular cadence (at minimum monthly). Pin dependency versions and use lock files. Audit your dependency tree regularly with npm audit, pip-audit, or mvn dependency:tree.
7. API Security Issues
As applications shift to API-first architectures, API-specific vulnerabilities have become a dominant finding category. The OWASP API Security Top 10 provides a useful taxonomy, and we see its entries reflected in nearly every API-focused engagement.
- Broken Object-Level Authorization (BOLA) — The API equivalent of IDOR. An authenticated user can access or modify other users' resources by manipulating object identifiers in API calls. This is the number one API vulnerability we find.
- Excessive data exposure — API responses that return entire database objects instead of only the fields the client needs. A user profile endpoint returning password hashes, internal IDs, role flags, or email verification tokens alongside the expected name and email.
- Mass assignment — APIs that bind request body parameters directly to internal data models without whitelisting. An attacker adds
"isAdmin": trueor"accountBalance": 999999to a legitimate request body. - Missing rate limiting — APIs without throttling on sensitive endpoints (login, password reset, OTP verification), enabling brute-force attacks and enumeration.
- Lack of input validation — APIs accepting arbitrary data types, oversized payloads, or unexpected fields without validation, leading to injection, denial of service, or logic bypass.
How to fix it: Implement object-level authorization checks for every API endpoint that accesses a resource. Use explicit response schemas — never return raw database objects. Whitelist permitted fields for mass assignment (e.g., Django REST Framework serializers, Rails strong parameters). Implement rate limiting at the API gateway level (e.g., Kong, AWS API Gateway, or nginx rate limiting). Validate all input against a strict schema using OpenAPI/Swagger specifications and validation middleware.
8. Cryptographic Failures
Cryptography is easy to get wrong, and we find cryptographic failures in a significant percentage of engagements:
- Weak password hashing — Applications storing passwords with MD5, SHA1, or even SHA256 without salting. These can be cracked in seconds with modern GPU hardware and rainbow tables.
- Missing encryption at rest — Sensitive data (PII, financial records, health data) stored in plaintext in databases, file systems, or backups.
- Weak TLS configuration — Servers supporting TLS 1.0 or 1.1, weak cipher suites, or missing certificate validation in outbound connections.
- Hardcoded secrets — API keys, database credentials, and encryption keys embedded in source code, configuration files committed to version control, or client-side JavaScript.
- Insecure random number generation — Using predictable random sources (e.g.,
Math.random()or Python'srandommodule) for security-sensitive operations like token generation, password resets, or session IDs.
How to fix it: Use bcrypt, scrypt, or Argon2id for password hashing — never MD5 or SHA-family algorithms alone. Encrypt sensitive data at rest using AES-256-GCM or ChaCha20-Poly1305. Enforce TLS 1.2 as a minimum, prefer TLS 1.3, and use strong cipher suites. Manage secrets with a dedicated secrets manager (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault). Use cryptographically secure random number generators (crypto.randomBytes() in Node.js, secrets module in Python, SecureRandom in Java).
New Trends in 2026
Beyond the established vulnerability classes, several emerging trends are reshaping the web application threat landscape.
AI-Assisted Attacks and Defenses
Large language models are now being used on both sides of the security equation. Attackers use AI to generate convincing phishing content, automate vulnerability discovery, and craft sophisticated social engineering attacks. On the defensive side, AI-powered code review tools can catch security flaws during development, and AI-assisted WAFs can detect novel attack patterns. However, AI-generated code itself introduces a new risk: developers accepting LLM-generated code without thorough review, leading to subtle vulnerabilities that pass cursory inspection but fail under adversarial testing. We have begun seeing patterns specific to AI-generated code — proper-looking input validation that misses edge cases, authentication logic that handles the happy path but fails on error conditions, and sanitization functions that are almost correct but can be bypassed.
GraphQL-Specific Vulnerabilities
GraphQL adoption continues to grow, and with it, a class of vulnerabilities specific to the query language. Introspection queries enabled in production expose the entire API schema. Deeply nested queries can cause denial of service through resource exhaustion. Batch queries enable brute-force attacks that bypass per-request rate limiting. Authorization is often implemented inconsistently across resolvers, with some resolvers checking permissions while others trust that the parent resolver already did. We test GraphQL APIs specifically for these issues using tools like InQL, GraphQL Voyager, and custom query crafting.
WebSocket Security Issues
WebSocket connections are increasingly used for real-time features — chat, notifications, collaborative editing, and live dashboards. However, WebSocket security is frequently overlooked. Common findings include missing authentication on WebSocket upgrade requests, absence of message-level authorization (any connected user can send any message type), cross-site WebSocket hijacking (the server does not validate the Origin header), and injection vulnerabilities in message handling. Many WAFs and security tools still do not inspect WebSocket traffic, creating blind spots in security monitoring.
Client-Side Prototype Pollution
Prototype pollution — the ability to inject properties into JavaScript object prototypes — has evolved from a theoretical concern to a practical attack vector. By polluting Object.prototype, an attacker can modify the behavior of all objects in the application, leading to XSS, authentication bypass, or denial of service. We increasingly find this in applications that use deep-merge utilities, URL parameter parsers, or JSON parsing libraries that do not guard against __proto__, constructor, or prototype property injection. Tools like pp-finder and ppmap help identify these vulnerabilities during testing.
Pentesting Methodology
Understanding how a professional penetration test works can help organizations prepare effectively and get maximum value from the engagement. At A.KHAT, our web application penetration testing follows a structured methodology.
1. Reconnaissance and Scope Definition
Before any testing begins, we work with the client to define a clear scope — which applications, environments, and user roles are in scope, what testing techniques are permitted, and what the objectives are. We then conduct passive and active reconnaissance: mapping the application's attack surface, identifying technologies in use, discovering API endpoints, and understanding business logic flows.
2. Automated Scanning
We use industry-standard tools for initial coverage: Burp Suite Professional for comprehensive web application scanning, Nuclei with custom and community templates for known vulnerability detection, and specialized tools like SQLMap, Nikto, and SSLyze for targeted assessments. Automated scanning provides breadth, catching known vulnerabilities and common misconfigurations efficiently.
3. Manual Testing
This is where the real value of a penetration test lies. Automated tools cannot understand business logic, assess authorization models in context, or chain low-severity findings into high-impact attack paths. Our testers manually examine authentication flows, test authorization boundaries across all user roles, probe business logic for abuse scenarios, and evaluate the application's behavior under conditions the developers did not anticipate.
4. Exploitation and Impact Assessment
When vulnerabilities are identified, we exploit them in a controlled manner to demonstrate real-world impact. An IDOR finding is more compelling when accompanied by evidence of actual data accessed. A SQL injection is rated differently when it yields database credentials versus read-only access to non-sensitive data. We assess and communicate impact in business terms, not just technical severity scores.
5. Reporting with Remediation Guidance
Our reports provide detailed findings with evidence (screenshots, HTTP request/response pairs, reproduction steps), risk ratings aligned with CVSS v4.0, and specific remediation guidance tailored to the client's technology stack. We include code examples where relevant — not just "use parameterized queries" but showing exactly how to implement the fix in the client's framework and language.
6. Re-testing After Fixes
A pentest report is only valuable if the findings get fixed. We include a re-test phase in every engagement, verifying that remediations are effective and have not introduced new issues. This close-the-loop approach ensures that the investment in penetration testing translates to measurable security improvement.
How to Prepare for a Penetration Test
Organizations that prepare well get significantly more value from their penetration testing engagements. Here is our advice for companies planning a web application pentest.
- Define scope clearly. Specify exactly which applications, URLs, API endpoints, and environments are in scope. Clarify whether third-party integrations, mobile APIs, and infrastructure are included or excluded.
- Provide test accounts. Create dedicated test accounts for each user role in the application (regular user, manager, admin, API consumer, etc.). Pre-populating these accounts with realistic data enables more thorough authorization testing.
- Set up a staging environment. Whenever possible, testing should occur on a staging or pre-production environment that mirrors production. This avoids risk to production data and allows more aggressive testing techniques without concern about service disruption.
- Have your development team ready. The most effective engagements are those where the development team is available to answer questions about intended behavior, discuss findings as they are discovered, and begin working on fixes during the testing window.
- Plan for re-testing. Budget time and resources for fixing identified vulnerabilities and scheduling a re-test. A pentest without follow-through is an expensive document that gathers dust.
- Gather documentation. API documentation (OpenAPI/Swagger specs), architecture diagrams, and previous security assessment reports help testers work efficiently and focus on areas of highest risk.
Conclusion
Web application security in 2026 demands continuous attention. The vulnerabilities we find in penetration testing engagements are not exotic zero-days — they are well-understood flaws that persist because of incomplete implementation, insufficient testing, and the ever-present pressure to ship features fast. Broken access control, injection flaws, authentication weaknesses, and security misconfigurations appear in applications built with the latest frameworks, by experienced development teams, at organizations of every size.
The good news is that these vulnerabilities are fixable. Proper authorization checks, parameterized queries, strong authentication, secure configuration, and disciplined dependency management address the vast majority of findings. The key is building security into the development lifecycle — through training, code review, automated scanning, and regular penetration testing — rather than treating it as an afterthought.
Regular penetration testing is not optional. It is an essential component of any mature security program, required by standards like ISO 27001, PCI DSS, and the EU NIS2 Directive. More importantly, it is the most effective way to understand your application's security posture from an attacker's perspective, before a real attacker does it for you.