Skip to content

Commit f8a3fc5

Browse files
claudebcordis
authored andcommitted
Fix security vulnerabilities: XSS, open redirect, path traversal, IDOR
- Fix reflected XSS in admin cpanel by escaping user-supplied msg parameter - Fix stored XSS in comment text output with htmlspecialchars() - Fix XSS in JavaScript context in podcast template using json_encode() - Fix open redirect in CwmsermonsController, CwmmediafileController, and CwmadminController by validating base64-decoded return URLs with Uri::isInternal() - Fix path traversal in backup restore by sanitizing upload filename with File::makeSafe() and basename() - Fix IDOR in download helper by checking published status and user access levels before serving media files - Sanitize Content-Disposition filename header to prevent header injection - Escape user-supplied handler name in error messages https://claude.ai/code/session_01Eq9nzEFGHytEtgTiUgTEHt
1 parent 743faa5 commit f8a3fc5

File tree

8 files changed

+53
-24
lines changed

8 files changed

+53
-24
lines changed

admin/src/Controller/CwmadminController.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121
use CWM\Component\Proclaim\Administrator\Helper\Cwmalias;
2222
use CWM\Component\Proclaim\Administrator\Helper\CwmcsvimportHelper;
2323
use CWM\Component\Proclaim\Administrator\Helper\CwmdbHelper;
24-
use CWM\Component\Proclaim\Administrator\Helper\CwmschemaorgHelper;
2524
use CWM\Component\Proclaim\Administrator\Helper\CwmdescriptionHelper;
2625
use CWM\Component\Proclaim\Administrator\Helper\CwmImageCleanup;
2726
use CWM\Component\Proclaim\Administrator\Helper\CwmImageMigration;
2827
use CWM\Component\Proclaim\Administrator\Helper\Cwmparams;
28+
use CWM\Component\Proclaim\Administrator\Helper\CwmschemaorgHelper;
2929
use CWM\Component\Proclaim\Administrator\Helper\CwmserverMigrationHelper;
3030
use CWM\Component\Proclaim\Administrator\Helper\Cwmthumbnail;
3131
use CWM\Component\Proclaim\Administrator\Helper\CwmupgradeHelper;
@@ -42,6 +42,7 @@
4242
use Joomla\CMS\MVC\Controller\FormController;
4343
use Joomla\CMS\Router\Route;
4444
use Joomla\CMS\Session\Session;
45+
use Joomla\CMS\Uri\Uri;
4546
use Joomla\Database\DatabaseInterface;
4647
use Joomla\Filesystem\Folder;
4748
use Joomla\Registry\Registry;
@@ -2153,10 +2154,10 @@ public function schemaSyncXHR(): void
21532154
}
21542155

21552156
echo json_encode([
2156-
'success' => true,
2157-
'count' => $total,
2158-
'counts' => $counts,
2159-
'message' => $message,
2157+
'success' => true,
2158+
'count' => $total,
2159+
'counts' => $counts,
2160+
'message' => $message,
21602161
], JSON_THROW_ON_ERROR);
21612162
} catch (\Exception $e) {
21622163
echo json_encode([
@@ -2194,7 +2195,8 @@ public function schemaForceRefresh(): void
21942195
}
21952196
}
21962197

2197-
$redirect = $return ? base64_decode($return) : 'index.php?option=com_proclaim';
2198+
$decoded = $return ? base64_decode($return) : '';
2199+
$redirect = ($decoded && Uri::isInternal($decoded)) ? $decoded : 'index.php?option=com_proclaim';
21982200
$app->redirect($redirect);
21992201
}
22002202

admin/src/Controller/CwmmediafileController.php

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ public function xhr(): void
162162
$app = Factory::getApplication();
163163
$app->close();
164164
} else {
165-
throw new \RuntimeException(Text::sprintf('Handler: "' . $handler . '" does not exist!'), 404);
165+
throw new \RuntimeException(Text::sprintf('Handler: "%s" does not exist!', htmlspecialchars($handler, ENT_QUOTES, 'UTF-8')), 404);
166166
}
167167
}
168168

@@ -244,8 +244,14 @@ public function cancel($key = null): bool
244244
}
245245
}
246246

247-
if ($this->input->getCmd('return') && parent::cancel($key)) {
248-
$this->setRedirect(base64_decode($this->input->getCmd('return')));
247+
$return = $this->input->getCmd('return');
248+
249+
if ($return && parent::cancel($key)) {
250+
$decoded = base64_decode($return);
251+
252+
if ($decoded && Uri::isInternal($decoded)) {
253+
$this->setRedirect($decoded);
254+
}
249255

250256
return true;
251257
}
@@ -532,8 +538,12 @@ protected function postSaveHook($model, $validData = []): void
532538
$task = $this->input->get('task');
533539

534540
if ($return && $task !== 'apply') {
535-
Factory::getApplication()->enqueueMessage(Text::_('JBS_MED_SAVE'), 'message');
536-
$this->setRedirect(base64_decode($return));
541+
$decoded = base64_decode($return);
542+
543+
if ($decoded && Uri::isInternal($decoded)) {
544+
Factory::getApplication()->enqueueMessage(Text::_('JBS_MED_SAVE'), 'message');
545+
$this->setRedirect($decoded);
546+
}
537547
}
538548
}
539549

