Skip to content

Commit caa3a76

Browse files
committed
fix: added missing CSRF check
1 parent efa24c4 commit caa3a76

3 files changed

Lines changed: 24 additions & 5 deletions

File tree

phpmyfaq/admin/assets/src/content/editor.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,9 @@ export const renderEditor = () => {
266266
ajax: {
267267
url: './api/media-browser',
268268
contentType: 'application/json; charset=UTF-8',
269+
data: {
270+
csrfToken: (document.getElementById('pmf-csrf-token') as HTMLInputElement).value,
271+
},
269272
},
270273
createNewFolder: false,
271274
deleteFolder: false,

phpmyfaq/src/phpMyFAQ/Controller/Administration/Api/MediaBrowserController.php

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use phpMyFAQ\Core\Exception;
2525
use phpMyFAQ\Enums\PermissionType;
2626
use phpMyFAQ\Filter;
27+
use phpMyFAQ\Session\Token;
2728
use phpMyFAQ\Translation;
2829
use phpMyFAQ\Utils;
2930
use RecursiveDirectoryIterator;
@@ -58,11 +59,23 @@ public function index(Request $request): JsonResponse|Response
5859
$action = Filter::filterVar($data->action, FILTER_SANITIZE_SPECIAL_CHARS);
5960

6061
if ($action === 'fileRemove') {
61-
$file = Filter::filterVar($data->name, FILTER_SANITIZE_SPECIAL_CHARS);
62-
$file = PMF_CONTENT_DIR . '/user/images/' . $file;
62+
if (!Token::getInstance($this->container->get(id: 'session'))->verifyToken(
63+
'media-browser',
64+
$data->csrfToken,
65+
)) {
66+
return $this->json(['error' => Translation::get(key: 'msgNoPermission')], Response::HTTP_UNAUTHORIZED);
67+
}
68+
69+
$file = basename(Filter::filterVar($data->name, FILTER_SANITIZE_SPECIAL_CHARS));
70+
$allowedDir = realpath(PMF_CONTENT_DIR . '/user/images');
71+
$targetPath = realpath(PMF_CONTENT_DIR . '/user/images/' . $file);
72+
73+
if ($targetPath === false || !str_starts_with($targetPath, $allowedDir . DIRECTORY_SEPARATOR)) {
74+
return $this->json(['error' => 'Invalid file path'], Response::HTTP_BAD_REQUEST);
75+
}
6376

64-
if (file_exists($file)) {
65-
unlink($file);
77+
if (file_exists($targetPath)) {
78+
unlink($targetPath);
6679
}
6780

6881
$response = [

tests/phpMyFAQ/Search/SearchDatabaseTest.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,10 @@ public function testSetAndGetConditionsWithoutConditions()
148148
public function testGetMatchClause()
149149
{
150150
$this->searchDatabase->setMatchingColumns(['faqdata.author']);
151-
$this->assertEquals(" (faqdata.author LIKE '%Thorsten%' ESCAPE '\\')", $this->searchDatabase->getMatchClause('Thorsten'));
151+
$this->assertEquals(
152+
" (faqdata.author LIKE '%Thorsten%' ESCAPE '\\')",
153+
$this->searchDatabase->getMatchClause('Thorsten'),
154+
);
152155
$this->assertIsString($this->searchDatabase->getMatchClause('Thorsten'));
153156
}
154157

0 commit comments

Comments
 (0)