using System.Net; using System.Text; namespace SatelliteProvider.IntegrationTests; public static class SecurityTests { public static async Task RunAll(HttpClient httpClient) { RouteTestHelpers.PrintTestHeader("Test: Security (SEC-01..SEC-04)"); await Sec01_SqlInjectionViaCoordinates(httpClient); await Sec02_PathTraversalInTileServing(httpClient); await Sec03_OversizedRegionRequest(httpClient); await Sec04_MalformedJson(httpClient); Console.WriteLine("✓ Security Tests: PASSED"); } private static async Task Sec01_SqlInjectionViaCoordinates(HttpClient httpClient) { Console.WriteLine(); Console.WriteLine("SEC-01: SQL injection attempt in coordinate query string"); var injection = "' OR 1=1 --"; var url = $"/api/satellite/tiles/latlon?Latitude={Uri.EscapeDataString(injection)}&Longitude=37.647063&ZoomLevel=18"; var response = await httpClient.GetAsync(url); if (response.StatusCode != HttpStatusCode.BadRequest && response.StatusCode != HttpStatusCode.UnprocessableEntity) { throw new Exception($"SEC-01 expected 400/422 for non-numeric coordinate, got {(int)response.StatusCode}"); } Console.WriteLine($" ✓ Non-numeric coordinate rejected with HTTP {(int)response.StatusCode}"); } private static async Task Sec02_PathTraversalInTileServing(HttpClient httpClient) { Console.WriteLine(); Console.WriteLine("SEC-02: Path traversal attempt against tile serving endpoint"); var traversalPaths = new[] { "/tiles/../../etc/passwd", "/tiles/18/..%2F..%2Fetc%2Fpasswd/0", "/tiles/18/0/..%2F..%2Fetc%2Fpasswd" }; foreach (var path in traversalPaths) { var response = await httpClient.GetAsync(path); var status = (int)response.StatusCode; if (status == 200) { throw new Exception($"SEC-02 expected non-200 for traversal '{path}', got 200"); } Console.WriteLine($" ✓ Traversal '{path}' rejected with HTTP {status}"); } } private static async Task Sec03_OversizedRegionRequest(HttpClient httpClient) { Console.WriteLine(); Console.WriteLine("SEC-03: Oversized region request (sizeMeters beyond allowed cap)"); var regionId = Guid.NewGuid(); var body = $"{{\"id\":\"{regionId}\",\"lat\":47.461747,\"lon\":37.647063,\"sizeMeters\":1000000,\"zoomLevel\":18,\"stitchTiles\":false}}"; var content = new StringContent(body, Encoding.UTF8, "application/json"); var response = await httpClient.PostAsync("/api/satellite/request", content); var status = (int)response.StatusCode; if (status != 400 && status != 422) { throw new Exception($"SEC-03 expected 400/422 for oversized region (1,000,000m), got {status}"); } Console.WriteLine($" ✓ Oversized region rejected with HTTP {status}"); } private static async Task Sec04_MalformedJson(HttpClient httpClient) { Console.WriteLine(); Console.WriteLine("SEC-04: Malformed JSON body"); var malformed = "{ this is not json ::"; var content = new StringContent(malformed, Encoding.UTF8, "application/json"); var response = await httpClient.PostAsync("/api/satellite/request", content); var status = (int)response.StatusCode; if (status != 400 && status != 415 && status != 422) { throw new Exception($"SEC-04 expected 400/415/422 for malformed JSON, got {status}"); } Console.WriteLine($" ✓ Malformed JSON rejected with HTTP {status}"); } }