Skip to content

Security: Privilege Escalation via Group Self-Assignment + AJAX Data Endpoints Bypass Permission Checks (10 Findings) #65

@lighthousekeeper1212

Description

@lighthousekeeper1212

Summary

InventorySystem uses an opt-in permission model where controllers must explicitly check permissions. Several AJAX data-fetching endpoints skip these checks, and the user settings form allows group self-assignment for privilege escalation.

Critical Finding

1. Privilege Escalation via Group Self-Assignment in Settings

File: application/controllers/Users.php:270-288

The setting() method passes $this->input->post('groups') directly to model_users->edit():

$update = $this->model_users->edit($data, $id, $this->input->post('groups'));

Any authenticated user who changes their password can simultaneously change their group to Administrator (group_id=1) by including a groups field in the POST request.

Impact: Any user with updateSetting permission can escalate to full Administrator.

High Findings

2. Attribute Value Operations Missing Permission Checks

File: application/controllers/Attributes.php:251-358
createValue(), updateValue(), removeValue() have zero permission checks. Parent attribute CRUD has checks — classic 1-of-N.

3. 6 AJAX Data Endpoints Bypass Permission Checks

Files: Products.php:38, Orders.php:37, Brands.php:38, Category.php:51, Stores.php:47, Attributes.php:44

fetchProductData, fetchOrdersData, etc. return full datasets via AJAX without permission checks. The index() methods that render views DO check permissions, but the underlying data endpoints are directly accessible.

Impact: Any authenticated user can dump all products (prices, SKUs), orders (customer PII — names, addresses, phone numbers), and configuration data regardless of their group permissions.

4. Stored XSS in Order Invoice Print

File: application/controllers/Orders.php:249-391
printDiv() constructs HTML by concatenating database values without HTML encoding. customer_name, customer_address, etc. are echoed unescaped. Users with createOrder can inject XSS that executes when admins view invoices.

Medium Findings

  1. 8 individual record fetch endpoints missing permission checks (fetchBrandDataById, etc.)
  2. Hardcoded encryption key (config.php:327) — Go87NSzqqq96Dq2jcjnvhVUCpKPeP2ea in public repo
  3. CSRF protection disabled (config.php:451) — csrf_protection = FALSE
  4. PHP object injection (MY_Controller.php:29-30) — unserialize($group_data['permission']) on every request

Low Findings

  1. Reports controller missing not_logged_in() — inconsistency, not directly exploitable
  2. Session save path NULL — defaults to /tmp, world-readable on shared hosting

Suggested Fix

  1. Remove $this->input->post('groups') from setting() — users should not self-assign groups
  2. Add permission checks to all fetch*Data methods
  3. HTML-encode all output in printDiv()
  4. Use json_decode/json_encode instead of serialize/unserialize for permissions

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions