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 protection
Impact
An authenticated user can:
- Download arbitrary files readable by the web server (e.g.,
.env with 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.
Summary
The system log download and clear endpoints are vulnerable to path traversal via unsanitized
filenameparameter. ThegetFilePath()method inSystemLogs.phpconcatenates the base log path with user-supplied filename without sanitizing directory traversal sequences.Affected Code
File:
src/Support/SystemLogs.php-getFilePath(string $name)Validation in
DownloadSystemLog.phpandClearSystemLog.php:Impact
An authenticated user can:
.envwith database credentials, APP_KEY)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 usesglob('*.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:Or add a regex validation rule:
'regex:/^[a-zA-Z0-9.\-_]+$/'Additional Note
A secondary issue exists in
MediaDownloadExternal.phpwhereisPublicDomainUrl()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.