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
- 8 individual record fetch endpoints missing permission checks (
fetchBrandDataById, etc.)
- Hardcoded encryption key (
config.php:327) — Go87NSzqqq96Dq2jcjnvhVUCpKPeP2ea in public repo
- CSRF protection disabled (
config.php:451) — csrf_protection = FALSE
- PHP object injection (
MY_Controller.php:29-30) — unserialize($group_data['permission']) on every request
Low Findings
- Reports controller missing
not_logged_in() — inconsistency, not directly exploitable
- Session save path NULL — defaults to
/tmp, world-readable on shared hosting
Suggested Fix
- Remove
$this->input->post('groups') from setting() — users should not self-assign groups
- Add permission checks to all
fetch*Data methods
- HTML-encode all output in
printDiv()
- Use
json_decode/json_encode instead of serialize/unserialize for permissions
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-288The
setting()method passes$this->input->post('groups')directly tomodel_users->edit():Any authenticated user who changes their password can simultaneously change their group to Administrator (group_id=1) by including a
groupsfield in the POST request.Impact: Any user with
updateSettingpermission can escalate to full Administrator.High Findings
2. Attribute Value Operations Missing Permission Checks
File:
application/controllers/Attributes.php:251-358createValue(),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:44fetchProductData,fetchOrdersData, etc. return full datasets via AJAX without permission checks. Theindex()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-391printDiv()constructs HTML by concatenating database values without HTML encoding.customer_name,customer_address, etc. are echoed unescaped. Users withcreateOrdercan inject XSS that executes when admins view invoices.Medium Findings
fetchBrandDataById, etc.)config.php:327) —Go87NSzqqq96Dq2jcjnvhVUCpKPeP2eain public repoconfig.php:451) —csrf_protection = FALSEMY_Controller.php:29-30) —unserialize($group_data['permission'])on every requestLow Findings
not_logged_in()— inconsistency, not directly exploitable/tmp, world-readable on shared hostingSuggested Fix
$this->input->post('groups')fromsetting()— users should not self-assign groupsfetch*DatamethodsprintDiv()json_decode/json_encodeinstead ofserialize/unserializefor permissions