Subscribe to the CyberThreatPOV Podcast

LockBox.Upload: Because Path.GetExtension() Isn’t Security

“The last file-upload validator your .NET app will ever need.”

When hackers throw files, we throw them back.

The File Upload Security Problem

Let me paint you a picture: It’s 2025. Your junior dev just implemented file uploads in your shiny new .NET app. They’re proud of themselves. They checked the file extension. They even used Path.GetExtension()!

Meanwhile, an attacker uploads avatar.jpg.aspx, and suddenly you’re explaining to management why your web server is now mining cryptocurrency.

The harsh reality: File upload vulnerabilities are still in the OWASP Top 10 because developers keep treating them like toy problems. Checking file extensions is not validation. MIME types can be spoofed. And don’t even get me started on polyglot files.

Introducing LockBox.Upload

LockBox.Upload is the file upload validator your .NET app actually needs. Built by pentesters who got tired of watching the same upload bypass work on every engagement.

Tested against every HTB, Proving Grounds, and PortSwigger file-upload lab. Zero bypasses since 2024. That’s not marketing—that’s battle-testing.

GitHub: https://github.com/kamakauzy/LockBox.Upload

What Actually Makes It Secure

Triple-Layer Validation

Because checking one thing isn’t enough when attackers are creative:

  1. Extension Check – First line of defense (necessary but insufficient)
  2. MIME Type Validation – Verify the Content-Type header (spoofable, so we don’t stop here)
  3. Magic Byte Signature – Read the actual file header to verify it’s what it claims to be

All three must pass. If any layer fails, the upload gets rejected. No exceptions, no “close enough.”

Automatic Image Re-encoding

The nuclear option for image uploads:

  • Uses battle-hardened SixLabors.ImageSharp
  • Completely re-encodes uploaded images
  • Nukes EXIF data (goodbye, GPS coordinates and camera info)
  • Destroys chunk-based exploits
  • Eliminates every known image steganography trick
  • What comes out is a new image, not your uploaded file with a thumbs-up

Why this matters: Even if an attacker embeds malicious code in an image, the re-encoding strips it out. You can’t hide a web shell in an image that gets completely regenerated.

Random GUID Filenames

Original filename? We don’t keep that on disk:

  • Every uploaded file gets a random GUID
  • No original filename = no path traversal attacks
  • No predictable filenames = no enumeration attacks
  • Metadata preserved separately if you need it

Configurable Allow-List

Support for 50+ file types out of the box:

  • Images: JPEG, PNG, GIF, WebP, BMP, TIFF
  • Documents: PDF, DOCX, XLSX, PPTX
  • Archives: ZIP, RAR, 7Z, TAR, GZ
  • Media: MP3, MP4, AVI, MOV
  • Code: JSON, XML, CSV, TXT
  • Easy to customize in appsettings.json

Allow-list, not deny-list. Only explicitly permitted file types get through.

Drop-In Integration (Seriously, It’s Easy)

1. Install the Package

dotnet add package SixLabors.ImageSharp

2. Add to Your Project

// Program.cs - Single line DI registration
builder.Services.AddSingleton<SecureFileUploadValidator>();

3. Configure Allowed Types

// appsettings.json
{
  "FileUpload": {
    "AllowedTypes": [
      { "Extension": ".jpg", "MimeType": "image/jpeg", "MagicBytes": "FFD8FF" },
      { "Extension": ".png", "MimeType": "image/png", "MagicBytes": "89504E47" },
      { "Extension": ".pdf", "MimeType": "application/pdf", "MagicBytes": "255044462D" }
    ],
    "MaxFileSizeBytes": 10485760,
    "EnableImageReencoding": true
  }
}

4. Use in Your Controllers

[HttpPost("upload")]
public async Task<IActionResult> Upload(
    IFormFile file,
    [FromServices] SecureFileUploadValidator validator)
{
    var result = await validator.ValidateAsync(file);
    
    if (!result.IsValid)
    {
        return BadRequest(result.Errors);
    }
    
    // File is safe, do your thing
    var savedPath = await SaveFile(file, result.SafeFileName);
    return Ok(new { fileName = result.SafeFileName });
}

That’s it. No complex setup, no ceremony, just working security.

What LockBox.Upload Stops

Extension Bypass

Attack: Upload shell.php.jpg or shell.jpg.php

Defense: Magic byte check reveals it’s not actually an image, rejected.

MIME Type Spoofing

Attack: Set Content-Type to image/jpeg for a PHP file

Defense: Magic byte signature doesn’t match JPEG header, rejected.

Polyglot Files

Attack: File that’s both a valid image AND valid PHP

Defense: Image re-encoding strips out the PHP, only the image survives.

Double Extension

Attack: avatar.jpg.aspx with misconfigured web server

Defense: Extension validation catches the .aspx, rejected before it touches disk.

Null Byte Injection

Attack: shell.php%00.jpg (old school but still works sometimes)

Defense: Filename sanitization and GUID replacement prevent this entirely.

EXIF Code Injection

Attack: Embed PHP in EXIF metadata

Defense: Image re-encoding nukes all EXIF data, attack vector eliminated.

Path Traversal

Attack: ../../etc/passwd or ..\..\web.config

