Skip to content

Commit d961426

Browse files
authored
Merge pull request #2 from iranpsc/security-bugfixes
chore: update PHP and Laravel dependencies, enhance file upload secur…
2 parents d7ec2b5 + d530d1e commit d961426

15 files changed

Lines changed: 2312 additions & 1544 deletions

File tree

app/Http/Controllers/FileUploadController.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
use Pion\Laravel\ChunkUpload\Exceptions\UploadMissingFileException;
88
use Pion\Laravel\ChunkUpload\Handler\HandlerFactory;
99
use Illuminate\Http\UploadedFile;
10+
use Illuminate\Support\Facades\Validator;
11+
use App\Rules\SecureFile;
1012

1113
class FileUploadController extends Controller
1214
{
@@ -58,6 +60,16 @@ public function upload(Request $request)
5860
*/
5961
protected function saveFile(UploadedFile $file)
6062
{
63+
$allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'zip', 'rar', 'pdf', 'doc', 'docx', 'fbx', 'obj', 'blend', 'stl', 'gltf', 'glb'];
64+
65+
$validator = Validator::make(['file' => $file], [
66+
'file' => ['required', 'file', new SecureFile($allowedExtensions)],
67+
]);
68+
69+
if ($validator->fails()) {
70+
abort(422, $validator->errors()->first());
71+
}
72+
6173
$fileName = $this->createFilename($file);
6274
$fileSize = $this->formatSizeUnits($file->getSize());
6375
// Group files by mime type
@@ -88,7 +100,8 @@ protected function saveFile(UploadedFile $file)
88100
protected function createFilename(UploadedFile $file)
89101
{
90102
$extension = $file->getClientOriginalExtension();
91-
$filename = str_replace("." . $extension, "", $file->getClientOriginalName()); // Filename without extension
103+
$originalName = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
104+
$filename = \Illuminate\Support\Str::slug($originalName);
92105

93106
// Add timestamp hash to name of the file
94107
$filename .= "_" . md5(time()) . "." . $extension;

app/Http/Middleware/Admin.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class Admin
1616
public function handle(Request $request, Closure $next): Response
1717
{
1818
if (! $request->user()->hasRole('admin')) {
19-
abort(404);
19+
return redirect()->back()->with('error', 'شما اجازه دسترسی به این صفحه را ندارید.');
2020
}
2121

2222
return $next($request);

app/Imports/ProductImport.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,12 @@ private function createImages(\App\Models\Product $product, array $images): void
200200
*/
201201
private function createFile(\App\Models\Product $product, string $filePath): void
202202
{
203+
// Security check: prevent path traversal
204+
if (strpos($filePath, '..') !== false) {
205+
Log::warning("Skipping file creation for product {$product->id} due to invalid path: {$filePath}");
206+
return;
207+
}
208+
203209
$product->file()->updateOrCreate(
204210
['product_id' => $product->id],
205211
['path' => $filePath]

app/Livewire/Forms/CreateProductForm.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,21 @@ public function save()
106106
mkdir(storage_path('app/' . $uploadPath), 0777, true);
107107
}
108108

109+
// Security check for file path traversal
110+
$inputPath = $this->fbx_file['path'] . $this->fbx_file['name'];
111+
if (strpos($inputPath, '..') !== false || strpos($this->fbx_file['path'], 'upload/') !== 0) {
112+
$this->addError('fbx_file', 'Invalid file path.');
113+
return;
114+
}
115+
109116
$originalPath = storage_path('app/' . $this->fbx_file['path'] . $this->fbx_file['name']);
117+
118+
// Verify the file exists and is inside the upload directory
119+
if (!file_exists($originalPath) || !str_starts_with(realpath($originalPath), storage_path('app/upload'))) {
120+
$this->addError('fbx_file', 'File not found or invalid path.');
121+
return;
122+
}
123+
110124
$newPath = storage_path('app/' . $uploadPath . '/' . $this->fbx_file['name']);
111125

112126
rename($originalPath, $newPath);

app/Livewire/Forms/UpdateProduct.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,21 @@ public function update()
148148
mkdir(storage_path('app/' . $uploadPath), 0777, true);
149149
}
150150

151+
// Security check for file path traversal
152+
$inputPath = $this->fbx_file['path'] . $this->fbx_file['name'];
153+
if (strpos($inputPath, '..') !== false || strpos($this->fbx_file['path'], 'upload/') !== 0) {
154+
$this->addError('fbx_file', 'Invalid file path.');
155+
return;
156+
}
157+
151158
$originalPath = storage_path('app/' . $this->fbx_file['path'] . $this->fbx_file['name']);
159+
160+
// Verify the file exists and is inside the upload directory
161+
if (!file_exists($originalPath) || !str_starts_with(realpath($originalPath), storage_path('app/upload'))) {
162+
$this->addError('fbx_file', 'File not found or invalid path.');
163+
return;
164+
}
165+
152166
$newPath = storage_path('app/' . $uploadPath . '/' . $this->fbx_file['name']);
153167

154168
// Move the file to the new path

app/Livewire/Support/CreateTicket.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@ class CreateTicket extends Component
1616
public $attachment;
1717
public $priority = 'medium';
1818

19-
protected $rules = [
20-
'title' => 'required|string|min:3|max:255',
21-
'message' => 'required|string|min:3|max:5000',
22-
'attachment' => 'nullable|file|mimes:pdf,jpg,jpeg,png|max:1024',
23-
'priority' => 'required|in:low,medium,high'
24-
];
19+
public function rules()
20+
{
21+
return [
22+
'title' => 'required|string|min:3|max:255',
23+
'message' => 'required|string|min:3|max:5000',
24+
'attachment' => ['nullable', 'file', 'max:1024', new \App\Rules\SecureFile(['pdf', 'jpg', 'jpeg', 'png'])],
25+
'priority' => 'required|in:low,medium,high'
26+
];
27+
}
2528

2629
public function createTicket()
2730
{

app/Models/Category.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public function getBreadcrumbAttribute()
4949
{
5050
$this->loadMissing('parent');
5151

52-
$url = '<a href="' . url('categories/' . $this->url) . '">' . $this->name . '</a>';
52+
$url = '<a href="' . url('categories/' . $this->url) . '">' . e($this->name) . '</a>';
5353

5454
return $this->parent ? $this->parent->breadcrumb . ' / ' . $url : $url;
5555
}

app/Models/Order.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ class Order extends Model
1010
{
1111
use HasFactory, HasUuids;
1212

13-
protected $guarded = [];
13+
protected $fillable = [
14+
'user_id',
15+
'amount',
16+
'status',
17+
'tracking_id',
18+
];
1419

1520
/**
1621
* The data type of the primary key ID.

app/Models/OrderItem.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ class OrderItem extends Model
99
{
1010
use HasFactory;
1111

12-
protected $guarded = [];
12+
protected $fillable = [
13+
'order_id',
14+
'product_id',
15+
'quantity',
16+
];
1317

1418
public $timestamps = false;
1519

app/Models/Transaction.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,18 @@ class Transaction extends Model
99
{
1010
use HasFactory;
1111

12-
protected $guarded = [];
12+
protected $fillable = [
13+
'order_id',
14+
'authority',
15+
'amount',
16+
'currency',
17+
'status',
18+
'card_hash',
19+
'card_pan',
20+
'fee_type',
21+
'fee',
22+
'reference_id',
23+
];
1324

1425
/**
1526
* Casts properties

0 commit comments

Comments
 (0)