-
Notifications
You must be signed in to change notification settings - Fork 446
Description
Summary
The system log download and clear endpoints are vulnerable to path traversal via unsanitized filename parameter. The getFilePath() method in SystemLogs.php concatenates the base log path with user-supplied filename without sanitizing directory traversal sequences.
Affected Code
File: src/Support/SystemLogs.php - getFilePath(string $name)
public function getFilePath(string $name): string
{
return $this->basePathForLogs() . $name; // No sanitization
}Validation in DownloadSystemLog.php and ClearSystemLog.php:
'filename' => ['required', 'string', 'max:255'] // Missing path traversal protectionImpact
An authenticated user can:
- Download arbitrary files readable by the web server (e.g.,
.envwith database credentials, APP_KEY) - Clear/truncate arbitrary files writable by the web server via
fopen($filePath, 'w+')
The APP_KEY leak can lead to RCE via Laravel's encrypted cookie deserialization.
Secure Comparison
The logs() method in the same class correctly uses glob('*.log') + realpath() to enumerate only actual log files. The download/clear endpoints should validate against this enumerated list.
Suggested Fix
Apply basename() to strip directory components, and validate the resolved path is within the logs directory:
public function getFilePath(string $name): string
{
$safeName = basename($name);
$filePath = $this->basePathForLogs() . $safeName;
$realPath = realpath($filePath);
$baseReal = realpath($this->basePathForLogs());
if ($realPath === false || !str_starts_with($realPath, $baseReal)) {
throw new \InvalidArgumentException('Invalid filename');
}
return $realPath;
}Or add a regex validation rule: 'regex:/^[a-zA-Z0-9.\-_]+$/'
Additional Note
A secondary issue exists in MediaDownloadExternal.php where isPublicDomainUrl() validates URLs by checking if the host is a raw IP but does not resolve DNS to check for private IP ranges, allowing DNS rebinding SSRF.