Aller au contenu

File Path Traversal

Traversée de Chemin de Fichier

Description

Une application peut permettre à un attaquant de naviguer à travers le système de fichiers au-delà des limites prévues. Cela peut conduire à un accès non autorisé à des fichiers ou des répertoires sensibles. En manipulant les chemins de fichiers, un attaquant peut contourner les contrôles d'accès et récupérer ou modifier des données critiques, telles que des fichiers de configuration, des informations d'identification d'utilisateurs ou des documents confidentiels. Cette vulnérabilité représente une menace importante car elle permet à l'attaquant d'élever ses privilèges, d'exécuter du code arbitraire ou de lancer de nouvelles attaques sur le système.

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}")
    }
}

Recommandation

Confinement de chemin : Normalisez le chemin et vérifiez s'il est contenu ou non dans le répertoire de destination.

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}")
    }
}

Utilisation de chemin absolu : Préférez l'utilisation de chemins absolus aux chemins relatifs dans la mesure du possible. En utilisant des chemins absolus, l'application spécifie explicitement l'emplacement exact du fichier ou du répertoire, ne laissant aucune place à l'interprétation.

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")
    }
}

Liens

Normes

  • 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