A practical, defensible guide for developers and security testers that explains the what, why, and how of penetration testing (pen-testing) for ASP.NET Core apps—with C# examples you can drop into tooling or test harnesses. Only test systems you own or have explicit written permission to test. Unauthorized testing is illegal.
1. What is penetration testing (short)
Penetration testing is a simulated attack against an application to discover security weaknesses before an attacker does. It complements static analysis (SAST) and dynamic scanning (DAST) by combining automated scanning with manual, creative testing of logic and flows.
Goals
Find authentication/authorization flaws and business logic issues.
Find input validation, injection, XSS, CSRF, file upload, and session weaknesses.
Measure impact (data exposure, privilege escalation, remote code execution).
Produce reproducible findings and remediation guidance.
2. Rules of engagement (must read)
Before testing
Get written authorization with scope, dates, allowed tools, and contacts.
Define in-scope assets (hostnames, endpoints, and environments). Prefer dedicated staging environments.
Define out-of-scope items (production databases, payment processors, third-party APIs).
Arrange backup and incident contacts in case of accidental disruption.
Keep tests non-destructive unless explicitly permitted.
3. Test methodology (high level)
Reconnaissance: gather info about app routes, public assets, and technologies.
Mapping & crawling: enumerate endpoints, API routes, and forms.
Automated scanning: run DAST scanners for common issues.
Manual testing: authentication/authorization logic, business logic flaws, injection, XSS, CSRF, and file upload attacks.
Exploitation & validation: validate findings with non-destructive proof-of-concept (PoC).
Reporting & remediation: document reproduction steps, impact, and mitigation.
4. Reconnaissance & mapping
What to gather:
Hostnames, subdomains, and exposed ports.
App tech (ASP.NET Core version, server headers, frameworks).
Public routes, sitemap, API endpoints, JS files.
Authentication flow and third-party integrations.
Tools (high-level): browser DevTools, automated site crawlers (OWASP ZAP / Burp Spider), robots.txt
, sitemap.
C# reconnaissance snippet: fetch /.well-known
and robots automatically.
using System;
using System.Net.Http;
using System.Threading.Tasks;
public static async Task ReconAsync(string baseUrl)
{
using var client = new HttpClient { BaseAddress = new Uri(baseUrl) };
var endpoints = new[] { "/robots.txt", "/.well-known/security.txt", "/favicon.ico" };
foreach (var ep in endpoints)
{
var res = await client.GetAsync(ep);
Console.WriteLine($"{ep} -> {(int)res.StatusCode} {res.ReasonPhrase}");
}
}
5. Automated scanning (DAST)
Automated scanners quickly find low-hanging fruit:
OWASP ZAP
Burp Suite (Professional for automation)
Nikto (web server issues)
SecurityHeaders.io for header checks
Best practice
Scan the staging environment.
Use authenticated scans for deeper coverage (login scripts).
Review results—scanners produce false positives.
You can orchestrate ZAP in CI (simple Docker command):
docker run --rm owasp/zap2docker-stable zap-baseline.py -t https://staging.example.com -r zap_report.html
6. Manual testing focus areas (with C# testing helpers)
Below are the core manual tests and small C# examples to help automate safe checks.
6.1 Authentication & session management
Check
Weak password policy, account enumeration, session fixation, missing MFA.
Cookie flags: HttpOnly
, Secure
, SameSite
.
Session timeout / logout behavior.
C#: test whether login sets secure cookie flags
using System;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
public static async Task CheckCookieFlags(HttpClient client, string loginUrl)
{
var res = await client.GetAsync(loginUrl);
if (res.Headers.TryGetValues("Set-Cookie", out var setCookies))
{
foreach (var c in setCookies)
{
Console.WriteLine(c);
if (!c.Contains("HttpOnly")) Console.WriteLine("Warning: Cookie missing HttpOnly");
if (!c.Contains("Secure")) Console.WriteLine("Warning: Cookie missing Secure");
}
}
}
6.2 Authorization & access control
Check
Horizontal privilege escalation (user A accessing user B resources).
Vertical privilege escalation (user role bypass to admin).
Insecure direct object references (IDOR).
C# approach: call API endpoints with different roles/tokens and assert 403
where appropriate.
// Simplified: send requests with different Authorization headers and assert response codes
6.3 Input validation & injection
Check
SQL/command injection, unsafe raw SQL, and deserialization issues.
Validate all inputs and ensure use of parameterized queries/ORM.
C# fuzzing snippet to POST common suspicious inputs to an endpoint:
using System;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading.Tasks;
public static async Task FuzzEndpoint(HttpClient client, string endpoint)
{
var payloads = new[] {
new { name = "normal" },
new { name = "' OR '1'='1" },
new { name = "<script>alert(1)</script>" },
new { name = new string('A', 5000) }
};
foreach (var p in payloads)
{
var res = await client.PostAsJsonAsync(endpoint, p);
Console.WriteLine($"Payload len {JsonSerializer.Serialize(p).Length} => {(int)res.StatusCode}");
}
}
Note: Use safe, non-destructive payloads that reveal behavior (status codes, error messages).
6.4 Cross-Site Scripting (XSS)
Check
Reflected, stored, and DOM XSS.
Ensure output encoding in Razor/JS and proper Content Security Policy (CSP).
Manual test: insert benign markers (e.g., <<TEST_XSS>>
) and search responses. Avoid using real script
tags in automated tests if not allowed; use markers and inspect whether they are reflected unencoded.
6.5 Cross-Site Request Forgery (CSRF)
Check
C#: attempt POST without anti-forgery token (expect 400 or 403).
var res = await client.PostAsJsonAsync("/account/create", new { dummy = "x" });
Console.WriteLine(res.StatusCode); // should be 400/403 if server enforces CSRF
6.6 File upload handling
Check
Manual: try upload with .jpg
extension but containing other content; monitor server response and behavior.
6.7 Business logic flaws
These are app-specific and most valuable:
Improper quota checks, pricing bypass, and race conditions (e.g., double spending).
Test flows (checkout, refunds) with manipulated parameters and concurrency.
7. Safe exploitation & proof-of-concept
When proving a finding:
Use non-destructive PoC (read-only requests; do not modify or delete data unless permitted).
Include request/response pairs, length/headers, and steps to reproduce.
If a destructive test is required for validation, obtain explicit permission.
8. Tools & utilities (short list)
Proxy / Manual testing: Burp Suite (Pro), OWASP ZAP
Crawling: Burp Spider, ZAP Spider
Automated scanning: ZAP, Nikto
Fuzzing/custom testing: custom C# HttpClient
scripts, ffuf
, wfuzz
Scripting: PowerShell/Bash for orchestration, C# for authenticated workflows or integration tests
SAST complement: Security Code Scan, Roslyn analyzers, SonarQube
Reporting: CSV/Markdown/HTML templates; create tickets in tracker (JIRA/GitHub)
9. Integrating pen-tests into your SDLC
Run automated scans on every major release (staging).
Add authenticated scans in CI for private endpoints (use test accounts).
Schedule periodic manual pen tests (quarterly or before major releases).
Track remediation and retest fixes automatically where possible.
You can orchestrate ZAP in CI and upload reports as artifacts. Use a test account and ensure credentials are securely injected into CI (secret variables).
10. Sample penetration testing checklist
Authentication
Rate limiting and lockout exist for login endpoints.
Multifactor authentication is supported for sensitive roles.
Password reset flows cannot be abused.
Authorization
Input handling
Parameterized DB queries/prepared statements are used.
Output encoding used for HTML and JS contexts.
Size and type checks for file uploads.
Session & cookies
Cookies include, and are appropriate SameSite
.
Sessions expire, and logout invalidates the session server-side.
CSRF & XSRF
Security headers & TLS
HSTS enabled (non-dev).
CSP, X-Frame-Options, and X-Content-Type-Options are present.
TLS 1.2+ enforced, no weak ciphers.
Logging & secrets
Business logic
11. Reporting: structure & what to include
For each finding, include:
Title & ID
Severity (Info / Low / Medium / High / Critical)
Affected components (URL, API path)
Description—what it is and why it matters
Reproduction steps—include exact HTTP request/response (redact sensitive data)
Proof-of-concept—safe, non-destructive example
Impact & risk
Recommended remediation—code snippets or configuration changes
References—OWASP, MSDN, docs
Example severity mapping
Critical—remote code execution, unauthenticated data exposure
High—authentication bypass, privilege escalation
Medium—stored XSS, SQLi (requires authentication)
Low—missing security header, info leak
12. Sample C# test harness
A simple C# test harness that runs a few automated checks and outputs a basic report.
// Minimal demo: run a set of checks and print summary
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.Linq;
class PentestMini
{
static async Task Main(string[] args)
{
var baseUrl = args.Length > 0 ? args[0] : "https://staging.example.com";
using var client = new HttpClient { BaseAddress = new Uri(baseUrl) };
Console.WriteLine($"Running quick checks against {baseUrl}\n");
// 1. Check security headers
var res = await client.GetAsync("/");
Console.WriteLine("Status: " + (int)res.StatusCode);
var headers = new[] { "X-Frame-Options", "X-Content-Type-Options", "Content-Security-Policy", "Referrer-Policy" };
foreach (var h in headers)
Console.WriteLine($"{h}: {(res.Headers.Contains(h) ? "Present" : "Missing")}");
// 2. Simple POST to state endpoint without CSRF (example)
var post = await client.PostAsync("/account/create", new StringContent("{\"dummy\":\"x\"}", System.Text.Encoding.UTF8, "application/json"));
Console.WriteLine($"/account/create => {(int)post.StatusCode} {post.StatusCode}");
// 3. Check login page cookie flags (GET)
if (res.Headers.TryGetValues("Set-Cookie", out var sc))
{
foreach (var c in sc)
{
Console.WriteLine("Set-Cookie -> " + c);
if (!c.Contains("HttpOnly")) Console.WriteLine(" Warning: cookie missing HttpOnly");
if (!c.Contains("Secure")) Console.WriteLine(" Warning: cookie missing Secure");
}
}
Console.WriteLine("\nQuick checks finished.");
}
}
This is a minimal starting point — expand with authenticated flows, role testing, and fuzzing.
13. Legal & ethical reminders
Penetration testing can break systems. Only test with explicit written authorization and follow your organization’s legal and safety requirements. If you find critical vulnerabilities in production, follow your incident response plan.