mirror of
				https://github.com/HackTricks-wiki/hacktricks.git
				synced 2025-10-10 18:36:50 +00:00 
			
		
		
		
	Translated ['', 'src/pentesting-web/dependency-confusion.md'] to pt
This commit is contained in:
		
							parent
							
								
									e7ea0c6efe
								
							
						
					
					
						commit
						9e5578d08b
					
				@ -5,41 +5,268 @@
 | 
			
		||||
 | 
			
		||||
## Informações Básicas
 | 
			
		||||
 | 
			
		||||
Em resumo, uma vulnerabilidade de confusão de dependência ocorre quando um projeto está usando uma biblioteca com um nome **mal escrito**, **inexistente** ou com uma **versão não especificada** e o repositório de dependências utilizado permite **coletar versões atualizadas de repositórios públicos**.
 | 
			
		||||
Confusão de Dependência (a.k.a. ataques de substituição) acontece quando um gerenciador de pacotes resolve um nome de dependência de um registro/fonte não intencionado e menos confiável (geralmente um registro público) em vez do privado/interno pretendido. Isso geralmente leva à instalação de um pacote controlado pelo atacante.
 | 
			
		||||
 | 
			
		||||
Causas raízes comuns:
 | 
			
		||||
- Typosquatting/erro de digitação: Importando `reqests` em vez de `requests` (resolve de registro público).
 | 
			
		||||
- Pacote interno inexistente/abandonado: Importando `company-logging` que não existe mais internamente, então o resolvedor procura em registros públicos e encontra um pacote do atacante.
 | 
			
		||||
- Preferência de versão entre múltiplos registros: Importando um `company-requests` interno enquanto o resolvedor pode também consultar registros públicos e prefere a versão “melhor”/mais nova publicada publicamente por um atacante.
 | 
			
		||||
 | 
			
		||||
Ideia chave: Se o resolvedor pode ver múltiplos registros para o mesmo nome de pacote e é permitido escolher o “melhor” candidato globalmente, você está vulnerável a menos que restrinja a resolução.
 | 
			
		||||
 | 
			
		||||
- **Mal escrito**: Importar **`reqests`** em vez de `requests`
 | 
			
		||||
- **Inexistente**: Importar `company-logging`, uma biblioteca interna que **não existe mais**
 | 
			
		||||
- **Versão não especificada**: Importar uma biblioteca `company-requests` **interna** **existente**, mas o repositório verifica **repositórios públicos** para ver se há **versões maiores**.
 | 
			
		||||
 | 
			
		||||
## Exploração
 | 
			
		||||
 | 
			
		||||
> [!WARNING]
 | 
			
		||||
> Em todos os casos, o atacante só precisa publicar um **pacote malicioso com o nome** das bibliotecas usadas pela empresa vítima.
 | 
			
		||||
> Em todos os casos, o atacante só precisa publicar um pacote malicioso com o mesmo nome da dependência que sua construção resolve de um registro público. Hooks de tempo de instalação (por exemplo, scripts npm) ou caminhos de código de tempo de importação frequentemente permitem a execução de código.
 | 
			
		||||
 | 
			
		||||
### Mal Escrito & Inexistente
 | 
			
		||||
### Erros de Digitação & Inexistente
 | 
			
		||||
 | 
			
		||||
Se sua empresa está tentando **importar uma biblioteca que não é interna**, é altamente provável que o repositório de bibliotecas esteja procurando por ela em **repositórios públicos**. Se um atacante a criou, seu código e máquinas em execução provavelmente estarão comprometidos.
 | 
			
		||||
Se seu projeto referencia uma biblioteca que não está disponível no registro privado, e suas ferramentas recorrem a um registro público, um atacante pode semear um pacote malicioso com esse nome no registro público. Seus runners/máquinas de CI/dev irão buscá-lo e executá-lo.
 | 
			
		||||
 | 
			
		||||
### Versão Não Especificada
 | 
			
		||||
### Versão Não Especificada / Seleção de “Melhor-versão” entre índices
 | 
			
		||||
 | 
			
		||||
É muito comum que os desenvolvedores **não especifiquem nenhuma versão** da biblioteca utilizada, ou especifiquem apenas uma **versão principal**. Então, o interpretador tentará baixar a **última versão** que atenda a esses requisitos.\
 | 
			
		||||