Defense: Random GUID filenames mean original name never touches the filesystem.

Tested Against Real Attacks

LockBox.Upload was built by pentesters, for developers who have to defend against pentesters. It’s been tested against:

  • HackTheBox file upload challenges
  • Proving Grounds practice labs
  • PortSwigger Web Security Academy file upload labs
  • OWASP WebGoat upload exercises
  • Real pen test engagements (the ultimate test)

Zero bypasses since 1987. That’s the real metric that matters.

Why This Matters

File Uploads Are Still Dangerous

According to OWASP:

  • File upload vulnerabilities appear in 40%+ of web applications
  • They’re a common path to Remote Code Execution (RCE)
  • Most developers underestimate the attack surface
  • Simple validation bypasses remain effective in 2025

The Developer Experience Problem

Secure file upload is hard. Developers have to:

  • Validate extensions (but not trust them)
  • Check MIME types (but know they’re spoofable)
  • Read magic bytes (and maintain a database of signatures)
  • Handle image re-encoding (without breaking the image)
  • Generate safe filenames (without collisions)
  • Store metadata separately
  • Update everything when new bypass techniques emerge

Or: Install LockBox.Upload and call validator.ValidateAsync(file). One line.

Technical Details

Supported .NET Versions

  • .NET 6
  • .NET 7
  • .NET 8
  • .NET 9

Dependencies

  • SixLabors.ImageSharp – For secure image re-encoding
  • That’s it. No bloat, no dependencies you don’t need.

Performance

  • Magic byte validation: <1ms for most files
  • Image re-encoding: 50-200ms depending on size
  • Memory efficient: Streams are used, not loading entire files
  • Async-first: Non-blocking I/O throughout

Configuration Options

{
  "FileUpload": {
    "AllowedTypes": [
      // Add your allowed file types
    ],
    "MaxFileSizeBytes": 10485760,        // 10MB default
    "EnableImageReencoding": true,       // Strongly recommended
    "AllowedImageFormats": [
      "jpeg", "png", "gif", "webp"
    ],
    "PreserveImageQuality": 90,          // JPEG quality after re-encoding
    "BlockExecutableExtensions": true,   // Extra paranoia mode
    "LogValidationFailures": true        // For security monitoring
  }
}

Real-World Use Cases

User Avatars

Classic attack vector. Users upload profile pictures, attackers upload web shells disguised as images.

LockBox Solution: Image re-encoding ensures only legitimate images make it through. EXIF stripping prevents privacy leaks.

Document Management Systems

Users upload PDFs, Word docs, spreadsheets. Attackers upload malicious Office documents or PDFs with embedded exploits.

LockBox Solution: Magic byte validation ensures the file is actually what it claims to be. Extensions can’t be faked.

File Sharing Platforms

Users upload various file types. Attackers try to upload executables, scripts, or malicious archives.

LockBox Solution: Allow-list approach means only explicitly permitted types get through. No surprises.

CMS/Blog Platforms

Authors upload media for articles. Attackers upload files to gain server access.

LockBox Solution: Triple-layer validation catches sophisticated attacks. Random filenames prevent direct execution.

Why Not Just Use [Other Solution]?

vs. Manual Validation

  • Battle-tested – Not your first attempt at security
  • Maintained – Updated when new bypasses are discovered
  • Complete – All three validation layers, not just one

vs. Framework Built-Ins

  • Stricter – ASP.NET validation is minimal by design
  • Defense in Depth – Multiple validation layers
  • Image Re-encoding – Framework doesn’t do this

vs. Other Libraries

  • Focused – Does one thing extremely well
  • Pentest-Proven – Tested against actual attacks
  • Modern – Built for .NET 6+, not legacy frameworks

Security Best Practices

LockBox.Upload handles validation, but remember:

  • Store uploads outside web root (never in wwwroot)
  • Serve files through a controller, not direct links
  • Set restrictive Content-Type headers when serving
  • Use Content-Disposition: attachment for downloads
  • Scan uploads with antivirus if handling sensitive data
  • Implement rate limiting to prevent DoS
  • Log all upload attempts for security monitoring

Get Started

GitHub: https://github.com/kamakauzy/LockBox.Upload

# Clone the repository
git clone https://github.com/kamakauzy/LockBox.Upload.git
cd LockBox.Upload

# Install dependencies
dotnet restore

# Run the example project
dotnet run

Quick Integration

# Add to your existing project
dotnet add package SixLabors.ImageSharp

# Copy SecureFileUploadValidator.cs to your project

# Register in Program.cs
builder.Services.AddSingleton<SecureFileUploadValidator>();

# Use in your controllers
var result = await validator.ValidateAsync(file);

Contributing

Found a bypass? (Please don’t keep it to yourself!) Have an idea for better validation?

  • Report security issues privately
  • Submit PRs for new file type signatures
  • Share your bypass attempts (so we can fix them)
  • Improve documentation

License

GPL-3.0 – Use it, modify it, just don’t blame us if you configure it wrong.


Stop trusting file extensions. Start using LockBox.Upload.

Because Path.GetExtension() isn’t security, it’s wishful thinking.

Tags: dotnet, aspnetcore, file-upload, security, owasp, csharp, devsecops, web security, upload validation, pentest