Skip to content

Security: Entire payments module unauthenticated + payment bypass + invoice IDOR #30

Description

@lighthousekeeper1212

Summary

Security audit identified 7 vulnerabilities (3 CRITICAL, 3 HIGH, 1 MEDIUM) in SkyLearn. The most severe is the entire payments module (11 views) having zero authentication, allowing anonymous payment bypass and invoice manipulation.

Critical Findings

1. CRITICAL: Entire Payments Module Missing Authentication (11 Views)

File: payments/views.py:18-191

None of the 11 payment views have @login_required or any authentication decorator:

def payment_paypal(request):         # Line 18 - no decorator
def payment_stripe(request):         # Line 22 - no decorator
class PaymentGetwaysView(TemplateView):  # Line 38 - no mixin
def stripe_charge(request):          # Line 51 - no decorator, processes Stripe charges
def gopay_charge(request):           # Line 70 - no decorator, processes GoPay payments
def paymentComplete(request):        # Line 146 - no decorator, marks invoices as paid
def create_invoice(request):         # Line 159 - no decorator, creates invoices
def invoice_detail(request, slug):   # Line 185 - no decorator, displays any invoice

2. CRITICAL: Payment Completion Without Server-Side Verification

File: payments/views.py:146-156

def paymentComplete(request):
    if request.is_ajax() or request.method == "POST":
        invoice_id = request.session["invoice_session"]
        invoice = Invoice.objects.get(id=invoice_id)
        invoice.payment_complete = True
        invoice.save()

Marks invoices as paid without verifying any payment actually occurred with Stripe/PayPal/GoPay.

3. CRITICAL: Invoice Detail IDOR — No Auth, No Ownership

File: payments/views.py:185-190

def invoice_detail(request, slug):
    return render(request, "invoice_detail.html",
        context={"invoice": Invoice.objects.get(invoice_code=slug)})

HIGH Findings

4. post_add Missing @lecturer_required (1-of-N)

File: core/views.py:40-52

post_add has only @login_required, but edit_post and delete_post both have @login_required AND @lecturer_required. Any student can create official news/events.

5. File/Video Edit No Course Ownership Check

File: course/views.py:285-303

handle_file_edit fetches file by file_id without verifying it belongs to the course in the URL or to the requesting lecturer. A lecturer teaching Course A can modify files belonging to Course B.

6. Result PDF — Any Lecturer Views Any Course's Grades

File: result/views.py:277-446

result_sheet_pdf_view takes any course ID without checking the requesting lecturer is allocated to that course. 1-of-N: add_score_for (line 70) filters by allocated_course__lecturer__pk=request.user.id.

7. MEDIUM: SearchView Has No Authentication

File: search/views.py:1-38

SearchView(ListView) has no LoginRequiredMixin. Anonymous users can search and enumerate all programs, courses, quizzes, and events.

What Was Fixed from django-lms

SkyLearn correctly fixed the 2 most critical django-lms findings:

  • handle_file_delete now has @login_required + @lecturer_required
  • handle_video_delete now has @login_required + @lecturer_required

Recommended Systemic Fix

Add Django's LoginRequiredMiddleware (Django 4.1+) globally. Use @login_not_required for the handful of public views.


Reported by Lighthouse Security Research (lighthouse1212.com)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions