Security Notes
  • Whoami
  • Pentesting
    • WEP-Pen
      • Reconnaissance
      • Enumeration
      • OWSAP TOP 10
        • Injection
          • Cross Site Scripting
            • Cross Site Scripting
            • Exploitation
            • Protections
          • SQL Injection
            • SQL Injection Overview
          • NoSQL Injection
          • CRLF Injection
          • XML Injection
        • Broken Access Control
          • Path Traversal
          • Sensitive Cookie with Improper SameSite Attribute
          • Link Following
          • Incorrect Default Permissions
          • Information disclosure
          • CSRF
            • csrf checklist
          • 403 bypass
          • Exposure of WSDL File Containing Sensitive Information
          • bussiness logic checklist
          • 2FA bypass checklist
          • admin panal checklist
          • idor checklist
          • Authentication checklist
          • reset_password_checklist
          • ATO
        • Cryptographic Failures
          • Cryptographic Failure
          • Weak Encoding for Password
          • Improper Following of a Certificate's Chain of Trust
            • Understanding Digital Certificates : Self-Signed and CA-Signed Certificate **
            • Transport Layer Security (TLS) and SSL **
          • Clear Text Transmission Of Sensitive Data
            • SSLStripping **
        • Insecure Design
        • Security Misconfiguration
          • CORS Miscofigration
          • Mail Server Misconfiguration
        • Vulnerable and Outdated Components
          • Using Components with Known Vulnerabilities
        • Identification and Authentication Failures
          • JWT Hacking
          • SAML Authentication bypass
        • Software and Data Integrity Failures
          • mass assignment
          • PostMessage Vulnerabilities
            • PostMessage Vulnerabilities
            • Blocking main page to steal postmessage
            • Bypassing SOP with Iframes - part 1
            • Bypassing SOP with Iframes - part 2
            • Steal postmessage modifying iframe location
        • Security Logging and Monitoring Failures
        • Server-Side Request Forgery (SSRF)
          • SSRF
      • Checklists
        • aem misconfiguration
        • exif_geo
        • xss
        • Session Management
        • Authorization
        • cookie
        • Django
        • Symfony
        • json
        • bypass rate limit
        • Rce
        • Register Page
      • eWPTXv2 Preparation
        • Encoding & Filtering
        • Evasion Basics
        • Cross-site scripting (XSS)
        • XSS Filter Evasion
        • Cross-site request forgery (CSRF
        • HTML5
      • API-Pen
        • API Discovry
        • Reverse Engineering API Documentation
        • Excessive Data Exposure
        • Vulnerability Scanning
        • API Authentication Attacks
          • Classic Authentication Attacks
          • API Token Attacks
        • API Authorization Attacks
          • Broken Object Level Authorization (BOLA)
          • Broken Function Level Authorization
        • Improper Assets Management
        • Mass Assignment
        • SSRF
        • Injection Attacks in API
        • Evasive Maneuvers
        • GraphQL Vulnerabilities
    • NET-Pen
      • Active Directory Pentesting
        • Active Directory Components
        • Initial Attack Vectors
          • LLMNR Poisoning
          • SMB Relay Attacks
          • IPv6 Attacks ( IPv6 DNS Takeover )
          • Printer Hacking
          • Methodology
          • Some Other Attacks
            • Zerologon (CVE-2020-1472)
            • PrintNightmare (CVE-2021-1675)
        • Post-Compromise Attacks
          • Pass Attacks
          • Kerberoasting Attack
          • Token Impersonation Attack
          • LNK File Attack
          • GPP / cPassword Attacks
          • Mimikatz
          • Methodology
        • We've Compromised the Domain
          • Dumping the NTDS.dit
          • Golden Ticket Attacks
          • Methodology
        • Case Study
        • Password Attacks
      • Attack Vectors by Port
        • FTP 21
        • SSH 22
        • Telnet 23 - 2323
        • SMTP 25
        • DNS 53
        • Kerberos 88
        • POP 110-995
        • RPC 111
        • Ident 113
        • NNTP 119
        • NetBIOS 137-138
        • SMB / Samba 135-139, 445
        • MSRPC 135
        • SNMP 161
        • LDAP 389,636
        • Modbus 502
        • OpenSSL 1337
        • Ms-SQL 1433
        • Oracle Listener 1521 1522 1529
        • NFS 2049
        • MySql 3306
        • RDP 3389
        • ADB Android Debug Bridge 5555
        • WinRM 5985 5986
        • VNC 5800 5900
        • Redis 6379
        • Unreal IRC 6667
        • Tomcat 8080
        • MongoDB 27017
        • http 80
      • Network basics
      • Information Gathering
      • Privilege Escalation
        • Windows Privilege Escalation
        • Linux Privilege Escalation
    • write-ups
      • How i found a Privilege Escalation via Impersonation Features feature
      • How I was able to discover ATO Via IDOR vulnerability
      • Easy full Account Takeover via Facebook OAuth Misconfiguration
Powered by GitBook
On this page
  • Vulnerable Scenarios and Examples
  • Relative Path
  • Absolute Path Traversal
  • Traversal Sequences Stripped Non-Recursivel
  • File Path Traversal with URL Encoding or Double Encoding
  • Validation of Path Start
  • File Path Traversal with Validation of File Extension and Null Byte Bypass
  • How to prevent a path traversal attack
  • Lab 1 : File path traversal, simple case
  • Lab 2 : File path traversal, traversal sequences blocked with absolute path bypass
  • Lab 3 : File path traversal, traversal sequences stripped non-recursively
  • Lab 4 : File path traversal, traversal sequences stripped with superfluous URL-decode
  • Lab 5 : File path traversal, validation of start of path
  • Lab 6 : File path traversal, validation of file extension with null byte bypass
  1. Pentesting
  2. WEP-Pen
  3. OWSAP TOP 10
  4. Broken Access Control

Path Traversal

Path Traversal vulnerabilities, also known as Directory Traversal, allow attackers to manipulate file paths in order to access restricted files on a server. By exploiting this vulnerability, attackers can gain access to sensitive data, and potentially modify or delete critical files, leading to further exploitation, including full server compromise.

Vulnerable Scenarios and Examples

Relative Path

Understanding Canonicalization ".." :

Canonicalizing a path is the process of resolving the path to its simplest, absolute form by eliminating redundant elements such as .. (parent directory) or symbolic links. Here are some examples:

  • Input: /var/www/project/../index.html

    • Canonicalized Path: /var/www/index.html

  • Input: /usr/local/bin/../bin/ls

    • Canonicalized Path: /usr/local/bin/ls

Let's say each user has their own directory which stores confidential data. To access the files, the user passes a path relative to this directory. It is obvious that other users' directories are nearby. Then, using the dot-dot-slash sequence ('..' or '../'), attackers may access the files of any user. They easily gain access to the adminPasswords.txt file, passing the following string as the path:

../admin/adminPasswords.txt 

Note that Windows filenames are delimited by backslash (''). To prevent such an attack, it's not enough to check that the string does not start with '../'. Attackers can use the following string for malicious purposes:

myFolder/../../admin/adminPasswords.txt

At first, they access the myFolder directory and then the directory containing each user's data. Then, attackers access the admin directory and get the file.

These examples show a possible way to perform a relative path traversal attack. Note that dot-dot-slash sequences allow an attacker to gain access to any file or directory on the disk.

Your application must be secured so that a user could not access other directories. The easiest way to prevent an attack is to check strings for dot-dot-slash sequences. Unfortunately, that's not enough to ensure complete security.

Vulnerable Code Example

In this scenario, user input is directly concatenated with a base directory path without validation, leading to a basic path traversal vulnerability:

const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();

app.get('/vuln', (req, res) => {
  const filename = req.query.file;
  if (!filename) {
    res.status(400).send('You need a parameter called file.');
    return;
  }
  // Vulnerable file path construction
  const filePath = path.join(__dirname, filename);
  fs.readFile(filePath, 'utf8', (err, data) => {
    if (err) {
      res.status(500).send('Error reading file');
    } else {
      res.send(data);
    }
  });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Attack Example

By accessing the endpoint /vuln?file=../../etc/passwd, an attacker can exploit the vulnerability to expose sensitive files like /etc/passwd.

Prevention Code

To mitigate Relative Path Traversal vulnerabilities, the following secure approach can be implemented:

const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();

app.get('/vuln', (req, res) => {
  const filename = req.query.file;
  if (!filename) {
    res.status(400).send('You need a parameter called file.');
    return;
  }

  // Sanitize the filename to prevent directory traversal
  const sanitizedFilename = path.basename(filename);
  const filePath = path.join(__dirname, sanitizedFilename);

  fs.readFile(filePath, 'utf8', (err, data) => {
    if (err) {
      res.status(500).send('Error reading file');
    } else {
      res.send(data);
    }
  });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Key Prevention Measures:

  1. Path Sanitization: By using path.basename(), only the filename is retained, discarding any path components that could lead to directory traversal.

  2. Secure Path Construction: path.join() ensures that the constructed path is relative to the intended directory, eliminating the risk of accessing unauthorized files.


Absolute Path Traversal

An absolute path traversal attack is easier to perform. Let's say we use the following JavaScript code to process a user's request:

const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();

app.get('/vuln', (req, res) => {
  let filePath = req.query.file;
  
  if (!filePath) {
    res.status(400).send('You need a parameter called file.');
    return;
  }
  if (filePath.includes('../')) {
    res.send('Hacker caught!');
    return;
  }

  // Absolute path handling
  filePath = path.resolve(__dirname, filePath);
  fs.readFile(filePath, 'utf8', (err, data) => {
    if (err) {
      res.send('Error reading file.');
    } else {
      res.send(data);
    }
  });
});

app.get('/', (req, res) => {
  res.send('Hi, the /vuln endpoint is what you want');
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

In this example, although the application tries to block ../, it may still be vulnerable, You might be able to use an absolute path from the filesystem root, such as :

filename=/etc/passwd

to directly reference a file without using any traversal sequences.

Prevention Code

To mitigate Relative Path Traversal vulnerabilities, the following secure approach can be implemented:

const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();

app.get('/vuln', (req, res) => {
  const filename = req.query.file;
  if (!filename) {
    res.status(400).send('You need a parameter called file.');
    return;
  }

  // Sanitize the filename to prevent directory traversal
  const sanitizedFilename = path.basename(filename); // Strip any path traversal characters (e.g., '..')
  
  // Securely construct the path relative to the current directory
  const resolvedPath = path.resolve(__dirname, sanitizedFilename);

  // Check if the resolved path is within the current directory
  if (!resolvedPath.startsWith(__dirname)) {
    return res.status(400).send('Invalid file path');
  }

  // Optional: You could implement a whitelist to limit accessible files
  const allowedFiles = ['file1.txt', 'file2.txt']; // Replace with your allowed files
  if (!allowedFiles.includes(sanitizedFilename)) {
    return res.status(403).send('Access to this file is not allowed');
  }

  // Check if the file exists before attempting to read it
  fs.exists(resolvedPath, (exists) => {
    if (!exists) {
      return res.status(404).send('File not found');
    }

    // Read the file if it exists
    fs.readFile(resolvedPath, 'utf8', (err, data) => {
      if (err) {
        res.status(500).send('Error reading file');
      } else {
        res.send(data);
      }
    });
  });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Traversal Sequences Stripped Non-Recursivel

This version demonstrates how a server might attempt to mitigate path traversal attacks by removing traversal sequences like ../, but only non-recursively, which means only the first occurrence will be stripped:

const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();

app.get('/vuln', (req, res) => {
  let filename = req.query.file;
  
  if (!filename) {
    res.status(400).send('You need a parameter called file.');
    return;
  }

  // Mitigate path traversal by removing traversal sequences once (non-recursively)
  filename = filename.replace(/\\.\\.\\//g, '');
  
  // Ensure file path is securely constructed
  const filePath = path.join(__dirname, filename);

  fs.readFile(filePath, 'utf8', (err, data) => {
    if (err) {
      if (err.code === 'ENOENT') {
        res.status(404).send('File not found');
      } else {
        res.status(500).send('Internal server error');
      }
    } else {
      res.send(`${data}`);
    }
  });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

While this approach removes one occurrence of a traversal sequence (../), attackers could craft input with multiple instances of the sequence, such as ....//....//.../, which may still allow access to restricted files if the server doesn’t repeatedly sanitize or check for further sequences.

Example Attack:

An attacker might pass the filename as ....//....//etc/passwd. While one ../ is stripped, the remaining traversal sequence (....//....//) could still resolve to a directory outside the intended path, allowing access to sensitive files like /etc/passwd

Solution: Recursive or Multiple Layer Sanitization

Instead of stripping traversal sequences just once, you could recursively sanitize the filename or employ more comprehensive validation checks. Additionally, regular expressions like the one in your code can be expanded to account for various other attack vectors.


File Path Traversal with URL Encoding or Double Encoding

If a server strips directory traversal sequences like ../ but does so in a non-recursive and simplistic manner, attackers may exploit the URL encoding mechanism to bypass this defense.

For example:

  • ../ can be URL-encoded as %2e%2e%2f.

  • Double URL-encoded traversal like ..%c0%af or ..%ef%bc%8f could also bypass some basic sanitization mechanisms.

If the application only strips ../ but doesn't account for URL encoding or double encoding, attackers could craft a payload like:

  • ../../../../../etc/passwd encoded as %2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc/passwd.


Validation of Path Start

Another defense is to check if the provided filename starts with a specific base folder (e.g., /var/www/images). However, this can be bypassed if attackers include the base folder followed by traversal sequences, such as:

  • filename=/var/www/images/../../../etc/passwd.

Even though the filename might start with the correct base folder, the traversal sequences allow access to arbitrary paths outside of the intended directory.

The application would only check the start of the path, so the request would be accepted as valid, even though it leads outside the allowed directory.

const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();
// Define the base folder
// You can change it to your base folder
const baseFolder = '/home/kali/VulnerableLabs/PathTraversal/lab5';
// Vulnerable endpoint
app.get('/vuln', (req, res) => {
    // Get the filename parameter from the query string
    const filename = req.query.filename;
    
    if (!filename) {
        return res.status(400).send('Provide filename parameter \\n\\n your working directory is /home/kali/VulnerableLabs/PathTraversal/lab5');
    }
    // Check if the filename starts with the expected base folder
    if (!filename.startsWith(baseFolder)) {
        return res.status(400).send('Invalid filename');
    }
    // Construct the full path to the file
    const filePath = path.normalize(filename);
    // Read the file content
    fs.readFile(filePath, 'utf8', (err, data) => {
        if (err) {
            return res.status(500).send('Error reading file');
        }
        // Display the file content in the response
        res.send(`${data}`);
    });
});
app.get('/', (req, res) => {
  res.send('Hi to 5th Lab Path Traversal, the /vuln endpoint is what you want');
});
// Start the server
app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

File Path Traversal with Validation of File Extension and Null Byte Bypass

Some applications validate the file extension (e.g., .png) to restrict access to specific file types. However, attackers can bypass this restriction by injecting a null byte (%00) after the filename, effectively truncating the file path and allowing access to sensitive files.

Example:

  • filename=../../../etc/passwd%00.png

The null byte (%00) terminates the string after etc/passwd, so the application will read the file as ../../../etc/passwd, bypassing the .png extension check.


How to prevent a path traversal attack

The most effective way to prevent path traversal vulnerabilities is to avoid passing user-supplied input to filesystem APIs altogether. Many application functions that do this can be rewritten to deliver the same behavior in a safer way.

If you can’t avoid passing user-supplied input to filesystem APIs, we recommend using two layers of defense to prevent attacks:

  • Validate User Input:

    • Always validate user input before processing it. This can be achieved by allowing only expected values or characters in the input. A whitelist approach is ideal, where the input is compared against a predefined list of safe values. If a whitelist isn't feasible, use a regular expression to ensure the input contains only safe characters, such as alphanumeric characters.

  • Canonicalize the Path:

    • After validation, append the input to the base directory and use the filesystem API to canonicalize the path. This step resolves any symbolic links, redundant separators, or references to parent directories (e.g., ..). It ensures the resulting path is an absolute, unique representation that can't escape the intended directory structure.

  • Verify the Path:

    • Verify that the canonicalized path starts with the expected base directory. This ensures that the final path resides within the intended directory and prevents unauthorized access to other locations.

    Node.js Example for Preventing Path Traversal:

    Below is a Node.js code example demonstrating how to prevent path traversal attacks using these principles:

    const path = require('path');
    const fs = require('fs');
    
    // Function to validate user input
    function validateInput(userInput) {
        // Example validation: allow only alphanumeric characters
        const alphanumericRegex = /^[a-zA-Z0-9]+$/;
        return alphanumericRegex.test(userInput);
    }
    
    // Function to process user input and prevent path traversal
    function processInput(baseDir, userInput) {
        // Validate user input
        if (!validateInput(userInput)) {
            throw new Error('Invalid input');
        }
    
        // Normalize and sanitize user input
        const userInputSafe = path.normalize(userInput);
        const fullPath = path.join(baseDir, userInputSafe);
    
        // Canonicalize the path
        const canonicalPath = path.resolve(fullPath);
    
        // Ensure that the canonical path starts with the expected base directory
        if (!canonicalPath.startsWith(path.resolve(baseDir))) {
            throw new Error('Invalid path');
        }
    
        // Proceed with filesystem operation using the safe path
        fs.readFile(canonicalPath, (err, data) => {
            if (err) {
                console.error('Error reading file:', err);
            } else {
                console.log('File content:', data.toString());
            }
        });
    }
    
    // Example usage
    const baseDirectory = '/path/to/base/directory';
    const userInput = 'file.txt'; // User-supplied input
    processInput(baseDirectory, userInput);

in this code:

  • validateInput function validates the user input. You can customize this function according to your requirements.

  • processInput function processes the user input by appending it to the base directory, canonicalizing the path, and verifying that the canonical path starts with the expected base directory.

  • If any validation or verification fails, an error is thrown, preventing a potential path traversal attack.

  • Ensure to replace /path/to/base/directory with the actual base directory in your application.

Remember that this is a basic example. Depending on specific use case and requirements, you may need to enhance the validation and error handling logic. Additionally, consider implementing additional security measures such as access controls and permissions to further mitigate risks.


Lab 1 : File path traversal, simple case

Aim: Read content of /etc/passwd

Click Access the lab

Website will launch on new tab where we will practice.

Then run burpsuite.

In burpsuite under HTTP history , click on filter and select images and css

Then reload the lab.

In the HTTP history, we can see filename parameter is loading various images, we will use one of these request , change the parameter and send the changed request to server.

Select any one of the request, right click and send it to repeater (or CTRL + R)

Our aim is to read the content of /etc/passwd ,but we don’t know the current location of the files filename parameter is fetching from. So we will use ../ which is used to move one directory up.

For example. If we are currently in /var/www/images folder then command ../ will move us one directory up into /var/www/ and multiple ../ will move us multiple directory up. ../../../../../../../../../../../../ will move us to root directory.

../../../../../etc/passwd will move to 5 directory up and then go to /etc/passwd . Thus loading the content of the passwd file.

Lab 1 completed successfully.


Same as before intercept the request and send it to repeater. For this lab traversal sequences is blocked but we can bypass this by providing absolute path.

By providing absolute path /etc/passwd we can successfully complet the lab.


Same as before, send the interesting request to repeater.

In this lab , there is some kind of filter/ sanitization which is stripping or removing the traversal sequence.

We can bypass this stripping easily by:

by adding extra ../ in between the payload we can bypass this filter. Note this will not work in recursive stripping process.


Previous method not working. We can come around this time by url encoding the payload .

By double url encoding ../../../../../../etc/passwd we can complete the lab.


An application may require the user-supplied filename to start with the expected base folder, such as /var/www/images. In this case, it might be possible to include the required base folder followed by suitable traversal sequences. For example:


An application may require the user-supplied filename to end with an expected file extension, such as .png. In this case, it might be possible to use a null byte to effectively terminate the file path before the required extension. For example:

filename=../../../etc/passwd%00.png everything after null byte %00 is ignored while fetching the file.

Which completes the lab.

PreviousBroken Access ControlNextSensitive Cookie with Improper SameSite Attribute

Last updated 2 months ago

Link to lab1:

Lab 2 : , traversal sequences blocked with absolute path bypass

link to lab2:

Image explaining absolute path vs relative path.

Lab 3 : , traversal sequences stripped non-recursively

link to lab:

stripping traversal sequence ../

Lab 4 : , traversal sequences stripped with superfluous URL-decode

link to lab 4:

Lab 5 : , validation of start of path

link to lab5:

Lab 6 : , validation of file extension with null byte bypass

link to lab:

https://portswigger.net/web-security/file-path-traversal/lab-simple
File path traversal
https://portswigger.net/web-security/file-path-traversal/lab-absolute-path-bypass
File path traversal
https://portswigger.net/web-security/file-path-traversal/lab-sequences-stripped-non-recursively
File path traversal
https://portswigger.net/web-security/file-path-traversal/lab-superfluous-url-decode
File path traversal
https://portswigger.net/web-security/file-path-traversal/lab-validate-start-of-path
File path traversal
https://portswigger.net/web-security/file-path-traversal/lab-validate-file-extension-null-byte-bypass