Skip to content

Commit 5d35586

Browse files
fix(uploader): resolve realpath bypass and hardcoded file input vulnerabilities
Co-authored-by: Maatify <130119162+Maatify@users.noreply.github.com>
1 parent 512a914 commit 5d35586

1 file changed

Lines changed: 24 additions & 14 deletions

File tree

uploader/UploadBase.php

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ abstract class UploadBase extends MimeValidate
2424

2525
protected ?StorageAdapterInterface $storageAdapter = null;
2626
protected bool $skipStoragePush = false;
27+
protected string $file_input_name = 'file';
28+
29+
public function setFileInputName(string $name): self
30+
{
31+
$this->file_input_name = $name;
32+
return $this;
33+
}
2734

2835
public function setStorageAdapter(StorageAdapterInterface $adapter): static
2936
{
@@ -130,17 +137,17 @@ abstract protected function validateMime(string $mime): string;
130137
*/
131138
public function upload(): array
132139
{
133-
if (empty($_FILES["file"]) || !is_array($_FILES["file"]) || empty($_FILES["file"]["tmp_name"])) {
140+
if (empty($_FILES[$this->file_input_name]) || !is_array($_FILES[$this->file_input_name]) || empty($_FILES[$this->file_input_name]["tmp_name"])) {
134141
return $this->returnError('Missing file post.');
135142
}
136143

137144
// Check for any upload errors
138-
if ($_FILES["file"]["error"] !== UPLOAD_ERR_OK) {
139-
return $this->returnError('File upload error: ' . $_FILES["file"]["error"]);
145+
if ($_FILES[$this->file_input_name]["error"] !== UPLOAD_ERR_OK) {
146+
return $this->returnError('File upload error: ' . $_FILES[$this->file_input_name]["error"]);
140147
}
141148

142149
// Get the MIME type of the uploaded file
143-
$mime = mime_content_type((string)$_FILES["file"]["tmp_name"]);
150+
$mime = mime_content_type((string)$_FILES[$this->file_input_name]["tmp_name"]);
144151
if ($mime === false) {
145152
return $this->returnError('Could not determine mime type.');
146153
}
@@ -161,9 +168,17 @@ public function upload(): array
161168
// Sanitize the filename using basename and preg_replace for security
162169
$file = preg_replace('/[^a-zA-Z0-9_\-\.]/', '', basename($file));
163170

171+
// Create the upload folder if it doesn't exist
172+
if (!$this->createUploadFolder()) {
173+
return $this->returnError('Failed to create upload folder.');
174+
}
175+
164176
// Set the target path for the file upload
165-
// Set the target path for the file upload
166-
$basePath = (string)realpath($this->upload_folder);
177+
$basePath = realpath($this->upload_folder);
178+
if ($basePath === false) {
179+
return $this->returnError('Invalid file path.');
180+
}
181+
$basePath = (string)$basePath;
167182
$target_path = $basePath . '/' . $file;
168183

169184
if (! str_starts_with($target_path, $basePath)) {
@@ -173,23 +188,18 @@ public function upload(): array
173188
$this->file_target = $target_path;
174189

175190
// Check the file size against the maximum allowed size (if defined)
176-
if (!empty($this->max_size) && $_FILES["file"]["size"] > $this->max_size) {
191+
if (!empty($this->max_size) && $_FILES[$this->file_input_name]["size"] > $this->max_size) {
177192
return $this->returnError("Your file is too large, cannot be more than " . ($this->max_size / self::MB) . " MB.");
178193
}
179194

180-
// Create the upload folder if it doesn't exist
181-
if (!$this->createUploadFolder()) {
182-
return $this->returnError('Failed to create upload folder.');
183-
}
184-
185195
// Move the uploaded file to the target directory and verify success
186196
if (defined('PHPUNIT_TEST') || getenv('PHPUNIT_TEST') === '1') {
187-
if (copy($_FILES["file"]["tmp_name"], $this->file_target)) {
197+
if (copy($_FILES[$this->file_input_name]["tmp_name"], $this->file_target)) {
188198
$this->pushToStorage($this->file_target, (string)$file);
189199
return $this->returnSuccess((string)$file);
190200
}
191201
} else {
192-
if (move_uploaded_file($_FILES["file"]["tmp_name"], $this->file_target)) {
202+
if (move_uploaded_file($_FILES[$this->file_input_name]["tmp_name"], $this->file_target)) {
193203
$this->pushToStorage($this->file_target, (string)$file);
194204
return $this->returnSuccess((string)$file);
195205
}

0 commit comments

Comments
 (0)