admin/src/Lib/Cwmrestore.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,8 @@ public function getPackageFromUpload(): bool|array
477477

478478
// Build the appropriate paths
479479
$config = Factory::getApplication()->getConfig();
480-
$tmp_dest = $config->get('tmp_path') . '/' . $userFile['name'];
480+
$safeName = File::makeSafe($userFile['name']);
481+
$tmp_dest = $config->get('tmp_path') . '/' . basename($safeName);
481482
$tmp_src = $userFile['tmp_name'];
482483

483484
// Move an uploaded file.

admin/tmpl/cwmcpanel/default.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@
3838

3939
$msg = '';
4040
$input = Factory::getApplication()->getInput();
41-
$msg = $input->get('msg');
41+
$msg = $input->getString('msg', '');
4242

4343
if ($msg) {
44-
echo $msg;
44+
echo htmlspecialchars($msg, ENT_QUOTES, 'UTF-8');
4545
}
4646

4747
$simple = Cwmhelper::getSimpleView();

site/src/Controller/CwmsermonsController.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use CWM\Component\Proclaim\Site\Model\CwmsermonsModel;
1919
use Joomla\CMS\Factory;
2020
use Joomla\CMS\MVC\Controller\BaseController;
21+
use Joomla\CMS\Uri\Uri;
2122

2223
// phpcs:disable PSR1.Files.SideEffects
2324
\defined('_JEXEC') or die;
@@ -66,9 +67,14 @@ public function playHit(): void
6667
CwmanalyticsHelper::logEvent('play', 0, $id);
6768

6869
// Now the hit has been updated will redirect to the url.
69-
$return = $app->getInput()->get('return');
70-
$return = base64_decode($return);
71-
$app->redirect($return);
70+
$return = $app->getInput()->getBase64('return', '');
71+
$return = $return ? base64_decode($return) : '';
72+
73+
if ($return && Uri::isInternal($return)) {
74+
$app->redirect($return);
75+
} else {
76+
$app->redirect('index.php');
77+
}
7278
}
7379

7480
/**

site/src/Helper/Cwmdownload.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ public function download(int $mid): void
7777
$db->quoteName('#__bsms_servers') . ' ON ('
7878
. $db->quoteName('#__bsms_servers.id') . ' = ' . $db->quoteName('#__bsms_mediafiles.server_id') . ')'
7979
)
80-
->where($db->quoteName('#__bsms_mediafiles.id') . ' = ' . $mid);
80+
->where($db->quoteName('#__bsms_mediafiles.id') . ' = ' . $mid)
81+
->where($db->quoteName('#__bsms_mediafiles.published') . ' = 1');
8182
$db->setQuery($query, 0, 1);
8283

8384
$media = $db->loadObject();
@@ -86,6 +87,14 @@ public function download(int $mid): void
8687
$this->sendError($app, 404, 'Media not found');
8788
}
8889

90+
// Verify the current user has the required access level
91+
$user = $app->getIdentity();
92+
$accessLevels = $user->getAuthorisedViewLevels();
93+
94+
if (isset($media->access) && !\in_array((int) $media->access, $accessLevels, true)) {
95+
$this->sendError($app, 403, 'Access denied');
96+
}
97+
8998
// Increment download count after validation
9099
$this->hitDownloads($mid);
91100

@@ -145,7 +154,8 @@ public function download(int $mid): void
145154

146155
header('Content-Description: File Transfer');
147156
header('Content-Type: application/octet-stream');
148-
header('Content-Disposition: attachment; filename="' . basename($params->get('filename')) . '"');
157+
$safeFilename = preg_replace('/[^\w.\-]/', '_', basename($params->get('filename')));
158+
header('Content-Disposition: attachment; filename="' . $safeFilename . '"');
149159
header('Expires: 0');
150160
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
151161
header('Cache-Control: private', false);

site/tmpl/cwmseriespodcastdisplay/default.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,16 +88,16 @@
8888
); ?>
8989
<td>
9090
<?php
91-
echo stripslashes($item->studytitle); ?>
91+
echo htmlspecialchars(stripslashes($item->studytitle), ENT_QUOTES, 'UTF-8'); ?>
9292
</td>
9393
<td>
9494
<?php
9595
echo HTMLHelper::Date($item->createdate); ?>
9696
</td>
9797
<td>
98-
<a href="javascript:loadVideo('<?php
99-
echo $path1; ?>', '<?php
100-
echo $item->series_thumbnail; ?>')">
98+
<a href="javascript:loadVideo(<?php
99+
echo htmlspecialchars(json_encode($path1), ENT_QUOTES, 'UTF-8'); ?>, <?php
100+
echo htmlspecialchars(json_encode($item->series_thumbnail), ENT_QUOTES, 'UTF-8'); ?>)">
101101
<?php
102102
echo Text::_('JBS_CMN_LISTEN'); ?>
103103
</a>

site/tmpl/cwmsermon/default_commentsform.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class="btn btn-outline-secondary heading<?php echo $pageclassSfx; ?>"
8383
</span>
8484
</div>
8585
<div class="comment-text">
86-
<?php echo $comment->comment_text; ?>
86+
<?php echo htmlspecialchars($comment->comment_text, ENT_QUOTES, 'UTF-8'); ?>
8787
</div>
8888
</div>
8989
<?php endforeach; ?>

0 commit comments

Comments
 (0)