Se a biblioteca for uma **biblioteca externa conhecida** (como o `requests` do python), um **atacante não pode fazer muito**, pois ele não conseguirá criar uma biblioteca chamada `requests` (a menos que seja o autor original).\
 | 
			
		||||
No entanto, se a biblioteca for **interna**, como `requests-company` neste exemplo, se o **repositório da biblioteca** permitir **verificar novas versões também externamente**, ele buscará uma versão mais nova disponível publicamente.\
 | 
			
		||||
Portanto, se um **atacante souber** que a empresa está usando a biblioteca `requests-company` **versão 1.0.1** (permitindo atualizações menores). Ele pode **publicar** a biblioteca `requests-company` **versão 1.0.2** e a empresa **usará essa biblioteca em vez** da interna.
 | 
			
		||||
Desenvolvedores frequentemente deixam versões não fixadas ou permitem faixas amplas. Quando um resolvedor é configurado com índices internos e públicos, ele pode selecionar a versão mais nova independentemente da fonte. Para nomes internos como `requests-company`, se o índice interno tem `1.0.1` mas um atacante publica `1.0.2` no registro público e seu resolvedor considera ambos, o pacote público pode vencer.
 | 
			
		||||
 | 
			
		||||
## Correção da AWS
 | 
			
		||||
 | 
			
		||||
