mirror of
https://github.com/myronblair/parkerslingshotrentals
synced 2026-06-30 09:40:14 -05:00
Security: block direct upload access, fix view-doc path traversal guard
- uploads/.htaccess: deny all direct web access to uploaded customer docs - admin/view-doc.php: add realpath() path-traversal check (mirrors view-doc.php) - admin/view-doc.php: remove dead double-query (result was always overwritten) - .gitignore: uploads/* wildcard so .htaccess can be tracked
This commit is contained in:
+2
-1
@@ -2,4 +2,5 @@
|
||||
.DS_Store
|
||||
*.swp
|
||||
|
||||
uploads/
|
||||
uploads/*
|
||||
!uploads/.htaccess
|
||||
|
||||
+15
-6
@@ -19,7 +19,6 @@ if (!$ref || !$type) {
|
||||
}
|
||||
|
||||
$col = $type === 'license' ? 'license_file' : 'insurance_file';
|
||||
$row = db()->prepare("SELECT {$col} AS file_path FROM bookings WHERE booking_ref=?")->execute([$ref]) ? null : null;
|
||||
$stmt = db()->prepare("SELECT {$col} AS file_path FROM bookings WHERE booking_ref=?");
|
||||
$stmt->execute([$ref]);
|
||||
$row = $stmt->fetch();
|
||||
@@ -30,17 +29,27 @@ if (!$row || !$row['file_path']) {
|
||||
exit('No document on file.');
|
||||
}
|
||||
|
||||
// Path stored as uploads/{ref}/{filename}
|
||||
$path = __DIR__ . '/../' . ltrim($row['file_path'], '/');
|
||||
if (!file_exists($path)) {
|
||||
$base = realpath(dirname(__DIR__) . '/uploads');
|
||||
$path = realpath(dirname(__DIR__) . '/' . $row['file_path']);
|
||||
|
||||
if (!$path || !$base || strpos($path, $base . DIRECTORY_SEPARATOR) !== 0) {
|
||||
http_response_code(404);
|
||||
header('Content-Type: text/plain');
|
||||
exit('File not found.');
|
||||
}
|
||||
|
||||
$mime = mime_content_type($path) ?: 'application/octet-stream';
|
||||
$finfo = new finfo(FILEINFO_MIME_TYPE);
|
||||
$mime = $finfo->file($path);
|
||||
$allowed = ['image/jpeg' => 'jpg', 'image/png' => 'png', 'application/pdf' => 'pdf'];
|
||||
if (!isset($allowed[$mime])) {
|
||||
http_response_code(403);
|
||||
header('Content-Type: text/plain');
|
||||
exit('Invalid file type.');
|
||||
}
|
||||
|
||||
$fname = $type . '-' . $ref . '.' . $allowed[$mime];
|
||||
header('Content-Type: ' . $mime);
|
||||
header('Content-Disposition: inline; filename="' . basename($path) . '"');
|
||||
header('Content-Disposition: inline; filename="' . $fname . '"');
|
||||
header('Content-Length: ' . filesize($path));
|
||||
header('Cache-Control: no-store, no-cache');
|
||||
readfile($path);
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# Block direct web access — documents served only through admin/view-doc.php
|
||||
<IfModule mod_authz_core.c>
|
||||
Require all denied
|
||||
</IfModule>
|
||||
<IfModule !mod_authz_core.c>
|
||||
Order deny,allow
|
||||
Deny from all
|
||||
</IfModule>
|
||||
Reference in New Issue
Block a user