flawopen.com/path-traversal/Csharp
How Path.Combine discards root paths in C#, and how to verify boundaries using Path.GetFullPath and StringComparison.OrdinalIgnoreCase.
एक होटल के कमरे के कार्ड रीडर की कल्पना करें जिसे केवल दूसरी मंजिल के कमरे खोलने चाहिए। यदि कोई मेहमान कीपैड पर '../../master-safe' टाइप करता है, तो असुरक्षित ताला हॉलवे से बाहर निकलकर प्रबंधक की तिजोरी खोल देता है।
Web Application SecurityCWE-918.CWE-918CWE-918): Standard Common Weakness Enumeration classification for path-traversal-csharp.Defense-in-Depthएंडपॉइंट HTTP पैरामीटर के माध्यम से उपयोगकर्ता द्वारा प्रदान किया गया फ़ाइल नाम स्वीकार करता है।
हमलावर फ़ाइल नाम में '../' या '..%2f' जैसे रिलेटिव डायरेक्टरी ट्रैवर्सल सीक्वेंस डालता है।
बैकएंड कैनोनिकल पाथ को सत्यापित किए बिना बेस डायरेक्टरी के साथ पाथ को जोड़ देता है।
सर्वर सिस्टम की संवेदनशील फ़ाइलें (/etc/passwd, पासवर्ड या कुंजियाँ) पढ़कर हमलावर को भेज देता है।
// VULNERABLE: Path.Combine discards baseFolder if userInput has a leading slash
using System.IO;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class FileController : ControllerBase {
private readonly string _baseFolder = @"C:\App\Storage\Uploads";
[HttpGet("download")]
public IActionResult Download([FromQuery] string file) {
// If file is "\Windows\System32\cmd.exe", basePath is discarded!
// If file is "..\..\App.config", it breaks out of the folder
string targetPath = Path.Combine(_baseFolder, file);
if (!System.IO.File.Exists(targetPath)) return NotFound();
return PhysicalFile(targetPath, "application/octet-stream");
}
}
// HARDENED: Canonicalize path and assert directory prefix containment
using System;
using System.IO;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class FileController : ControllerBase {
private readonly string _baseFolder;
public FileController() {
_baseFolder = Path.GetFullPath(@"C:\App\Storage\Uploads");
}
[HttpGet("download")]
public IActionResult Download([FromQuery] string file) {
if (string.IsNullOrWhiteSpace(file)) return BadRequest("Invalid filename");
// 1. Strip leading slashes to prevent Path.Combine root discard
string cleanName = file.TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
// 2. Resolve canonical full path
string fullPath = Path.GetFullPath(Path.Combine(_baseFolder, cleanName));
// 3. Strict boundary containment check with DirectorySeparatorChar
string safePrefix = _baseFolder.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
if (!fullPath.StartsWith(safePrefix, StringComparison.OrdinalIgnoreCase)) {
return Forbid("Path traversal attempt detected");
}
if (!System.IO.File.Exists(fullPath)) return NotFound();
return PhysicalFile(fullPath, "application/octet-stream");
}
}
Path.Combine()।Path.GetFullPath() to resolve traversal dots।