Skip to content

Commit 2f38284

Browse files
security:resolve arbitrary table drop and session bypass vulnerabilities
- Implement migration-based whitelist validation in Theme::deleteProcess to prevent arbitrary database table deletion. - Re-activate user account status (active/banned) check in Ci4MsAuthFilter to ensure immediate session revocation for deactivated users.
1 parent adb241b commit 2f38284

9 files changed

Lines changed: 67 additions & 38 deletions

File tree

.gitignore

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -135,31 +135,16 @@ template
135135
app/Config/Routes.php
136136
*.zip
137137
.history
138-
.devilbox
139-
htdocs
140138
public/uploads/.tmb/
141139
public/uploads/.trash/
142140
public/media/.tmb/
143141
writable/tmp/*
144142
bertug_s_docs
145-
modules/Grapes
146-
modules/ActivityLog
147-
modules/Crm
148-
modules/Cronjobs
149-
modules/DocumentManager
150-
modules/EmailManagement
151-
modules/FormBuilder
152-
modules/TaskManager
153-
modules/LicenseServer
154-
modules/LicenseClient
155-
modules/TaskManager
156-
public/be-assets/plugins/grapesjs
157143
.agent
158144
build/
159145
dist/
160146
composer.lock.json
161147
.antigravityignore
162148
.claude
163-
modules/Notifications
164149
tests/*
165150
phpunit.xml.dist

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) conventions adapted to the existing four-component version numbers.
66

7+
## [0.31.8.0] - 2026-04-19
8+
9+
### Fixed
10+
11+
- **Security (Session Management):** Re-activated user account status verification in `Ci4MsAuthFilter`. Deactivated or banned users now have their sessions immediately terminated upon their next request, remediating a session bypass flaw.
12+
- **Security (Arbitrary Table Drop):** Implemented migration-based whitelist validation in `Theme::deleteProcess`. This ensures that selectively dropping database tables during theme deletion is restricted exclusively to tables declared within the specific theme's migration files, preventing arbitrary database table deletion.
13+
714
## [0.31.7.0] - 2026-04-17
815

916
### Added
@@ -286,6 +293,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
286293

287294
- Expanded database migrations and introduced new supporting libraries.
288295

296+
[0.31.8.0]: https://github.com/ci4-cms-erp/ci4ms/releases/tag/0.31.8.0
289297
[0.31.7.0]: https://github.com/ci4-cms-erp/ci4ms/releases/tag/0.31.7.0
290298
[0.31.6.0]: https://github.com/ci4-cms-erp/ci4ms/releases/tag/0.31.6.0
291299
[0.31.5.0]: https://github.com/ci4-cms-erp/ci4ms/releases/tag/0.31.5.0

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,6 @@ A huge thank you to the security researchers who have helped make **ci4ms** more
201201
| **[offset](https://github.com/offset)** | Identified Critical vulnerabilities including multiple Stored XSS, Authorization Bypass in Fileeditor, Install Guard Bypass, and CRLF Injection. | Apr 2026 |
202202
| **[fg0x0](https://github.com/fg0x0)** | Identified Critical Arbitrary File Write (Zip Slip RCE) vulnerabilities in Theme::upload and Backup::restore modules. | Apr 2026 |
203203
| **[0xAlchemist](https://github.com/bugmithlegend)** , **[peeefour](https://github.com/peeefour)** and **[DexterHK](https://github.com/DexterHK)** | Identified Critical Full Account Takeover and Privilege Escalation via Stored DOM Blind XSS in Backup Management (v2). | Apr 2026 |
204-
| **[dapickle](https://github.com/dapickle)** | Identified Critical Authenticated Remote Code Execution (RCE) via unrestricted PHP file upload in Theme installation | Apr 2026 |
204+
| **[dapickle](https://github.com/dapickle)** | Identified Critical Authenticated RCE in Theme installation, Arbitrary Database Table Drop in Theme module, and a Session Management Bypass. | Apr 2026 |
205205

206206
> If you find a security vulnerability, please report it via [Security Policy](SECURITY.md).

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"codeigniter4/translations": "4.7.0",
2424
"ezyang/htmlpurifier": "4.19",
2525
"gregwar/captcha": "1.3.0",
26-
"studio-42/elfinder": "2.1.66"
26+
"studio-42/elfinder": "2.1.67"
2727
},
2828
"require-dev": {
2929
"fakerphp/faker": "^1.9",

composer.lock

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

modules/Auth/Filters/Ci4MsAuthFilter.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ public function before(RequestInterface $request, $arguments = null)
1313
if (! auth()->loggedIn()) {
1414
return redirect()->route('login');
1515
}
16-
/* $user = auth()->user();
17-
if ($user && ($user->isBanned() || !$user->active)) {
18-
auth('session')->logout();
16+
$user = auth()->user();
1917

18+
if ($user && ($user->isBanned() || (isset($user->active) && (int)$user->active === 0))) {
19+
auth('session')->logout();
2020
return redirect()->route('login')->with('error', lang('Auth.bannedUser'));
21-
} */
21+
}
2222

