Path Traversal
Traversée de répertoire (Path Traversal)
Description
Les vulnérabilités de traversée de répertoire se produisent lorsque l'entrée utilisateur est mal gérée par une application web, permettant à un attaquant de naviguer en dehors de la structure de répertoires prévue et d'accéder à des fichiers ou répertoires non autorisés. L'exploitation de cette vulnérabilité implique la manipulation des entrées afin d'y inclure des séquences capables de traverser le système de fichiers, comme ../.
L'impact des vulnérabilités de traversée de répertoire peut aller de la divulgation d'informations sensibles à l'exécution de code arbitraire, selon le contexte dans lequel la vulnérabilité est exploitée.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.io.BufferedReader;
import java.io.FileReader;
@SpringBootApplication
public class PathTraversalExample {
public static void main(String[] args) {
SpringApplication.run(PathTraversalExample.class, args);
}
}
@RestController
class FileController {
@PostMapping("/processFile")
public String processFile(@RequestBody String userInput) {
try {
// Vulnerable path traversal without proper input validation
String filePath = "/var/www/data/" + userInput;
// Process the file content (vulnerable code)
return processFileContent(filePath);
} catch (Exception e) {
return "Error processing file content: " + e.getMessage();
}
}
private String processFileContent(String filePath) throws Exception {
// Read the file content
BufferedReader br = new BufferedReader(new FileReader(filePath));
StringBuilder content = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
content.append(line).append("\n");
}
br.close();
return "Processed file content:\n" + content.toString();
}
}
const express = require('express');
const bodyParser = require('body-parser');
const fs = require('fs');
const app = express();
const port = 3000;
app.use(bodyParser.text());
app.post('/processFile', (req, res) => {
try {
// Vulnerable path traversal without proper input validation
const filePath = '/var/www/data/' + req.body;
// Process the file content (vulnerable code)
const content = processFileContent(filePath);
res.send(content);
} catch (error) {
res.status(500).send('Error processing file content: ' + error.message);
}
});
function processFileContent(filePath) {
// Read the file content
const content = fs.readFileSync(filePath, 'utf-8');
return 'Processed file content:\n' + content;
}
app.listen(port, () => {
console.log(`Server listening at http://localhost:${port}`);
});
<?php
// Save this file as index.php and run it using: php -S localhost:8000
// Get user input from the POST request
$userInput = $_POST['userInput'];
// Vulnerable path traversal without proper input validation
$filePath = '/var/www/data/' . $userInput;
// Process the file content (vulnerable code)
echo processFileContent($filePath);
function processFileContent($filePath) {
try {
// Read the file content
$content = file_get_contents($filePath);
return 'Processed file content:' . PHP_EOL . $content;
} catch (Exception $e) {
return 'Error processing file content: ' . $e->getMessage();
}
}
?>
Recommandation
Afin d'atténuer le risque de traversée de répertoire, tenez compte des recommandations suivantes :
- Éviter la concaténation directe : Évitez de concaténer directement l'entrée utilisateur lors de la construction des chemins du système de fichiers.
- Nettoyage des entrées utilisateur : Nettoyez l'entrée utilisateur avant de l'utiliser dans la construction d'un chemin, les séquences de caractères comme
../doivent être supprimées et le chemin doit être normalisé. - Utiliser des analyseurs de chemin robustes : Utilisez des bibliothèques d'analyse de chemin bien établies et sécurisées, certaines bibliothèques pouvant être intrinsèquement vulnérables à la traversée de répertoire.
- Vérifier le confinement du chemin : Après avoir validé l'entrée fournie, ajoutez-la au répertoire de base et utilisez une API du système de fichiers de la plateforme pour canoniser le chemin. Vérifiez que le chemin canonisé est contenu dans le répertoire de base.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.io.BufferedReader;
import java.io.FileReader;
@SpringBootApplication
public class MitigatedPathTraversalExample {
public static void main(String[] args) {
SpringApplication.run(MitigatedPathTraversalExample.class, args);
}
}
@RestController
class MitigatedFileController {
@PostMapping("/processFile")
public String processFile(@RequestBody String userInput) {
try {
// Mitigated: Validate user input to prevent path traversal
if (!isValidInput(userInput)) {
return "Invalid file path.";
}
// Safe file inclusion with proper input validation
String filePath = "/var/www/data/" + userInput;
// Process the file content
return processFileContent(filePath);
} catch (Exception e) {
return "Error processing file content: " + e.getMessage();
}
}
private boolean isValidInput(String userInput) {
// Mitigated: Implement proper input validation (e.g., regex)
// In a real-world scenario, use a more robust validation mechanism.
return userInput.matches("[a-zA-Z0-9_-]+\\.pdf");
}
private String processFileContent(String filePath) throws Exception {
// Read the file content
BufferedReader br = new BufferedReader(new FileReader(filePath));
StringBuilder content = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
content.append(line).append("\n");
}
br.close();
return "Processed file content:\n" + content.toString();
}
}
const express = require('express');
const bodyParser = require('body-parser');
const fs = require('fs');
const app = express();
const port = 3000;
app.use(bodyParser.text());
app.post('/processFile', (req, res) => {
try {
// Mitigated: Validate user input to prevent path traversal
if (!isValidInput(req.body)) {
res.status(400).send('Invalid file path.');
return;
}
// Safe file inclusion with proper input validation
const filePath = '/var/www/data/' + req.body;
// Process the file content
const content = processFileContent(filePath);
res.send(content);
} catch (error) {
res.status(500).send('Error processing file content: ' + error.message);
}
});
function isValidInput(userInput) {
// Mitigated: Implement proper input validation (e.g., regex)
// In a real-world scenario, use a more robust validation mechanism.
return userInput.match(/^[a-zA-Z0-9_-]+\.pdf$/);
}
function processFileContent(filePath) {
// Read the file content
const content = fs.readFileSync(filePath, 'utf-8');
return 'Processed file content:\n' + content;
}
app.listen(port, () => {
console.log(`Server listening at http://localhost:${port}`);
});
<?php
// Save this file as index.php and run it using: php -S localhost:8000
// Mitigated: Validate user input to prevent path traversal
$userInput = $_POST['userInput'];
if (!isValidInput($userInput)) {
http_response_code(400);
echo 'Invalid file path.';
exit;
}
// Safe file inclusion with proper input validation
$filePath = '/var/www/data/' . $userInput;
// Process the file content
echo processFileContent($filePath);
function isValidInput($userInput) {
// Mitigated: Implement proper input validation (e.g., regex)
// In a real-world scenario, use a more robust validation mechanism.
return preg_match('/^[a-zA-Z0-9_-]+\.pdf$/', $userInput);
}
function processFileContent($filePath) {
try {
// Read the file content
$content = file_get_contents($filePath);
return 'Processed file content:' . PHP_EOL . $content;
} catch (Exception $e) {
return 'Error processing file content: ' . $e->getMessage();
}
}
?>
Liens
Normes
- CWE_TOP_25:
- CWE_22
- GDPR:
- ART_25
- ART_32
- PCI_STANDARDS:
- REQ_6_4
- REQ_6_5
- SOC2_CONTROLS:
- CC_2_1
- CC_4_1
- CC_7_1
- CC_7_2
- CC_7_4
- CC_7_5
- HIPAA_CONTROLS:
- SECURITY212
- SECURITY213
- SECURITY255