Skip to content

File Path Traversal

File Path Traversal

Description

An application can allow an attacker to navigate through the file system beyond the intended boundaries. This can lead to unauthorized access to sensitive files or directories. By manipulating file paths, an attacker can bypass access controls and retrieve or modify critical data, such as configuration files, user credentials, or confidential documents. This vulnerability poses a significant threat as it enables the attacker to escalate privileges, execute arbitrary code, or launch further attacks on the system.

import 'package:file/local.dart';

void main() {
  var file = new LocalFileSystem();
  var f = file.file("../../passwords.txt");
  f.copy("pass.txt");
}

// Or changing the root of the current running process:

import 'package:file/file.dart';
import 'package:file/chroot.dart';
import 'package:file/local.dart';
import 'package:path/path.dart' as path;

void main() {
  final String root = path.canonicalize("../../..");
  final FileSystem newRoot = new ChrootFileSystem(
  const LocalFileSystem(),
  root,
);
import Foundation

func readSensitiveFile(fileURL: URL) -> String? {
    let fileManager = FileManager.default
    let fileContents = fileManager.contents(atPath: fileURL.path)

    return String(data: fileContents!, encoding: .utf8)
}

func main() {
    let userDirectory = FileManager.default.homeDirectoryForCurrentUser
    let userInput = "/path/to/user/input.txt"
    let fileURL = userDirectory.appendingPathComponent(userInput)

    if let contents = readSensitiveFile(fileURL: fileURL) {
        print("File contents: \(contents)")
    } else {
        print("Failed to read file.")
    }
}

main()
import java.io.File

fun readFile(filePath: String): String {
    val file = File("/var/www/files/$filePath")
    return file.readText()
}

fun main() {
    println("Enter the file name:")
    val fileName = readLine()

    try {
        val content = readFile(fileName!!)
        println("File content: $content")
    } catch (e: Exception) {
        println("Error: ${e.message}")
    }
}

Recommendation

Path containment: Normalize the path and check whether it's contained within the destination directory or not.

import 'package:file/local.dart';
import 'dart:io';

void main() {
  var fileSystem = LocalFileSystem();
  var currentDirectory = Directory.current.path;
  print(currentDirectory);
  var inputFile = File('$currentDirectory/../../passwords.txt');
  var outputFile = File('$currentDirectory/pass.txt');

  if (!isWithinDirectory(inputFile, currentDirectory) ||
      !isWithinDirectory(outputFile, currentDirectory)) {
    print("Invalid file path");
    return;
  }

  inputFile.copy(outputFile.path)
      .then((_) => print("File copied successfully"))
      .catchError((error) => print("Error: $error"));
}

bool isWithinDirectory(FileSystemEntity file, String directoryPath) {
  var fileDirectory = Directory(file.parent.path);
  var specifiedDirectory = Directory(directoryPath);
  return fileDirectory.path == specifiedDirectory.path ||
      fileDirectory.path.startsWith('${specifiedDirectory.path}${Platform.pathSeparator}');
}
import Foundation

func readSensitiveFile(fileURL: URL) -> String? {
    let fileManager = FileManager.default

    // Check if the fileURL is within the allowed directory
    if fileURL.pathComponents.contains("path") && fileURL.pathComponents.contains("to") && fileURL.pathComponents.contains("user") {
        let fileContents = fileManager.contents(atPath: fileURL.path)
        return String(data: fileContents!, encoding: .utf8)
    }

    return nil
}

func main() {
    let userDirectory = FileManager.default.homeDirectoryForCurrentUser
    let userInput = "/path/to/user/input.txt"
    let fileURL = userDirectory.appendingPathComponent(userInput)

    if let contents = readSensitiveFile(fileURL: fileURL) {
        print("File contents: \(contents)")
    } else {
        print("Failed to read file.")
    }
}

main()
import java.io.File

fun readFile(filePath: String): String {
    val sanitizedFilePath = filePath.replace("..", "").replace("/", "")
    val file = File("/var/www/files/$sanitizedFilePath")
    return file.readText()
}

fun main() {
    println("Enter the file name:")
    val fileName = readLine()

    try {
        val content = fileName?.let { readFile(it) }
        println("File content: $content")
    } catch (e: Exception) {
        println("Error: ${e.message}")
    }
}

Absolute Path Usage: Prefer using absolute paths instead of relative paths whenever possible. By using absolute paths, the application explicitly specifies the exact location of the file or directory, leaving no room for interpretation.

import 'dart:io';
import 'package:path/path.dart' as path;

void main() {
  final absolutePath = '/path/to/file.txt';
  var file = File(absolutePath);

  // print('File name: ${path.basename(dir.file.path)}');
  print('File name: ${path.basename(file.path)}');
}
import Foundation

func main() {
    let absolutePath = "/path/to/file.txt"
    let fileManager = FileManager.default

    if fileManager.fileExists(atPath: absolutePath) {
        // Perform operations on the file
        print("File exists at \(absolutePath)")
    } else {
        print("File not found at \(absolutePath)")
    }
}

main()
import java.io.File

fun main() {
    val absolutePath = "/path/to/file.txt"
    val file = File(absolutePath)

    if (file.exists()) {
        // Perform operations on the file
        println("File exists at $absolutePath")
    } else {
        println("File not found at $absolutePath")
    }
}

Standards

  • OWASP_MASVS_L1:
    • MSTG_PLATFORM_2
  • OWASP_MASVS_L2:
    • MSTG_PLATFORM_2
  • GDPR:
    • ART_5
    • ART_32
  • PCI_STANDARDS:
    • REQ_2_2
    • REQ_6_2
    • REQ_6_3
    • REQ_7_3
    • REQ_11_3
  • OWASP_MASVS_v2_1:
    • MASVS_PLATFORM_2
  • SOC2_CONTROLS:
    • CC_2_1
    • CC_4_1
    • CC_7_1
    • CC_7_2
    • CC_7_4
    • CC_7_5