
openSIS Classic 9.3 - Insecure Direct Object Reference (IDOR)
9,3
Critical
Discovered by
External researcher
Summary
Full name
openSIS Classic 9.3 - Insecure Direct Object Reference (IDOR)
Code name
State
Public
Release date
Affected product
openSIS Classic
Vendor
openSIS
Affected version(s)
9.3
Vulnerability name
Insecure object reference
Vulnerability type
Remotely exploitable
Yes
CVSS v4.0 vector string
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N
CVSS v4.0 base score
9.3
Exploit available
Yes
CVE ID(s)
Description
An authenticated user with the built-in teacher role can select an arbitrary staff record through staff_id and cause the School Information update path to reset that selected account's password. The server authorizes the request only at the broad role/module level; it never verifies that the selected staff record belongs to the authenticated teacher or that the teacher has edit permission for it.
Consequently, a teacher can set a new password for an administrator account and authenticate as that administrator. This is not intended self-service profile behavior: the teacher menu labels the endpoint as “My Info,” and the default permission data grants teachers CAN_USE but not CAN_EDIT for the relevant staff-information categories.
Vulnerability
Root cause
The staff-management workflow conflates the authenticated user with the staff record selected for editing. In a new Teacher session, Staff.php accepts an arbitrary request-supplied staff_id and persists it as $_SESSION['staff_id']. Subsequent authorization checks permit the Teacher role but do not verify that this selected record belongs to that Teacher. The password-update workflow then uses that selected session ID to update an authentication credential.
Source-to-sink path
Attacker-controlled object selection —
modules/users/Staff.php:33-34copies$_REQUEST['staff_id']to$_SESSION['staff_id']when no staff record is selected.UserStaffID()is only a wrapper over that session value (functions/CurrentFnc.php:78-81); it is not the authenticated principal ($_SESSION['STAFF_ID']).A direct request selecting another staff ID therefore establishes that other account as the active object in the teacher's session. There is no equality/ownership check against
UserID()or$_SESSION['STAFF_ID'].Role-only access control — the endpoint explicitly allows both administrators and teachers past its target-selection gate (
modules/users/Staff.php:159-164). The teacher menu exposesusers/Staff.phpas “My Info” (modules/users/Menu.php:48-51), and the supplied default profile data grants profile 2 (teacher) use of that endpoint and its School Information category while leavingCAN_EDITunset (install/Upgrade6.php:1577-1579). These UI/permission settings do not enforce object ownership at the write sink.Credential-update sink — when
SchoolsInfoInc.phpprocessesstaff_school[PASSWORD], it obtains the selected staff record usingUserStaffID()(modules/users/includes/SchoolsInfoInc.php:482-487), generates a password hash, and writes it tologin_authenticationfor the selected account (modules/users/includes/SchoolsInfoInc.php:499-541). No condition verifies either ownership of thatUSER_IDorAllowEdit().
The reporter's original explanation conflates this with the earlier UPDATE staff ... WHERE STAFF_ID=$_REQUEST[staff_id] code in Staff.php. That is not the credential-table sink used by the supplied staff_school[PASSWORD] request. The exploitable credential update is the SchoolsInfoInc.php flow above.
Impact
An authenticated user with the Teacher role can reset the password of an Administrator account and log in as that Administrator. This provides unauthorized access to administrator-only functions and the information and integrity controls available to that role. The demonstrated attack requires neither victim interaction nor knowledge of the Administrator's previous password.
PoC
The following procedure should be performed only against a locally controlled installation.
Log in as a teacher and identify an administrator's numeric
STAFF_ID, denoted below asTARGET_ID.In the same authenticated session, load the Staff endpoint with
staff_id=TARGET_ID. This causesStaff.php:33-34to storeTARGET_IDin$_SESSION['staff_id']. If the teacher had already selected their own record, first use the normal deselect/back flow (or start a fresh session) so that the target-selection assignment can occur.Submit a multipart POST to the normal Staff update route with
modfunc=update,include=SchoolsInfoInc, and a new value forstaff_school[PASSWORD]. Preserve the session cookie. The request must contain the ordinary School Information fields required by the deployment;school_info_idis not the authorization control.The handler hashes the supplied password and updates
login_authentication.USER_ID=TARGET_ID. Authenticate as the target administrator using the new password to confirm the account takeover.
Evidence of Exploitation
Video of exploitation:
Static evidence:

Our security policy
We have reserved the ID CVE-2026-91107 to refer to this issue from now on.
System Information
openSIS Classic
Version: 9.3 Community Edition
Operating System: Any deployment running the affected openSIS Classic messaging module
References
GitHub Repository: https://github.com/OS4ED/openSIS-Classic
Patch: https://github.com/OS4ED/openSIS-Classic/commit/24bb530391a67c114cd4fe3dff65da7e070f5ed1
Mitigation
An updated version of OpenSIS is available on the vendor page.
Credits
The vulnerability was discovered by Daniel Celis, an independent security researcher.
Timeline
Vulnerability discovered
Vendor contacted
Vendor replied
Vendor confirmed
Vulnerability patched
Public disclosure
Does your application use this vulnerable software?
During our free trial, our tools assess your application, identify vulnerabilities, and provide recommendations for their remediation.














