Skip to content

Security: Systemic Cross-Instructor IDOR - Course Takeover, Content Manipulation #77

@lighthousekeeper1212

Description

@lighthousekeeper1212

Summary

Security audit identified 13 vulnerabilities (4 Critical, 6 High, 3 Medium) in ulearn. The dominant pattern is systemic missing ownership checks in instructor endpoints.

Critical Findings

1. Cross-Instructor Course View/Edit IDOR (CRITICAL)

Files: app/Http/Controllers/CourseController.php:361-413

Four GET endpoints (instructorCourseInfo, instructorCourseImage, instructorCourseVideo, instructorCourseCurriculum) use Course::find($course_id) without verifying the course belongs to the authenticated instructor. Any instructor can view/edit any other instructor's course.

2. Course Takeover via instructorCourseInfoSave (CRITICAL)

File: CourseController.php:462-513

Takes course_id from POST input, finds course without ownership check, then overwrites instructor_id with current user's ID. Any instructor can steal any course.

3. Cross-Instructor Image/Video Modification + File Deletion (CRITICAL)

Files: CourseController.php:415-460, 515-597

instructorCourseImageSave and instructorCourseVideoSave accept course_id without ownership check. Additionally, old_course_image comes from user input and is passed to Storage::delete(), enabling arbitrary file deletion.

4. 15 Curriculum Endpoints Lack Ownership Checks (CRITICAL)

File: CourseController.php:600-1133

postSectionSave, postSectionDelete, postLectureSave, postLectureQuizDelete, postLectureDescSave, postLectureVideoSave, postLectureAudioSave, postLecturePresentationSave, postLectureDocumentSave, postLectureResourceSave, postLectureResourceDelete, postLectureTextSave, postLecturePublishSave, postLectureLibrarySave, postCurriculumSort — none verify resource ownership. Any instructor can modify any course's curriculum.

High Findings

  • Rating Deletion IDOR (CourseController.php:75-79): Any student deletes any rating
  • Rating Update/Hijack (CourseController.php:49-73): Student can hijack another user's rating
  • orWhere SQL Logic Bug (CourseController.php:332-359): Instructor course list leaks other instructors' courses via search
  • Arbitrary DB Field Clearing via deletePhoto (CourseController.php:315-330): Uses user-controlled table name and field in DB update
  • Withdraw Amount Manipulation (InstructorController.php:195-205): No balance validation
  • Payment Bypass (PaymentController.php:98-157): Zero-amount shortcut with empty guarded on Transaction model

Root Cause

The role:instructor middleware ensures only instructors access these endpoints, but no endpoint validates the resource belongs to the current instructor. Every Course::find($course_id) should be Course::where('id', $course_id)->where('instructor_id', Auth::user()->instructor->id)->firstOrFail().


Found during security research. This report covers vulnerability classes and fixes without providing exploitation details.

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