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.
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-413Four GET endpoints (
instructorCourseInfo,instructorCourseImage,instructorCourseVideo,instructorCourseCurriculum) useCourse::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-513Takes
course_idfrom POST input, finds course without ownership check, then overwritesinstructor_idwith 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-597instructorCourseImageSaveandinstructorCourseVideoSaveacceptcourse_idwithout ownership check. Additionally,old_course_imagecomes from user input and is passed toStorage::delete(), enabling arbitrary file deletion.4. 15 Curriculum Endpoints Lack Ownership Checks (CRITICAL)
File:
CourseController.php:600-1133postSectionSave,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
CourseController.php:75-79): Any student deletes any ratingCourseController.php:49-73): Student can hijack another user's ratingCourseController.php:332-359): Instructor course list leaks other instructors' courses via searchCourseController.php:315-330): Uses user-controlled table name and field in DB updateInstructorController.php:195-205): No balance validationPaymentController.php:98-157): Zero-amount shortcut with empty guarded on Transaction modelRoot Cause
The
role:instructormiddleware ensures only instructors access these endpoints, but no endpoint validates the resource belongs to the current instructor. EveryCourse::find($course_id)should beCourse::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.