2323
$router = service('router');
2424
$controllerName = $router->controllerName();

modules/Backend/Commands/Ci4msSetup.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ public function run(array $params)
218218
'app.supportedLocales' => '["ar","de","en","es","fr","hi","ja","pt","ru","tr","zh"]',
219219
'app.negotiateLocale' => 'true',
220220
'app.appTimezone' => '\'Europe/Istanbul\'',
221-
'app.version' => '0.31.7.0',
221+
'app.version' => '0.31.8.0',
222222
];
223223

224224
if (!$this->updateEnvSettings($updates)) {

modules/Install/Controllers/Install.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public function index()
6666
'app.supportedLocales' => '["ar","de","en","es","fr","hi","ja","pt","ru","tr","zh"]',
6767
'app.negotiateLocale' => 'true',
6868
'app.appTimezone' => '\'Europe/Istanbul\'',
69-
'app.version' => '0.31.7.0'
69+
'app.version' => '0.31.8.0'
7070
];
7171
if ($this->copyEnvFile() && $this->updateEnvSettings($updates)) $this->generateEncryptionKey();
7272

modules/Theme/Controllers/Theme.php

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,32 @@ public function upload()
2424
// Allowed static file extensions for the public/ directory.
2525
// PHP files MUST NOT be written under public/ (RCE prevention).
2626
$allowedPublicExtensions = [
27-
'css', 'js', 'map',
28-
'png', 'jpg', 'jpeg', 'gif', 'svg', 'webp', 'ico', 'bmp', 'avif',
29-
'woff', 'woff2', 'ttf', 'eot', 'otf',
30-
'xml', 'json', 'txt', 'md',
31-
'mp4', 'webm', 'ogg', 'mp3', 'wav',
27+
'css',
28+
'js',
29+
'map',
30+
'png',
31+
'jpg',
32+
'jpeg',
33+
'gif',
34+
'svg',
35+
'webp',
36+
'ico',
37+
'bmp',
38+
'avif',
39+
'woff',
40+
'woff2',
41+
'ttf',
42+
'eot',
43+
'otf',
44+
'xml',
45+
'json',
46+
'txt',
47+
'md',
48+
'mp4',
49+
'webm',
50+
'ogg',
51+
'mp3',
52+
'wav',
3253
'pdf',
3354
];
3455

@@ -142,16 +163,31 @@ public function deleteProcess(string $slug)
142163
return redirect()->route('templateSettings')->with('errors', [lang('Theme.themeActiveCannotDelete')]);
143164
}
144165

166+
$allowedTables = [];
167+
$migrationPath = APPPATH . 'Database/Migrations/templates/' . $themeName;
168+
if (is_dir($migrationPath)) {
169+
$files = glob($migrationPath . '/*.php');
170+
foreach ($files as $file) {
171+
$content = file_get_contents($file);
172+
preg_match_all("/\\\$this->forge->createTable\s*\(\s*['\"]([^'\"]+)['\"]/i", $content, $matches);
173+
if (!empty($matches[1])) {
174+
foreach ($matches[1] as $tName) {
175+
$allowedTables[] = $tName;
176+
}
177+
}
178+
}
179+
}
180+
$allowedTables = array_unique($allowedTables);
145181
$log = [];
146-
// Delete tables (selected ones)
147182
$tablesToDrop = $this->request->getPost('tables');
148183
if (!empty($tablesToDrop) && is_array($tablesToDrop)) {
149184
$forge = \Config\Database::forge();
150185
$db = \Config\Database::connect();
151186
foreach ($tablesToDrop as $table) {
152-
if ($db->tableExists($table)) {
187+
// Sadece izin verilen (temaya ait) tabloları sil
188+
if (in_array($table, $allowedTables) && $db->tableExists($table)) {
153189
$forge->dropTable($table, true);
154-
$log[] = "🗑️ Table deleted: $table";
190+
$log[] = "🗑️ " . lang('Theme.tableDeleted', [$table]);
155191
}
156192
}
157193
}

0 commit comments

Comments
 (0)