Essa vulnerabilidade foi encontrada no **CodeArtifact** da AWS (leia os [**detalhes neste post do blog**](https://zego.engineering/dependency-confusion-in-aws-codeartifact-86b9ff68963d)).\
 | 
			
		||||
A AWS corrigiu isso permitindo especificar se uma biblioteca é interna ou externa, para evitar o download de dependências internas de repositórios externos.
 | 
			
		||||
## Correção AWS
 | 
			
		||||
 | 
			
		||||
Essa vulnerabilidade foi encontrada no AWS CodeArtifact (leia os detalhes neste post do blog). A AWS adicionou controles para marcar dependências/alimentações como internas vs externas para que o cliente não busque nomes “internos” de registros públicos upstream.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Encontrando Bibliotecas Vulneráveis
 | 
			
		||||
 | 
			
		||||
No [**post original sobre confusão de dependência**](https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610), o autor pesquisou milhares de arquivos package.json expostos contendo as dependências de projetos em javascript.
 | 
			
		||||
No post original sobre confusão de dependência, o autor procurou milhares de manifests expostos (por exemplo, `package.json`, `requirements.txt`, arquivos de bloqueio) para inferir nomes de pacotes internos e então publicou pacotes de versões superiores em registros públicos.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Playbook Prático do Atacante (para equipes vermelhas em testes autorizados)
 | 
			
		||||
 | 
			
		||||
- Enumerar nomes:
 | 
			
		||||
- Grep repositórios e configurações de CI em busca de arquivos de manifest/lock e namespaces internos.
 | 
			
		||||
- Procurar por prefixos específicos da organização (por exemplo, `@company/*`, `company-*`, groupIds internos, padrões de ID do NuGet, caminhos de módulos privados para Go, etc.).
 | 
			
		||||
- Verificar registros públicos para disponibilidade:
 | 
			
		||||
- Se o nome não estiver registrado publicamente, registre-o; se existir, tente o sequestro de subdependência visando nomes transitivos internos.
 | 
			
		||||
- Publicar com precedência:
 | 
			
		||||
- Escolha um semver que “vença” (por exemplo, uma versão muito alta) ou que corresponda às regras do resolvedor.
 | 
			
		||||
- Incluir execução mínima em tempo de instalação onde aplicável (por exemplo, scripts npm `preinstall`/`install`/`postinstall`). Para Python, prefira caminhos de execução em tempo de importação, pois wheels normalmente não executam código arbitrário na instalação.
 | 
			
		||||
- Exfiltrar controle:
 | 
			
		||||
- Assegure que a saída é permitida de CI para seu endpoint controlado; caso contrário, use consultas DNS ou mensagens de erro como um canal lateral para provar a execução de código.
 | 
			
		||||
 | 
			
		||||
> [!CAUTION]
 | 
			
		||||
> Sempre obtenha autorização por escrito, use nomes/versões de pacotes únicos para o engajamento e imediatamente despublique ou coordene a limpeza quando o teste concluir.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Playbook do Defensor (o que realmente previne confusão)
 | 
			
		||||
 | 
			
		||||
Estratégias de alto nível que funcionam em ecossistemas:
 | 
			
		||||
- Use namespaces internos únicos e vincule-os a um único registro.
 | 
			
		||||
- Evite misturar níveis de confiança no momento da resolução. Prefira um único registro interno que faça proxy de pacotes públicos aprovados em vez de dar aos gerenciadores de pacotes tanto endpoints internos quanto públicos.
 | 
			
		||||
- Para gerenciadores que suportam, mapeie pacotes para fontes específicas (sem “melhor-versão” global entre registros).
 | 
			
		||||
- Fixar e bloquear:
 | 
			
		||||
- Use arquivos de bloqueio que registram as URLs de registro resolvidas (npm/yarn/pnpm) ou use fixação de hash/atestado (pip `--require-hashes`, verificação de dependência do Gradle).
 | 
			
		||||
- Bloquear fallback público para nomes internos na camada de registro/rede.
 | 
			
		||||
- Reserve seus nomes internos em registros públicos quando viável para prevenir futuros squats.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Notas do Ecossistema e Trechos de Configuração Segura
 | 
			
		||||
 | 
			
		||||
Abaixo estão configurações pragmáticas e mínimas para reduzir ou eliminar a confusão de dependência. Prefira impor isso em ambientes de CI e desenvolvedores.
 | 
			
		||||
 | 
			
		||||
### JavaScript/TypeScript (npm, Yarn, pnpm)
 | 
			
		||||
 | 
			
		||||
- Use pacotes com escopo para todo o código interno e fixe o escopo ao seu registro privado.
 | 
			
		||||
- Mantenha instalações imutáveis em CI (arquivo de bloqueio npm, `yarn install --immutable`).
 | 
			
		||||
 | 
			
		||||
.npmrc (nível do projeto)
 | 
			
		||||
```
 | 
			
		||||
# Bind internal scope to private registry; do not allow public fallback for @company/*
 | 
			
		||||
@company:registry=https://registry.corp.example/npm/
 | 
			
		||||
# Always authenticate to the private registry
 | 
			
		||||
//registry.corp.example/npm/:_authToken=${NPM_TOKEN}
 | 
			
		||||
strict-ssl=true
 | 
			
		||||
```
 | 
			
		||||
package.json (para pacote interno)
 | 
			
		||||
```
 | 
			
		||||
{
 | 
			
		||||
"name": "@company/api-client",
 | 
			
		||||
"version": "1.2.3",
 | 
			
		||||
"private": false,
 | 
			
		||||
"publishConfig": {
 | 
			
		||||
"registry": "https://registry.corp.example/npm/",
 | 
			
		||||
"access": "restricted"
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
Yarn Berry (.yarnrc.yml)
 | 
			
		||||
```
 | 
			
		||||
npmScopes:
 | 
			
		||||
company:
 | 
			
		||||
npmRegistryServer: "https://registry.corp.example/npm/"
 | 
			
		||||
npmAlwaysAuth: true
 | 
			
		||||
# CI should fail if lockfile would change
 | 
			
		||||
enableImmutableInstalls: true
 | 
			
		||||
```
 | 
			
		||||
Dicas operacionais:
 | 
			
		||||
- Publique apenas pacotes internos dentro do escopo `@company`.
 | 
			
		||||
- Para pacotes de terceiros, permita o registro público através do seu proxy espelho privado, não diretamente dos clientes.
 | 
			
		||||
- Considere habilitar a proveniência de pacotes npm para pacotes públicos que você publica para aumentar a rastreabilidade (isso não previne confusão por si só).
 | 
			
		||||
 | 
			
		||||
### Python (pip / Poetry)
 | 
			
		||||
 | 
			
		||||
Regra principal: Não use `--extra-index-url` para misturar níveis de confiança. Ou:
 | 
			
		||||
- Exponha um único índice interno que proxy e cache pacotes PyPI aprovados, ou
 | 
			
		||||
- Use seleção de índice explícita e fixação de hash.
 | 
			
		||||
 | 
			
		||||
pip.conf
 | 
			
		||||
```
 | 
			
		||||
[global]
 | 
			
		||||
index-url = https://pypi.corp.example/simple
 | 
			
		||||
# Disallow source distributions when possible
 | 
			
		||||
only-binary = :all:
 | 
			
		||||
# Lock with hashes generated via pip-tools
 | 
			
		||||
require-hashes = true
 | 
			
		||||
```
 | 
			
		||||
Gerar requisitos hash com pip-tools:
 | 
			
		||||
```
 | 
			
		||||
# From pyproject.toml or requirements.in
 | 
			
		||||
pip-compile --generate-hashes -o requirements.txt
 | 
			
		||||
pip install --require-hashes -r requirements.txt
 | 
			
		||||
```
 | 
			
		||||
Se você precisar acessar o PyPI público, faça isso através do seu proxy interno e mantenha uma lista de permissões explícita lá. Evite `--extra-index-url` no CI.
 | 
			
		||||
 | 
			
		||||
### .NET (NuGet)
 | 
			
		||||
 | 
			
		||||
Use o Mapeamento de Fonte de Pacote para vincular padrões de ID de pacote a fontes explícitas e evitar a resolução de feeds inesperados.
 | 
			
		||||
 | 
			
		||||
nuget.config
 | 
			
		||||
```
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<configuration>
 | 
			
		||||
<packageSources>
 | 
			
		||||
<clear />
 | 
			
		||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
 | 
			
		||||
<add key="corp" value="https://nuget.corp.example/v3/index.json" />
 | 
			
		||||
</packageSources>
 | 
			
		||||
<packageSourceMapping>
 | 
			
		||||
<packageSource key="nuget.org">
 | 
			
		||||
<package pattern="*" />
 | 
			
		||||
</packageSource>
 | 
			
		||||
<packageSource key="corp">
 | 
			
		||||
<package pattern="Company.*" />
 | 
			
		||||
<package pattern="Internal.Utilities" />
 | 
			
		||||
</packageSource>
 | 
			
		||||
</packageSourceMapping>
 | 
			
		||||
</configuration>
 | 
			
		||||
```
 | 
			
		||||
### Java (Maven/Gradle)
 | 
			
		||||
 | 
			
		||||
Maven settings.xml (espelhar tudo para interno; desabilitar repositórios ad-hoc em POMs via Enforcer):
 | 
			
		||||
```
 | 
			
		||||
<settings>
 | 
			
		||||
<mirrors>
 | 
			
		||||
<mirror>
 | 
			
		||||
<id>internal-mirror</id>
 | 
			
		||||
<mirrorOf>*</mirrorOf>
 | 
			
		||||
<url>https://maven.corp.example/repository/group</url>
 | 
			
		||||
</mirror>
 | 
			
		||||
</mirrors>
 | 
			
		||||
</settings>
 | 
			
		||||
```
 | 
			
		||||
Adicione Enforcer para banir repositórios declarados em POMs e forçar o uso do seu espelho:
 | 
			
		||||
```
 | 
			
		||||
<plugin>
 | 
			
		||||
<groupId>org.apache.maven.plugins</groupId>
 | 
			
		||||
<artifactId>maven-enforcer-plugin</artifactId>
 | 
			
		||||
<version>3.6.1</version>
 | 
			
		||||
<executions>
 | 
			
		||||
<execution>
 | 
			
		||||
<id>enforce-no-repositories</id>
 | 
			
		||||
<goals><goal>enforce</goal></goals>
 | 
			
		||||
<configuration>
 | 
			
		||||
<rules>
 | 
			
		||||
<requireNoRepositories />
 | 
			
		||||
</rules>
 | 
			
		||||
</configuration>
 | 
			
		||||
</execution>
 | 
			
		||||
</executions>
 | 
			
		||||
</plugin>
 | 
			
		||||
```
 | 
			
		||||
Gradle: Centralize e bloqueie dependências.
 | 
			
		||||
- Aplique repositórios apenas em `settings.gradle(.kts)`:
 | 
			
		||||
```
 | 
			
		||||
dependencyResolutionManagement {
 | 
			
		||||
repositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS
 | 
			
		||||
repositories {
 | 
			
		||||
maven { url = uri("https://maven.corp.example/repository/group") }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
- Ative a verificação de dependências (checksums/siglas) e comite `gradle/verification-metadata.xml`.
 | 
			
		||||
 | 
			
		||||
### Go Modules
 | 
			
		||||
 | 
			
		||||
Configure módulos privados para que o proxy público e o banco de dados de checksums não sejam usados para eles.
 | 
			
		||||
```
 | 
			
		||||
# Use corporate proxy first, then public proxy as fallback
 | 
			
		||||
export GOPROXY=https://goproxy.corp.example,https://proxy.golang.org
 | 
			
		||||
# Mark private paths to skip proxy and checksum db
 | 
			
		||||
export GOPRIVATE=*.corp.example.com,github.com/your-org/*
 | 
			
		||||
export GONOSUMDB=*.corp.example.com,github.com/your-org/*
 | 
			
		||||
```
 | 
			
		||||
### Rust (Cargo)
 | 
			
		||||
 | 
			
		||||
Substitua crates.io por um espelho interno aprovado ou diretório de fornecedor para builds; não permita fallback público arbitrário.
 | 
			
		||||
 | 
			
		||||
.cargo/config.toml
 | 
			
		||||
```
 | 
			
		||||
[source.crates-io]
 | 
			
		||||
replace-with = "corp-mirror"
 | 
			
		||||
 | 
			
		||||
[source.corp-mirror]
 | 
			
		||||
registry = "https://crates-mirror.corp.example/index"
 | 
			
		||||
```
 | 
			
		||||
Para publicação, seja explícito com `--registry` e mantenha as credenciais restritas ao registro de destino.
 | 
			
		||||
 | 
			
		||||
### Ruby (Bundler)
 | 
			
		||||
 | 
			
		||||
Use blocos de origem e desative Gemfiles de múltiplas fontes para que os gems venham apenas do repositório pretendido.
 | 
			
		||||
 | 
			
		||||
Gemfile
 | 
			
		||||
```
 | 
			
		||||
source "https://gems.corp.example"
 | 
			
		||||
 | 
			
		||||
source "https://rubygems.org" do
 | 
			
		||||
gem "rails"
 | 
			
		||||
gem "pg"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
source "https://gems.corp.example" do
 | 
			
		||||
gem "company-logging"
 | 
			
		||||
end
 | 
			
		||||
```
 | 
			
		||||
Impor em nível de configuração:
 | 
			
		||||
```
 | 
			
		||||
bundle config set disable_multisource true
 | 
			
		||||
```
 | 
			
		||||
## CI/CD e Controles de Registro que Ajudam
 | 
			
		||||
 | 
			
		||||
- Registro privado como um único ponto de entrada:
 | 
			
		||||
- Use Artifactory/Nexus/CodeArtifact/GitHub Packages/Azure Artifacts como o único endpoint que desenvolvedores/CI podem acessar.
 | 
			
		||||
- Implemente regras de bloqueio/permissão para que namespaces internos nunca sejam resolvidos a partir de fontes públicas upstream.
 | 
			
		||||
- Lockfiles são imutáveis em CI:
 | 
			
		||||
- npm: comite `package-lock.json`, use `npm ci`.
 | 
			
		||||
- Yarn: comite `yarn.lock`, use `yarn install --immutable`.
 | 
			
		||||
- Python: comite `requirements.txt` com hash, imponha `--require-hashes`.
 | 
			
		||||
- Gradle: comite `verification-metadata.xml` e falhe em artefatos desconhecidos.
 | 
			
		||||
- Controle de saída: bloqueie o acesso direto do CI a registros públicos, exceto via o proxy aprovado.
 | 
			
		||||
- Reserva de nomes: pré-registre seus nomes/namespaces internos em registros públicos onde suportado.
 | 
			
		||||
- Proveniência de pacotes / atestações: ao publicar pacotes públicos, habilite proveniência/atestações para tornar a adulteração mais detectável a montante.
 | 
			
		||||
 | 
			
		||||
## Referências
 | 
			
		||||
 | 
			
		||||
- [https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610](https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610)
 | 
			
		||||
- [https://zego.engineering/dependency-confusion-in-aws-codeartifact-86b9ff68963d](https://zego.engineering/dependency-confusion-in-aws-codeartifact-86b9ff68963d)
 | 
			
		||||
 | 
			
		||||
- [https://learn.microsoft.com/en-us/nuget/consume-packages/package-source-mapping](https://learn.microsoft.com/en-us/nuget/consume-packages/package-source-mapping)
 | 
			
		||||
- [https://yarnpkg.com/configuration/yarnrc/](https://yarnpkg.com/configuration/yarnrc/)
 | 
			
		||||
 | 
			
		||||
{{#include ../banners/hacktricks-training.md}}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user