
Extrai URLs de Arquivos de OSINT para Insights de Segurança
Extrai URLs de Arquivos OSINT para Insights de Segurança.
Urx é uma ferramenta de linha de comando projetada para coletar URLs de arquivos OSINT, como a Wayback Machine e o Common Crawl. Construída com Rust para eficiência, ela aproveita o processamento assíncrono para consultar rapidamente múltiplas fontes de dados. Esta ferramenta simplifica o processo de coleta de informações de URL para um domínio especificado, fornecendo um conjunto de dados abrangente que pode ser usado para diversos fins, incluindo testes de segurança e análise.
--cdx-endpoint URL, sem necessidade de alteração de código-H, --cookie e --user-agent se aplicam a todas as requisições que o urx faz ao alvo (--check-status, --extract-links, --extract-js-endpoints, --expand-specs) e deliberadamente nunca são enviados a um arquivo--match-regex / --filter-regex)--meta-*): filtre por data da primeira/última captura, tipo MIME registrado e status registrado uniformemente em todos os provedores, após a coletaurx example.com/shop envia o escopo para a própria consulta CDX (url=example.com/shop*), de modo que uma subárvore de um site grande custa uma fração do índice inteiro em vez de ser filtrada no lado do cliente--scope-file): a própria lista *.example.com / !admin.example.com de um programa usada literalmente, repetível e unida, com exclusões sempre prevalecendo--dedup-similar)wordlist — os segmentos de caminho e nomes de parâmetros dos quais o alvo é construído, com ids, hashes e datas deixados de fora--params (o inventário completo de parâmetros do alvo), --params-by-endpoint (qual endpoint aceita o quê) e --fuzz-placeholder FUZZ (uma URL modelada por assinatura de parâmetro, pronta para ffuf ou dalfox)first_seen, last_seen, mime, archive_status e digest retornam com cada URL que um arquivo CDX reportou, sem custo extra de rede--stream): as URLs são escritas conforme cada provedor as reporta, para que um pipeline comece a funcionar imediatamente em vez de esperar pelo arquivo mais lento--archive-body), para que páginas que não existem mais ainda revelem os links que continham — uma requisição por corpo distinto, graças à deduplicação por digest do CDX--extract-js-endpoints, minera também o JavaScript arquivado: um bundle nomeado por hash de build retorna 404 no momento em que o site é reimplantado, e o arquivo é o único lugar onde sua superfície de API ainda existe--archive-body-dir) como um corpus para grep do que nenhum extrator de links procura — comentários de desenvolvedores, credenciais embutidas, hostnames internos — sem requisições extras--expand-specs): documentos OpenAPI 3.x, Swagger 2.0 e introspecção GraphQL, JSON ou YAML, transformados em todas as rotas que descrevem — uma requisição compra toda a superfície documentada--check-status também registra Location, Content-Length e Content-Type, e --check-title adiciona o do HTML--archived-discovery): todas as versões distintas que a Wayback Machine mantém, para que um Disallow: de 2015 ainda nomeie os caminhos que o site deixou de mencionarurx cache para inspecionar e manter o cache: stats, list, prune, drop <domain>, clear
cargo install urx
### Do Homebrew```bash
# https://formulae.brew.sh/formula/urx
brew install urx
git clone https://github.com/hahwul/urx.git cd urx cargo build --release
O binário compilado estará disponível em `target/release/urx`.
### A partir do Docker
[ghcr.io/hahwul/urx](https://github.com/hahwul/urx/pkgs/container/urx)
### Shell Completions
O `urx` gera seu próprio script de completion, então ele sempre corresponde às flags do
binário que você realmente tem instalado.```bash
# zsh — any directory on your $fpath works
urx --completions zsh > ~/.zfunc/_urx
# (make sure ~/.zfunc is on the fpath, then `compinit`)
# bash
urx --completions bash > ~/.local/share/bash-completion/completions/urx
# fish
urx --completions fish > ~/.config/fish/completions/urx.fish
powershell e elvish também são suportados. A flag não precisa de domínio de destino.
urx --manpage > ~/.local/share/man/man1/urx.1 man urx
## Uso
### Uso Básico```bash
# Scan a single domain
urx example.com
# Scan multiple domains
urx example.com example.org
# Scan domains from a file
cat domains.txt | urx
Usage: urx [OPTIONS] [DOMAINS]... [COMMAND]
Commands: cache Inspect and maintain the URL cache: stats, list, prune, drop ..., clear
Arguments: [DOMAINS]... Domains to fetch URLs for
Options: -c, --config Config file to load --provider-config Separate provider config file holding only API keys (default: $XDG_CONFIG_HOME/urx/provider-config.toml). CLI/env > provider-config > main config. --completions Print a shell completion script (bash, zsh, fish, powershell, elvish) to stdout and exit --manpage Print the roff man page to stdout and exit -h, --help Print help -V, --version Print version
Input Options:
--files ... Read URLs directly from files (supports WARC, URLTeam compressed, and text files)
--domain-list File of newline-separated domains to scan (repeatable; merged with positional DOMAINS and stdin; # comments allowed)
Output Options:
-o, --output Output file to write results
--output-dir Write one file per domain into this directory (extension matches --format). Coexists with --output / stdout.
-f, --format Output format: "plain", "json" (one array), "jsonl" (one JSON object per line), "csv", "wordlist" (path segments and parameter names, deduplicated and sorted) [default: plain]
--stream Write URLs as each provider reports them instead of once at the end (unsorted; bypasses cache; rejects options needing the full result set)
--merge-endpoint Merge endpoints with the same path and merge URL parameters
--normalize-url Normalize URLs for better deduplication (sorts query parameters, removes trailing slashes)
--dedup-similar Collapse URLs that differ only in variable data (numeric ids, UUIDs, hashes, dates, query values)
--params Replace the URL list with every query parameter name the run saw, once each
--params-by-endpoint
One line per endpoint: the endpoint and the comma-separated union of the parameter names seen on it (id-looking path segments collapse to {id})
--fuzz-placeholder
Replace every query parameter value with VALUE, keeping one URL per parameter signature — output you can feed straight to ffuf or dalfox
Provider Options:
--providers
Providers to use (comma-separated, e.g., "wayback,cc,otx,arquivo,vt,urlscan") [default: wayback,cc,otx]
--exclude-providers <EXCLUDE_PROVIDERS>
Providers to exclude (comma-separated). Wins on conflict with --providers / --all-providers.
--all-providers
Enable every supported provider. API-keyed providers only activate when a key is available.
--list-providers
List every supported provider then exit.
--subs
Include subdomains when searching
--cc-index <CC_INDEX>
Common Crawl index to use; accepts comma-separated list to query multiple indexes in parallel (e.g. CC-MAIN-2026-17,CC-MAIN-2025-51). latest (the default) resolves the newest via collinfo.json. [default: latest]
--cdx-endpoint
Query an additional CDX index server (any pywb, OutbackCDX, or classic Internet-Archive-style CDX API) by its full API URL, e.g. https://vefsafn.is/cdx. Repeatable. Each endpoint becomes a provider with id cdx:<host> and honours --subs, --from/--to and the --archive-* filters. See "Custom CDX Endpoints" below
--cdx-dialect
Which CDX dialect the --cdx-endpoint servers speak: pywb or classic. Unset: urx probes each endpoint once and falls back to pywb when the answer is ambiguous
--from
Restrict every CDX-backed provider (wayback, cc, arquivo, --cdx-endpoint) to captures at or after DATE (YYYY/YYYYMM/YYYYMMDD/YYYYMMDDhhmmss). Alias: --wayback-from
--to
Restrict every CDX-backed provider to captures at or before DATE (same format as --from). Alias: --wayback-to
--archive-status
Keep only captures the archive recorded with this HTTP status code (e.g. "200"). Applied by the CDX index itself, so unlike --include-status it costs no extra requests. A multi-value list works on wayback only — see "Archive-side Filtering" below
--archive-exclude-status
Drop captures the archive recorded with these HTTP status codes (comma-separated, e.g. "404,500"). Multi-value works on every CDX provider
--archive-mime
Keep only captures with this recorded MIME type (e.g. "application/json"). Catches endpoints with no file extension, which -e/--extensions cannot
--archive-exclude-mime
Drop captures with these recorded MIME types (comma-separated, e.g. "text/html,image/png")
--vt-api-key <VT_API_KEY>
API key for VirusTotal (can be used multiple times for rotation, can also use URX_VT_API_KEY environment variable with comma-separated keys)
--urlscan-api-key <URLSCAN_API_KEY>
Optional API key for Urlscan; the provider also works anonymously (rate-limited ~30 req/min per IP). Can be used multiple times for rotation, or via URX_URLSCAN_API_KEY (comma-separated keys)
--github-api-key <GITHUB_API_KEY>
Personal access token for the GitHub Code Search provider (also reads URX_GITHUB_API_KEY, comma-separated for rotation)
--bevigil-api-key <BEVIGIL_API_KEY>
API key for BeVigil, which returns URLs extracted from unpacked Android apps (also reads URX_BEVIGIL_API_KEY, comma-separated for rotation). Required for the provider
<title>bevigilDiscovery Options: --exclude-robots Exclude robots.txt discovery --exclude-sitemap Exclude sitemap.xml discovery --archived-discovery Also read every distinct archived version of robots.txt and sitemap.xml the Wayback Machine holds --archived-discovery-limit Maximum archived documents fetched per domain by each archived provider (nested sitemaps count) [default: 50]
Display Options: -v, --verbose Show verbose output --silent Silent mode (no output) --no-progress No progress bar --no-color Disable ANSI color in the progress UI and output (NO_COLOR is also honored) --show-sources Annotate output URLs with the providers that returned them --show-meta Annotate plain-text URLs with the archive capture metadata --stats Print a per-provider summary to stderr at end of run
Filter Options:
-p, --preset
Filter Presets (e.g., "no-resources,no-images,no-audio,only-js,only-style,only-secrets,only-backup,only-config,only-api")
-e, --extensions
Filter URLs to only include those with specific extensions (comma-separated, e.g., "js,php,aspx")
--exclude-extensions <EXCLUDE_EXTENSIONS>
Filter URLs to exclude those with specific extensions (comma-separated, e.g., "html,txt")
--patterns
Filter URLs to only include those containing specific patterns (comma-separated)
--exclude-patterns <EXCLUDE_PATTERNS>
Filter URLs to exclude those containing specific patterns (comma-separated)
--match-regex
Keep only URLs matching this regular expression (repeatable, ORed; case-sensitive; never comma-split)
--filter-regex
Drop URLs matching this regular expression (repeatable; one match is enough)
--show-only-host
Only show the host part of the URLs
--show-only-path
Only show the path part of the URLs
--show-only-param
Only show the parameters part of the URLs
--min-length <MIN_LENGTH>
Minimum URL length to include
--max-length <MAX_LENGTH>
Maximum URL length to include
--strict
Enforce exact host validation (default)
--no-strict
Disable host validation (keep URLs on any host a provider returns). Wins over --strict. A target's path scope still applies: only the host check is waived
--scope-file
Bug-bounty scope file: one host pattern per line, ! to exclude, *.example.com for a wildcard (which covers the apex too), # for a comment. Repeatable and unioned; exclusions always win. See "Scope Files" below
--meta-first-seen-after
Keep URLs whose oldest archived capture is on or after DATE (YYYY/YYYYMM/YYYYMMDD/YYYYMMDDhhmmss)
--meta-first-seen-before
Keep URLs whose oldest archived capture is on or before DATE
--meta-last-seen-after
Keep URLs whose newest archived capture is on or after DATE — "still alive as of"
--meta-last-seen-before
Keep URLs whose newest archived capture is on or before DATE — "dead since"
--meta-mime
Keep only URLs whose archived MIME type is one of these (comma-separated; image/* matches any subtype)
--meta-exclude-mime
Drop URLs whose archived MIME type is one of these
--meta-status
Keep only URLs whose archived status code matches (comma-separated; 20x / 5xx patterns)
--meta-exclude-status
Drop URLs whose archived status code matches
Network Options:
--network-scope <NETWORK_SCOPE> Control which components network settings apply to (all, providers, testers, or providers,testers) [default: all]
--proxy Use proxy for HTTP requests (format: http://proxy.example.com:8080)
--proxy-auth <PROXY_AUTH> Proxy authentication credentials (format: username:password)
--insecure Skip SSL certificate verification (accept self-signed certs)
--random-agent Use a random User-Agent for HTTP requests
-H, --header <NAME: VALUE> Extra request header, repeatable; sent only on requests urx makes to the target, never to an archive
--cookie Cookie header for requests to the target; shorthand for -H "Cookie: ..."
--user-agent User-Agent for requests to the target, overriding the default and --random-agent
--timeout Request timeout in seconds [default: 120]
--retries Number of retries for failed requests [default: 2]
--parallel Maximum domains fetched concurrently per provider (and concurrent URL tests); a provider's --rate-limit is shared across them [default: 5]
--rate-limit <RATE_LIMIT> Rate limit (requests per second)
--rate-limit-by Per-provider rate overrides (e.g. vt=1,wayback=10); falls back to --rate-limit for unlisted providers
--max-time <MAX_TIME> Global ceiling on provider enumeration time in seconds (0 = unlimited) [default: 0]
Testing Options:
--check-status
Check HTTP status code of collected URLs [aliases: ----cs]
--check-title
Also record each response's HTML while checking statuses; implies --check-status
--include-status <INCLUDE_STATUS>
Include URLs with specific HTTP status codes or patterns (e.g., --is=200,30x) [aliases: ----is]
--exclude-status <EXCLUDE_STATUS>
Exclude URLs with specific HTTP status codes or patterns (e.g., --es=404,50x,5xx) [aliases: ----es]
--extract-links
Extract additional links from collected URLs (requires HTTP requests)
--extract-js-endpoints
Fetch collected JavaScript files and extract the endpoint paths and URLs found in their string literals (requires HTTP requests); with --archive-body this also mines the archived copy of each script
--max-js-files
Maximum number of files --extract-js-endpoints will fetch (0 = unlimited) [default: 500]
--archive-body
Fetch the archived body of each collected URL from the Wayback Machine and extract the links inside it (works for pages that no longer exist)
--archive-body-limit
Maximum number of archived bodies --archive-body fetches per run; bounds distinct bodies, not URLs [default: 500]
--archive-body-dir
Keep every body --archive-body replays in DIR, with an index.jsonl mapping each file back to its URL, capture and content type
--expand-specs
Fetch the API specification documents among the collected URLs (OpenAPI, Swagger, GraphQL introspection; JSON or YAML) and expand every route they document into a URL. See "Expanding API Specifications" below
--max-spec-files
Maximum number of specification documents --expand-specs will fetch (0 = unlimited) [default: 50]
Cache Options:
--incremental Enable incremental scanning mode (only return new URLs compared to previous scans)
--cache-type Cache backend: sqlite or redis [default: sqlite]
--cache-path Path for the SQLite cache database
--redis-url Redis connection URL for remote caching
--cache-ttl Cache time-to-live in seconds [default: 86400]
--no-cache Disable caching entirely
Notification Options:
--notify POST a run summary to this webhook when the run ends (repeatable; also URX_NOTIFY_URL, provider-config notify_url, or [notify].url)
--notify-on <NOTIFY_ON> When to send: new (only if URLs were emitted), always, or never [default: new]
--notify-format <NOTIFY_FORMAT> Payload shape: json (urx summary), slack ({"text"}), or discord ({"content"}) [default: json]
`--extract-links` lê todas as tags que contêm URLs, não apenas âncoras: `<a href>`,
`<script src>`, `<link href>`, `<form action>`, ``, ``,
`<source src>`, `<object data>`, `<embed src>`, e alvos de `<meta http-equiv="refresh">`.
URLs relativos são resolvidos em relação à página (respeitando `<base href>`),
duplicados são eliminados, e os links descobertos passam pelos mesmos filtros
e validação de host que o resto da execução. Consulte
[docs/content/guide/cli-options.md](https://github.com/hahwul/urx/blob/main/docs/content/guide/cli-options.md) para a
tabela completa.
`--extract-js-endpoints` vai um passo mais longe e lê o próprio JavaScript:
cada URL recolhido que pareça ser um script é obtido e os seus
literais de string são explorados em busca dos caminhos e URLs que a aplicação chama —
`fetch("/api/v2/users")`, `axios.post("/graphql")`, o prefixo estático de
`` `/api/orders/${id}` ``. Estes são os endpoints que nunca aparecem no HTML.
A saída é agressivamente desruidificada (tipos MIME, especificadores de módulo, base64,
valores CSS, fragmentos de regex e mais são descartados), cada corpo é limitado a
10 MiB, o número de ficheiros obtidos é limitado por `--max-js-files`, e os
endpoints descobertos passam pelos mesmos filtros e validação de host que tudo o
resto. A política completa de extração e supressão de ruído está em
[docs/content/guide/cli-options.md](https://github.com/hahwul/urx/blob/main/docs/content/guide/cli-options.md#javascript-endpoint-extraction).
`--archive-body` faz a mesma extração sobre os corpos que a Wayback Machine
*armazenou* em vez de sobre o site em direto, pelo que uma página que foi eliminada há anos
ainda produz os links que continha. Consulte
[Mining Archived Response Bodies](#mining-archived-response-bodies).
### Exemplos```bash
# Save results to a file
urx example.com -o results.txt
# Output in JSON format
urx example.com -f json -o results.json
# Filter for JavaScript files only
urx example.com -e js
# Exclude HTML and text files
urx example.com --exclude-extensions html,txt
# Filter for API endpoints
urx example.com --patterns api,v1,graphql
# Exclude specific patterns
urx example.com --exclude-patterns static,images
# Use Fileter Preset (similar to --exclude-extensions=png,jpg,.....)
urx example.com -p no-images
# Use specific providers
urx example.com --providers wayback,otx
# Add the keyless Arquivo.pt (Portuguese web archive) provider
urx example.com --providers wayback,cc,otx,arquivo
# Query another CDX index server alongside the defaults (id: cdx:vefsafn.is)
urx example.is --cdx-endpoint https://vefsafn.is/cdx
# ...or on its own, rate-limited, with the archive-side filters it shares with wayback/cc
urx example.is --cdx-endpoint https://vefsafn.is/cdx --providers cdx:vefsafn.is \
--rate-limit-by cdx:vefsafn.is=1 --from 2020 --archive-status 200
# URLScan works without a key (anonymous, rate-limited); a key just raises limits
urx example.com --providers urlscan
# BeVigil: endpoints pulled out of unpacked Android apps (key required; auto-enables the provider)
URX_BEVIGIL_API_KEY=*** urx example.com
# Using VirusTotal and URLScan providers
# 1. Explicitly add to providers (with API keys via command line)
urx example.com --providers=vt,urlscan --vt-api-key=*** --urlscan-api-key=***
# 2. Using environment variables for API keys
URX_VT_API_KEY=*** URX_URLSCAN_API_KEY=*** urx example.com --providers=vt,urlscan
# 3. Auto-enabling: providers are automatically added when API keys are provided
urx example.com --vt-api-key=*** --urlscan-api-key=*** # No need to specify in --providers
# 4. Multiple API key rotation (to mitigate rate limits)
# Using repeated flags for multiple keys
urx example.com --vt-api-key=key1 --vt-api-key=key2 --vt-api-key=key3
# Using environment variables with comma-separated keys
URX_VT_API_KEY=key1,key2,key3 URX_URLSCAN_API_KEY=ukey1,ukey2 urx example.com
# Combining CLI flags and environment variables (CLI keys are used first)
URX_VT_API_KEY=env_key1,env_key2 urx example.com --vt-api-key=cli_key1 --vt-api-key=cli_key2
# URLs from robots.txt and sitemap.xml are included by default
# Exclude URLs from robots.txt files
urx example.com --exclude-robots
# Exclude URLs from sitemap
urx example.com --exclude-sitemap
# Also read every archived version of robots.txt and sitemap.xml, so paths the
# site once listed and has since removed come back
urx example.com --archived-discovery
# Only the versions captured in a given era
urx example.com --archived-discovery --from 2014 --to 2016 --exclude-sitemap
# Include subdomains
urx example.com --subs
# Check status of collected URLs
urx example.com --check-status
# Read URLs directly from a text file
urx --files urls.txt
# Combine file input with filtering
urx --files urls.txt --patterns api,admin -f json
# Extract additional links from collected URLs
# (anchors, scripts, stylesheets, form actions, iframes, images, media
# sources, objects, embeds, and meta-refresh targets)
urx example.com --extract-links
# Discovered links go through the same filters as everything else, so this
# keeps only the JavaScript the pages reference
urx example.com --extract-links -e js
# Read the collected JavaScript and pull out the API paths it calls
urx example.com --extract-js-endpoints --patterns api
# Chain them: collect the site's bundles, then mine those for endpoints
urx example.com --extract-links --extract-js-endpoints --max-js-files 100
# Mine the links inside the *archived* bodies instead — dead pages included.
# One request per distinct body; the limit bounds bodies, not URLs
urx example.com --archive-body --archive-body-limit 200 --rate-limit 5
# Network configuration
urx example.com --proxy http://localhost:8080 --timeout 60 --parallel 10 --insecure
# Advanced filtering
urx example.com -e js,php --patterns admin,login --exclude-patterns logout,static --min-length 20
# HTTP Status code based filtering (live requests: urx re-fetches each URL)
urx example.com --include-status 200,30x,405 --exclude-status 20x
# Archive-side filtering (free: the CDX index already knows these)
# Skip everything the archive recorded as a 404 — no extra requests
urx example.com --archive-exclude-status 404
# Only captures the archive served as JSON — finds extensionless API endpoints
urx example.com --archive-mime application/json
# Drop HTML to leave assets and endpoints behind
urx example.com --archive-exclude-mime text/html
# Restrict the crawl window across wayback, cc, arquivo, and any --cdx-endpoint alike
urx example.com --from 2023 --to 2024
# Disable host validation
urx example.com --strict false
# URL normalization and deduplication
# Normalize URLs by sorting query parameters and removing trailing slashes
urx example.com --normalize-url
# Combine normalization with endpoint merging for comprehensive deduplication
urx example.com --normalize-url --merge-endpoint
# URL normalization with file input
urx --files urls.txt --normalize-url
# Collapse /post/1, /post/2, /post/99999 ... into a single representative line
urx example.com --dedup-similar
# Regular-expression filtering (repeat either flag; they are never comma-split)
urx example.com --match-regex '/api/v[0-9]+/'
urx example.com --match-regex '\.php$' --match-regex '\.aspx$'
urx example.com --filter-regex '/(assets|static)/'
# Regexes are case-sensitive; ask for insensitivity explicitly
urx example.com --match-regex '(?i)admin'
# Security presets: match by path shape as well as by extension
urx example.com -p only-secrets # /.env, /.git/config, id_rsa, *.pem
urx example.com -p only-backup # *.bak, *.sql, /backup/, index.php~
urx example.com -p only-config # *.yaml, web.config, .htaccess, Dockerfile
urx example.com -p only-api # /api/, /v1/, /graphql, /swagger, *.wsdl
# Scope files: a bug bounty program's own host list, used verbatim
urx example.com --subs --scope-file scope.txt
# Metadata filters, applied after collection so every provider is covered
urx example.com --providers wayback --meta-last-seen-after 2024 --meta-exclude-mime 'image/*'
urx example.com --providers wayback --meta-mime application/json --meta-status 200
# What parameters does this target take, and where?
urx example.com --params
urx example.com --params-by-endpoint
# One templated URL per parameter signature, straight into a fuzzer
urx example.com --fuzz-placeholder FUZZ | ffuf -w - -u FUZZ
# A target-specific wordlist instead of a URL list
urx example.com --subs -f wordlist -o words.txt
# Open the API specifications the sweep found and expand every route in them
urx example.com -p only-api --expand-specs
# Status checks also keep the response head; --check-title adds the <title>
urx example.com --check-status -f jsonl
urx example.com --check-title --show-meta
# Inspect and maintain the cache
urx cache stats
urx cache drop example.com
Delimitando uma Execução a um Caminho
Um alvo pode nomear um caminho, e significa o que diz: urx example.com/shop
coleta a parte do site sob /shop.```bash
urx example.com/shop
urx https://example.com/api/v2 # a pasted URL works too
Isto não é um filtro aplicado a posteriori. Um índice CDX responde a consultas de prefixo nativamente, por isso o urx envia `url=example.com/shop*` e o arquivo nunca envia o resto do site pela rede — num alvo grande, essa é a diferença entre algumas centenas de linhas e algumas centenas de milhares. Os fornecedores que não conseguem expressar um caminho na sua consulta (OTX, VirusTotal, urlscan, GitHub, BeVigil, ZoomEye) são questionados sobre o host e as suas respostas são restringidas posteriormente, tal como os resultados de uma execução `--subs`, onde a forma `*.host` e um prefixo de caminho não podem ser combinados numa única consulta CDX.
Âmbito significa *no ou sob* o caminho: `/shop` e `/shop/cart` estão incluídos, `/shopping` não. As maiúsculas/minúsculas são ignoradas, porque um servidor CDX converte todo o URL para minúsculas quando constrói a chave do seu índice — `example.com/Shop*` e `example.com/shop*` devolvem as mesmas linhas, todas escritas em minúsculas, por isso uma verificação sensível a maiúsculas/minúsculas descartaria tudo o que o arquivo acabou de devolver. Uma query string ou fragmento no alvo é descartada — esses restringem um pedido, não um âmbito.
> Nota: o urx costumava descartar o caminho de um alvo, por isso
> `urx https://example.com/shop` analisava todo o `example.com`. Agora
> analisa `/shop`. Passe apenas o host para o comportamento antigo; uma execução cujo alvo
> contém um caminho indica-o no stderr.
### Filtragem por Expressão Regular
`--patterns` / `--exclude-patterns` são testes simples de subcadeia: ambos os lados são convertidos para minúsculas, e cada metacaractere é literal. `--match-regex` / `--filter-regex` são as contrapartes regex, e diferem em três aspetos que vale a pena recordar:
| | `--patterns` | `--match-regex` |
|---|---|---|
| Correspondência | subcadeia | [sintaxe regex](https://docs.rs/regex/latest/regex/#syntax) completa |
| Maiúsculas/minúsculas | insensível (ambos os lados em minúsculas) | **sensível** — use `(?i)` para desativar |
| Múltiplos valores | uma flag separada por vírgulas | repita a flag; as vírgulas nunca são divididas |
Ambas as flags regex são avaliadas contra a **cadeia de URL completa** tal como recolhida (esquema, host, caminho e query), por isso `^https://` e `\.js$` funcionam ambos. A exclusão prevalece: um URL que corresponda a `--filter-regex` é descartado mesmo que `--match-regex` também tenha correspondido. Uma expressão malformada faz falhar a execução no arranque, antes de qualquer arquivo ser consultado.
### Ficheiros de Âmbito
O âmbito de um programa de bug bounty é uma lista de hosts, e todas as plataformas a escrevem da mesma forma. `--scope-file` recebe essa lista literalmente em vez de o obrigar a traduzi-la manualmente para alternâncias regex ancoradas — onde errar a ancoragem silenciosamente *amplia* o âmbito em vez de falhar.```text
# scope.txt — in scope
*.example.com
api.example.org
# out of scope, even though the wildcard above covers them
!admin.example.com
!*.internal.example.com
Instalação
Instalação rápida (recomendada)
# Clone o repositório
git clone https://github.com/yourusername/kitploit.git
cd kitploit
# Instale as dependências
pip install -r requirements.txt
# Execute a ferramenta
python kitploit.py --help
Instalação via pip
pip install kitploit
Instalação via Docker
docker pull kitploit/kitploit:latest
docker run -it --rm kitploit/kitploit:latest --help
Uso
Uso básico
# Exibir ajuda
kitploit --help
# Executar uma verificação básica
kitploit scan --target example.com
# Especificar um arquivo de saída
kitploit scan --target example.com --output results.json
Opções avançadas
# Ativar modo detalhado
kitploit scan --target example.com --verbose
# Definir nível de threads
kitploit scan --target example.com --threads 10
# Usar um arquivo de configuração personalizado
kitploit scan --config /path/to/config.yaml
Exemplos
# Verificar vários alvos
kitploit scan --targets targets.txt
# Exportar resultados em formato CSV
kitploit scan --target example.com --format csv --output results.csv
# Executar apenas módulos específicos
kitploit scan --target example.com --modules recon,scan
Configuração
A ferramenta pode ser configurada através de um arquivo YAML ou variáveis de ambiente.
Arquivo de configuração
# config.yaml
target: example.com
threads: 5
timeout: 30
verbose: false
output:
format: json
path: results.json
modules:
- recon
- scan
- report
Variáveis de ambiente
export KITPLOIT_TARGET=example.com
export KITPLOIT_THREADS=5
export KITPLOIT_TIMEOUT=30
export KITPLOIT_VERBOSE=true
Módulos
Módulo de reconhecimento
O módulo de reconhecimento coleta informações sobre o alvo.
kitploit recon --target example.com
Módulo de varredura
O módulo de varredura procura por vulnerabilidades conhecidas.
kitploit scan --target example.com
Módulo de relatório
O módulo de relatório gera relatórios detalhados.
kitploit report --input results.json --output report.html
Solução de problemas
Erro de permissão negada
Se você encontrar um erro de permissão negada, execute a ferramenta com privilégios elevados:
sudo kitploit scan --target example.com
Erro de conexão
Verifique sua conexão de rede e certifique-se de que o alvo esteja acessível:
ping example.com
curl -I http://example.com
Dependências ausentes
Instale as dependências ausentes:
pip install -r requirements.txt
Contribuição
Contribuições são bem-vindas! Por favor, siga estas etapas:
- Faça um fork do repositório
- Crie uma branch para sua funcionalidade (
git checkout -b feature/nova-funcionalidade)
- Faça commit das suas alterações (
git commit -am 'Adiciona nova funcionalidade')
- Faça push para a branch (
git push origin feature/nova-funcionalidade)
- Abra um Pull Request
Licença
Este projeto está licenciado sob a Licença MIT - consulte o arquivo LICENSE para mais detalhes.
Aviso legal
Esta ferramenta é destinada apenas para testes de segurança autorizados e fins educacionais. Os autores não são responsáveis por qualquer uso indevido ou danos causados por esta ferramenta. Sempre obtenha permissão por escrito antes de testar qualquer sistema que você não possua.
Agradecimentos
Contato
- Autor: Seu Nome
- Email: [email protected]
- GitHub: @yourusername```bash
urx example.com --subs --scope-file scope.txt
urx --domain-list targets.txt --subs --scope-file scope-a.txt --scope-file scope-b.txt
`*.example.com` corresponde ao apex, bem como a tudo sob ele (a
leitura de bug-bounty, que é o que a tabela de escopo de uma plataforma
significa); um host isolado corresponde exatamente a esse host; um `*` sozinho
torna o ficheiro uma lista de negação pura; as exclusões vencem sempre; `#`
inicia um comentário. Qualquer coisa que o urx não consiga honrar — uma
porta, um caminho, um wildcard no meio — é um erro de arranque que nomeia o
ficheiro e a linha, em vez de um escopo silenciosamente mais amplo. O filtro
aplica-se a todos os fornecedores e aos links extraídos, e combina-se com
`--strict` em vez de o substituir, pelo que uma linha de escopo
`*.example.com` continua a precisar de `--subs`.
### Filtros de Metadados de Arquivo
`--from`/`--to` e os predicados `--archive-*` são empurrados para a consulta
do próprio arquivo, o que os torna gratuitos e também os limita a
fornecedores com suporte CDX — e os dois dialetos CDX divergem o suficiente
para que uma lista positiva com múltiplos valores
(`--archive-status 200,301`) seja insatisfazível em servidores pywb. Os oito
filtros `--meta-*` são executados *após* a recolha, sobre um único conjunto
unificado de metadados de captura por URL, pelo que se aplicam a todos os
fornecedores de forma uniforme.```bash
# Endpoints still being captured recently, with HTML and images out of the way
urx example.com --providers wayback --meta-last-seen-after 2024 --meta-exclude-mime 'text/html,image/*'
# Pages that died: nothing captured since 2019
urx example.com --providers wayback --meta-last-seen-before 2019
# JSON the archive served successfully
urx example.com --providers wayback --meta-mime application/json --meta-status 200
# First archived during 2020 (partial dates pad to the start / end of the period)
urx example.com --providers wayback --meta-first-seen-after 2020 --meta-first-seen-before 2020
URLs que não carregam metadados — os provedores não-CDX, a entrada --files, acertos de cache — são divididos pela direção do predicado: um predicado positivo não pode ser satisfeito por um valor ausente, então a URL é descartada; uma exclusão descarta apenas o que corresponde positivamente, então ela sobrevive. --verbose relata a divisão, e quando metadados ausentes respondem por todo o conjunto de resultados o urx informa isso mesmo sem -v, porque um acerto de cache de outra forma faz uma execução vazia parecer um alvo sem nada a encontrar.
Colapsando Quase-duplicatas
Um arquivo retornará alegremente /post/1 até /post/99999. Eles são um endpoint, e --dedup-similar imprime uma linha para eles. Um segmento de caminho é tratado como dado — não como parte da rota — quando é inteiramente um dos seguintes:
- uma sequência de dígitos (
/post/1, /page/42)
- um UUID (
/u/550e8400-e29b-41d4-a716-446655440000)
- um digest hex de 32/40/64 caracteres (md5, sha1, sha256)
- uma data separada (
/blog/2024-01-02/)
- um token longo de maiúsculas e minúsculas misturadas com dígitos nele (ids de sessão, blobs assinados)
Segmentos que meramente contêm dígitos permanecem, então /api/v1/ e /api/v2/ ainda são dois endpoints, e um slug em minúsculas é prosa em vez de um token. Strings de consulta são agrupadas apenas por nomes de parâmetros: ?q=cats&page=1 e ?q=dogs&page=7 colapsam, enquanto ?q=cats sozinho não — descartar um parâmetro altera a requisição.
O sobrevivente de cada grupo é sua URL lexicograficamente menor, então duas execuções sobre os mesmos dados imprimem a mesma coisa. --verbose relata quantas URLs foram colapsadas. A opção é independente de --normalize-url e --merge-endpoint e combina com qualquer uma delas; todas as três precisam do conjunto de resultados completo, então nenhuma delas funciona com --stream.
Visões de Parâmetros e Fuzz
--show-only-param apenas corta a string de consulta de cada URL, o que não consegue responder à primeira pergunta que um testador faz: quais parâmetros este alvo aceita? Três visões respondem a isso, construídas sobre o mesmo agrupamento que --dedup-similar usa.```console
$ urx example.com --params
page
q
ref
sort
utm_source
$ urx example.com --params-by-endpoint
https://example.com/post/{id} ref,utm_source
https://example.com/search page,q,sort
$ urx example.com --fuzz-placeholder FUZZ
https://example.com/post/1?ref=FUZZ
https://example.com/post/2?utm_source=FUZZ
https://example.com/search?q=FUZZ&page=FUZZ
https://example.com/search?q=FUZZ&sort=FUZZ
`--params-by-endpoint` colapsa segmentos de caminho com aparência de id para `{id}` exatamente como
`--dedup-similar` faz, e escreve o endpoint por extenso porque o urx
costuma escanear vários hosts em uma única execução. `--fuzz-placeholder` mantém uma URL por
assinatura de parâmetro e mantém seu caminho real — um `{id}` não rotearia — então
a saída alimenta diretamente um fuzzer:```bash
urx example.com --fuzz-placeholder FUZZ | ffuf -w - -u FUZZ
urx example.com --fuzz-placeholder FUZZ | dalfox pipe
Todos os três precisam do conjunto completo de resultados, portanto são apenas em lote e mutuamente exclusivos entre si e com as visualizações --show-only-*.
Saída de Wordlist
-f wordlist transforma uma execução em uma wordlist específica para o alvo: cada segmento de caminho e nome de parâmetro de consulta que viu, deduplicado em toda a execução e ordenado, um termo por linha.```bash
urx example.com --subs -f wordlist -o words.txt
ffuf -w words.txt -u https://example.com/FUZZ
Segmentos que parecem dados em vez de nomes de rota são deixados de fora, reutilizando os
grupos de teste `--dedup-similar` — uma wordlist cheia de `4711`, UUIDs, datas e
tokens de sessão é pior do que nenhuma wordlist, já que cada uma dessas palavras existe
em exatamente um alvo. Um segmento cujo radical é um identificador também sai
(`article-1234.html`). O uso de maiúsculas e minúsculas é preservado: segmentos de caminho diferenciam maiúsculas de minúsculas na
maioria das origens, então converter `WebResource.axd` para minúsculas produziria uma palavra que retorna 404
em todos os lugares onde fosse tentada. A união tem de ser feita sobre o conjunto completo, então o
formato é apenas em lote.
### Saída em Streaming
Por padrão, o urx coleta tudo, depois filtra, ordena e imprime uma vez. Em um
alvo grande, isso significa nenhuma saída até que o arquivo mais lento termine.
`--stream` escreve cada URL no momento em que o provedor que a reporta retorna:```bash
# Matches start appearing immediately instead of after the slowest provider
urx big-target.com --stream | grep admin
# Line-delimited JSON stays valid while it is still being written
urx big-target.com --stream -f jsonl | jq -r 'select(.url | test("/api/")) | .url'
URLs transmitidas passam exatamente pelos mesmos filtros que uma execução em lote e ainda são
deduplicadas. Duas coisas diferem:
- Ordem. Os resultados chegam na ordem de conclusão do provedor, portanto a saída não é
ordenada. Canalize por
sort se precisar de ordenação.
- Escopo. Opções que precisam do conjunto completo de resultados são rejeitadas de imediato
(com uma mensagem nomeando cada uma):
--merge-endpoint, --dedup-similar,
--check-status /
--include-status / --exclude-status, --extract-links,
--extract-js-endpoints, --archive-body, --expand-specs,
--incremental, --show-sources, --show-meta, os filtros --meta-*,
--params, --params-by-endpoint, --fuzz-placeholder, --output-dir e
--files. O cache é ignorado;
--format json é recusado em favor de jsonl porque um array JSON precisa
saber qual entrada é a última, e --format wordlist porque nenhum termo pode ser conhecido
como novo até que todas as URLs tenham chegado.
Como o mapa de resultados em lote nunca é populado neste modo, uma execução transmitida
também mantém muito menos em memória — apenas o conjunto de deduplicação de URLs já gravadas.
Metadados de Captura de Arquivo
Um índice CDX registra mais do que a URL: cada captura carrega um timestamp, o
tipo MIME e o status HTTP que o arquivo viu, e um digest do corpo. O urx mantém
tudo isso, então os provedores com suporte a CDX — wayback, cc, arquivo e qualquer
--cdx-endpoint — relatam cada URL junto com:
Campo Significado first_seenTimestamp da captura mais antiga, formato CDX de 14 dígitos (YYYYMMDDhhmmss) last_seenTimestamp da captura mais recente mimeTipo MIME da captura mais recente que registrou um archive_statusStatus HTTP que o arquivo registrou no momento da captura digestUm digest de conteúdo representativo entre as capturas
archive_status não é status: status só aparece sob --check-status,
que re-requisita a URL ao vivo agora, enquanto archive_status é o que o crawler
obteve quando capturou a página. Uma URL pode perfeitamente ter archive_status
200 e estar morta hoje.
Quando a mesma URL vem de várias capturas ou vários arquivos, os valores
são mesclados: first_seen é o timestamp mais antigo que qualquer um relatou, last_seen
o mais recente, e mime/archive_status vêm da captura mais recente que
os tinha. Provedores sem índice de captura (otx, vt, urlscan, zoomeye,
github, bevigil, robots, sitemap e entrada --files) relatam apenas a URL
— nenhum valor é inventado para eles.
Como os metadados aparecem depende do formato:
json / jsonl — cada campo aparece como uma chave quando tem um valor e é
omitido inteiramente quando não tem, exatamente como sources.
csv — uma coluna é adicionada apenas quando pelo menos uma linha tem um valor para ela,
então uma execução sem metadados ainda produz uma única coluna url.
- texto simples — inalterado por padrão, uma URL nua por linha, para que os pipelines
existentes continuem funcionando. Passe
--show-meta para anexar os campos.```bash
Rich records: when the URL was alive, and what it served
urx example.com --providers wayback -f jsonl
{"url":"https://example.com/old.php","first_seen":"20040112093000",
"last_seen":"20180722140311","mime":"text/html","archive_status":"200",
"digest":"HT2DYGA5UKZCPBSFVCV3JOBXGW2G5UUA"}
Triage by age: everything last captured before 2010
urx example.com -f jsonl | jq -r 'select(.last_seen < "20100101000000") | .url'
Opt plain output into the metadata
urx example.com --providers wayback --show-meta
Streaming (`--stream`) reporta apenas URLs. Uma URL é impressa na primeira aparição,
antes que as capturas que ampliariam seu intervalo `first_seen`/`last_seen` tenham
chegado, então `--show-meta` é rejeitado ali pelo mesmo motivo
que `--show-sources`.
Um acerto de cache também não carrega metadados: o cache armazena URLs, então um domínio servido
do cache reporta suas URLs sem campos de captura. Use `--no-cache` (ou aguarde
o TTL) para uma execução que os repovoe.
### Metadados de Resposta ao Vivo
`--check-status` já envia uma requisição e aguarda o cabeçalho de resposta, então
o que esse cabeçalho carrega vem de graça: `Location`, `Content-Length` e
`Content-Type` são registrados junto com o código de status. Redirecionamentos ainda nunca são
seguidos, então um status reportado sempre pertence à URL que foi solicitada e
`location` simplesmente diz para onde o 3xx apontou.
`--check-title` adiciona o `<title>` do HTML. É o único campo que não é gratuito —
um título precisa do corpo da resposta — então fica atrás de sua própria flag. A leitura é
limitada duas vezes (no máximo 64 KiB, e para na tag de fechamento) e ignorada
inteiramente para um corpo que o servidor declarou como não-HTML, então uma API JSON ou uma imagem
não custa nada. O título tem espaços em branco colapsados, entidades decodificadas e é cortado em 200
caracteres. `--check-title` implica `--check-status`.```bash
urx example.com --check-status -f jsonl
urx example.com --check-title --show-meta
urx example.com --check-status --is 30x -f jsonl | jq -r '.url + " -> " + .location'
A exposição segue a regra que os metadados do arquivo já definiram: json/jsonl/csv
sempre carregam os campos (chaves ausentes são omitidas, e as colunas CSV são
anexadas após as existentes), enquanto o texto simples permanece uma URL nua por linha
a menos que --show-meta solicite o contrário. Na saída simples, o título é citado, já que
é o único valor que rotineiramente contém espaços.
Requisições Autenticadas e Personalizadas
--check-status, --extract-links, --extract-js-endpoints e
--expand-specs todos refazem a requisição das URLs coletadas a partir do próprio alvo. -H
fornece a essas requisições quaisquer cabeçalhos de que precisem:```bash
urx example.com --check-status -H "Authorization: Bearer $TOKEN"
urx example.com --extract-links --cookie "session=abc; role=admin"
urx example.com --check-status --user-agent "acme-security-scan/1.0"
`-H` é repetível, aceita `Name: value`, e um malformado interrompe a execução
em vez de passar despercebido — um argumento que é silenciosamente descartado deixa
uma varredura anónima a ser lida como autenticada. `--cookie` e
`--user-agent` são atalhos para os cabeçalhos correspondentes.
**Estes cabeçalhos nunca chegam a um arquivo.** São enviados apenas pelos componentes
que comunicam com o alvo: os quatro testadores acima, mais os fornecedores `robots` e
`sitemap`, que também obtêm do alvo. Todos os outros fornecedores
consultam web.archive.org, index.commoncrawl.org ou uma API de terceiros, e o mesmo faz
`--archive-body` quando reproduz uma captura; entregar-lhes o cookie de sessão do alvo
enviaria uma credencial para um serviço que guarda o que
recebe, sem qualquer ganho. As consultas de arquivo mantêm o User-Agent próprio do urx, que
`--random-agent` ainda roda.
### Extração de Corpos de Resposta Arquivados
`--extract-links` obtém todos os URLs recolhidos do site em direto, que é
exatamente o local errado para procurar as páginas que mais interessam a uma varredura OSINT:
as que já não existem. `--archive-body` obtém os corpos que a Wayback
Machine armazenou. Para cada URL recolhido que tenha um timestamp de captura, o urx reproduz essa captura na sua forma bruta
(`https://web.archive.org/web/<timestamp>id_/<url>` — o sinalizador `id_` desativa a barra de ferramentas do Wayback e a reescrita de links, pelo que o corpo são os bytes originais) e
executa a mesma extração de links que `--extract-links` usa sobre ele.```bash
# Links from the archived bodies of everything the CDX providers found
urx example.com --archive-body
# Bound the run and pace it; the archive is one host no matter how many URLs
urx example.com --archive-body --archive-body-limit 200 --rate-limit 5
# Only the JavaScript those pages referenced back then
urx example.com --archive-body -e js
Por que isto precisa de muito menos requisições do que o waymore. Cada linha do CDX carrega um digest de conteúdo, e duas capturas com o mesmo digest são byte a byte o mesmo corpo. Os arquivos estão cheios deles: cada variante ?utm_source= de uma página, cada /index.html ao lado do seu /, cada permutação de parâmetro de rastreamento serve bytes idênticos, então uma lista de dezenas de milhares de URLs rotineiramente colapsa para alguns milhares de corpos distintos. O waymore não tem noção disto — ele baixa uma resposta por URL e lida com o volume através de um limite bruto -l 5000, que tanto martela o arquivo quanto trunca a cobertura. O urx reivindica cada digest na primeira vez que é visto e pula cada URL posterior que reproduziria os mesmos bytes, então a mesma cobertura custa uma requisição por corpo distinto. --archive-body-limit (padrão 500) limita corpos distintos, não URLs; duplicatas nunca contam contra ele, e --verbose reporta quantas foram puladas.
Mineração de JavaScript arquivado. A superfície de API de um app moderno vive em seus bundles como literais de string, e --extract-js-endpoints os busca do site ao vivo — onde eles frequentemente já não existem. Bundles são nomeados por hash de build, então app.a3f9c2.js retorna 404 no momento em que o site é reimplantado, e os endpoints que ele nomeava vão junto. Execute as duas flags juntas e o urx minera a cópia arquivada em vez disso, e os blocos <script> inline de uma página arquivada junto com seus links:```bash
urx example.com --archive-body --extract-js-endpoints
**Mantendo os corpos.** Os pedidos já estão a ser feitos, por isso escrever os corpos para o disco não custa nada extra e responde às perguntas que nenhum extrator de links faz: o comentário `<!-- staging.internal -->`, o token que uma build de 2019 incorporou, o stack trace que nomeia uma versão de framework.```bash
urx example.com --archive-body --archive-body-dir ./corpus
grep -ri "api[_-]key" ./corpus
Cada arquivo é nomeado a partir da sua URL mais um hash dela, e corpus/index.jsonl
mapeia cada arquivo de volta para a sua URL, timestamp de captura, digest e tipo de conteúdo.
Apenas corpos do tipo texto são armazenados — HTML, script, JSON, XML, CSS, texto simples —
para que o diretório não se encha com as imagens e fontes do site. Como a
busca é deduplicada por digest, o corpus cobre muito mais do alvo por
requisição do que uma resposta por URL cobriria.
Detalhes que vale a pena saber:
- Apenas URLs com um timestamp de captura se qualificam. Os provedores CDX (
wayback,
cc, arquivo) fornecem um; a entrada --files, provedores não-CDX e resultados
em cache (o cache armazena apenas URLs) não têm nenhum. O urx avisa quando não há
nada para reproduzir — passe --no-cache para obter capturas novas.
- A captura mais recente de cada URL é reproduzida. Um timestamp reportado por outro
arquivo cai na captura Wayback mais próxima; uma URL que a Wayback Machine nunca
viu responde 404 e é ignorada. Capturas que o arquivo registrou como erros não
são mineradas, exatamente como
--extract-links ignora páginas de erro ao vivo.
- Os links descobertos passam pelos mesmos filtros, validação de host e transformações
de saída que todo o resto, e cada corpo é limitado a 10 MiB.
--rate-limit, --rate-limit-by wayback=N, --parallel, --proxy,
--timeout e --retries aplicam-se a todas as requisições de reprodução.
- Incompatível com
--stream, como toda opção que executa após a coleta.
Expandindo Especificações de API
Uma varredura -p only-api encontra /swagger.json, /openapi.yaml e /v3/api-docs
e então nunca os abre: --extract-links analisa HTML, --extract-js-endpoints
descarta corpos application/json, e --archive-body executa o analisador de HTML sobre
o que quer que o arquivo retorne. --expand-specs os lê e expande cada rota
que eles descrevem para o conjunto de resultados — uma requisição compra toda a
superfície documentada, exata e já parametrizada.```bash
urx example.com -p only-api --expand-specs
urx example.com --expand-specs --max-spec-files 10 --rate-limit 2
Recover an API the live host no longer serves: read the archived document
urx example.com --archive-body --expand-specs
O que é expandido:
* **OpenAPI 3.x** — `servers[].url` (absoluto, relativo ao documento e com template,
com `{var}` resolvido a partir de `variables[var].default` ou do primeiro valor de `enum`)
cruzado com cada chave de `paths`; os `servers` próprios de um path item sobrepõem-se aos
do documento.
* **Swagger 2.0** — `schemes` × `host` + `basePath`, com cada parte a recorrer à
parte correspondente do próprio URL do documento. `ws`/`wss` são descartados.
* **Introspeção GraphQL** — um URL por campo de query, mutation e subscription,
escrito como o endpoint mais `?query=…`. Um schema guardado como ficheiro
resolve para o seu endpoint (`/graphql/schema.json` → `/graphql`).
JSON e YAML são ambos lidos. Os alvos são escolhidos primeiro por nome e sem custo (uma
substring marcadora de spec — `swagger`, `openapi`, `api-docs`, `graphql`,
`introspection` — mais uma extensão `json`/`yaml`/`yml` quando existe, pelo que
`swagger-ui.html` não custa nenhum pedido), depois pelo `Content-Type` da resposta. Os
templates de caminho são emitidos tal como o documento os escreve (`/users/{id}`, não
`/users/%7Bid%7D`). Os corpos são limitados a 10 MiB, e um documento YAML com mais
de 32 referências de alias é recusado antes da análise para excluir bombas de expansão.
`--max-spec-files` (predefinição 50) limita os documentos obtidos. Com
`--archive-body` também ativo, uma especificação arquivada é lida como uma sem custo
extra de pedido — o corpo já estava a ser obtido.
### robots.txt e sitemap.xml arquivados
Os providers `robots` e `sitemap` leem os ficheiros *em direto*, que apenas dizem o que
um site esconde ou lista hoje. `--archived-discovery` também lê todas as versões
distintas desses ficheiros que a Wayback Machine armazenou. Um `Disallow:` de 2015
nomeia caminhos que o site deixou de mencionar — muitas vezes porque se destinavam a ser
esquecidos, não porque desapareceram — e um sitemap antigo lista
tudo o que o site outrora queria que fosse rastreado.```bash
# Every archived version of robots.txt and sitemap.xml, alongside the live ones
urx example.com --archived-discovery
# Bound it and pace it; both archived providers answer to --rate-limit-by
urx example.com --archived-discovery --archived-discovery-limit 20 --rate-limit-by robots=2,sitemap=2
# Only the versions captured in a given era
urx example.com --archived-discovery --from 2014 --to 2016
Como funciona, e por que é barato:
- As versões de um documento são listadas com uma consulta CDX por arquivo
(
robots.txt, sitemap.xml, sitemap_index.xml, sitemap.txt), usando
collapse=digest para que capturas consecutivas que serviram os mesmos bytes
se fundam em uma única linha. Apenas as linhas registradas como sucesso são
solicitadas: o índice funde www. e o apex em uma única listagem, e suas
linhas 301/200 intercaladas de outra forma derrotam o collapse — para
github.com/robots.txt isso é 325k linhas sem o filtro e 14k com ele, para as
mesmas 107 versões distintas.
- Cada versão distinta é reproduzida em forma bruta (
/web/<timestamp>id_/…) e
entregue ao mesmo parser que o arquivo ao vivo. Sem segundo parser: um
robots.txt de 2015 é lido exatamente pelas regras do atual, incluindo as
proteções de caminho absoluto e de salto de padrões. Um <sitemapindex>
arquivado é seguido em seus filhos como estavam naquele mesmo momento.
- Capturas que o arquivo registrou como erros (o robots.txt do github.com foi
um 401 durante parte de 2007) são ignoradas sem uma requisição e reportadas
apenas sob
--verbose.
--archived-discovery-limit (padrão 50) limita os documentos buscados por
domínio por cada provedor arquivado, versões mais recentes primeiro;
sitemaps aninhados contam. --verbose informa quando o limite cortou a lista.
- As variantes arquivadas rodam como suas próprias instâncias de provedor —
"Robots.txt (archived)" e "Sitemap (archived)" em
--stats e
--show-sources — mas sob os ids existentes robots / sitemap, então
--exclude-robots, --exclude-sitemap e --rate-limit-by robots=N governam
tanto as leituras ao vivo quanto as arquivadas. --from / --to restringem
quais versões são consideradas.
- Funciona com
--stream; é um provedor como qualquer outro.
Filtragem do Lado do Arquivo
--archive-status, --archive-mime, --from e --to são avaliados pelo
índice CDX do arquivo em vez de pelo urx. Duas consequências valem a pena
conhecer:
- Elas se aplicam apenas a provedores com suporte a CDX —
wayback, cc,
arquivo e qualquer --cdx-endpoint. Outros provedores as ignoram; o urx
avisa quando nenhuma está habilitada.
- Os arquivos não compartilham um único dialeto de filtro. O Wayback Machine (e
qualquer endpoint
--cdx-dialect classic) trata valores como expressões
regulares, então --archive-status "30." corresponde a qualquer 3xx. Common
Crawl, Arquivo.pt e endpoints pywb correspondem exatamente, e seu índice
faz AND de filtros repetidos — então uma lista positiva com múltiplos valores
como --archive-status 200,301 é insatisfazível ali. O urx pula esse filtro
para esses provedores (com um aviso) em vez de enviar uma consulta que
voltaria vazia. Exclusões com múltiplos valores significam "não isto e não
aquilo" e funcionam em todos os lugares.
Use --archive-status quando você quer o que o arquivo registrou no momento do
crawl e --check-status / --include-status quando você quer o status do alvo
agora; o último refaz a requisição de cada URL.
Endpoints CDX Personalizados
Todo arquivo web construído sobre pywb, OutbackCDX ou o servidor CDX do Internet
Archive expõe a mesma API de consulta. Em vez de codificar um provedor por
arquivo, --cdx-endpoint URL transforma qualquer servidor desse tipo em um
provedor na hora:```bash
The Icelandic web archive, alongside the default providers
urx example.is --cdx-endpoint https://vefsafn.is/cdx
Several at once; each gets its own progress line, stats row and rate limit
urx example.com --cdx-endpoint https://vefsafn.is/cdx --cdx-endpoint http://localhost:8080/cdx
--rate-limit-by cdx:vefsafn.is=1
* O id do provedor é `cdx:<host>` (`cdx:vefsafn.is`), que é o que
`--exclude-providers`, `--rate-limit-by`, `--stats` e `--show-sources` usam.
Nomear um endpoint o habilita; nenhuma entrada `--providers` é necessária, e
`--providers cdx:vefsafn.is` o executa sozinho. `--list-providers` mostra os
endpoints nomeados na mesma linha de comando com os ids com que serão executados.
* Tudo o que os provedores CDX integrados respeitam também se aplica aqui: `--subs`,
`--from`/`--to`, os filtros `--archive-*`, paginação, `--rate-limit` e
os metadados de captura descritos acima.
* `--cdx-dialect classic|pywb` nomeia o dialeto do servidor (nomes de campos, semântica de filtros,
formato de linha e esquema de paginação decorrem todos dele — veja
"Archive-side Filtering"). Se não for definido, o urx sonda o endpoint uma vez por execução
e recorre a `pywb`, o dialeto mais comum; defina-o explicitamente quando a
sondagem não conseguir determinar (uma resposta vazia para um domínio desconhecido, por exemplo).
* Também pode ser definido no arquivo de configuração (`cdx_endpoint = [...]`, `cdx_dialect`).
**Endpoints verificados.** No momento em que escrevo, o único endpoint público confirmado
como funcional de ponta a ponta é `https://vefsafn.is/cdx` (o arquivo web islandês da Landsbókasafn, dialeto pywb). Duas coisas a saber sobre ele: ele ignora `limit`, `page`
e `showNumPages` e retorna o conjunto completo de resultados para cada consulta, o que
o urx trata; e após algumas requisições ele pode começar a responder com uma
página de proteção contra bots no estilo Anubis ("Session Verification"). O urx detecta uma resposta HTML
no lugar de linhas CDX e a reporta como um erro de provedor nomeando o
endpoint — nunca é contada como "nenhuma URL". Se você se deparar com isso, diminua a velocidade com
`--rate-limit-by cdx:vefsafn.is=1` ou tente novamente mais tarde.
**Conhecidos por não funcionar.** O UK Web Archive (`webarchive.org.uk`), o arquivo web da Library of
Congress (`webarchive.loc.gov`), a Bibliotheca Alexandrina e a
National Library of Australia (`web.archive.org.au`) estão todos atrás de proteção contra bots
ou redirecionamentos que bloqueiam suas APIs CDX de um cliente de linha de comando.
O urx não tenta contornar isso, então apontar `--cdx-endpoint` para eles
produz o erro de resposta HTML acima.
### Caching e Varredura Incremental
O Urx suporta caching para melhorar o desempenho em varreduras repetidas e varredura incremental para descobrir apenas novas URLs.```bash
# Enable caching with SQLite (default)
urx example.com --cache-type sqlite --cache-path ~/.urx/cache.db
# Use Redis for distributed caching
urx example.com --cache-type redis --redis-url redis://localhost:6379
# Incremental scanning - only show new URLs since last scan
urx example.com --incremental
# Set cache TTL (time-to-live) to 12 hours
urx example.com --cache-ttl 43200
# Disable caching entirely
urx example.com --no-cache
# Combine incremental scanning with filters
urx example.com --incremental -e js,php --patterns api
# Configuration file with caching settings
urx -c example/config.toml example.com
Gerenciando o Cache
urx cache inspeciona e mantém o cache sem tocar no banco de dados manualmente. Todo subcomando respeita os mesmos --cache-type, --cache-path, --redis-url e --cache-ttl que um scan, e todos os cinco funcionam com ambos os backends.```bash
urx cache stats # entries, domains, URLs, age span, size, expired count
urx cache list # per-domain counts, last scan, TTL remaining
urx cache list --domain '*.example.com'
urx cache prune # delete only what --cache-ttl has expired
urx cache drop example.com # rescan one target without clearing the rest
urx cache clear --yes # delete everything
machine-readable
urx cache stats -f json | jq '.expired_entries'
A correspondência de domínios não diferencia maiúsculas de minúsculas e é **exata**, a menos que o padrão contenha
`*` — um padrão de substring predefinido teria feito com que `drop example.com` eliminasse também
`notexample.com`. `clear` pergunta antes de eliminar e recusa um
stdin não interativo em vez de assumir uma resposta, `drop` nomeia qualquer padrão
que não correspondeu a nada, consultar a cache nunca a cria, e o Redis é varrido
com `SCAN` em vez do bloqueante `KEYS` (com qualquer palavra-passe em `--redis-url`
redigida antes de ser impressa).
#### Casos de Uso de Cache```bash
# Daily monitoring - only alert on new URLs (built-in webhook, see below)
urx target.com --incremental --silent --notify https://hooks.slack.com/services/... --notify-format slack
# ...or hand the new URLs to an external notifier
urx target.com --incremental --silent | notify-tool
# Efficient domain lists processing
cat domains.txt | urx --incremental --cache-ttl 3600 > new_urls.txt
# Distributed team scanning with Redis
urx example.com --cache-type redis --redis-url redis://shared-cache:6379
# Fast re-scans during development
urx test-domain.com --cache-ttl 300 # 5-minute cache for rapid iterations
Notificações por Webhook
--notify <URL> envia via POST um resumo da execução para um webhook quando a execução termina,
o que transforma --incremental em um monitor: coloque-o no cron e o webhook
dispara apenas quando algo novo aparecer.```bash
Slack incoming webhook, only when the run finds new URLs (the default)
urx target.com --incremental --silent
--notify https://hooks.slack.com/services/T000/B000/XXXX --notify-format slack
Discord, and send even when nothing is new
urx target.com --incremental --notify "$DISCORD_HOOK" --notify-format discord --notify-on always
Several receivers, urx's own JSON schema (the default format)
urx target.com --incremental --notify https://n8n.example/hook --notify https://ntfy.example/urx
Keep the webhook out of the shell history
export URX_NOTIFY_URL=https://hooks.slack.com/services/...
urx target.com --incremental --notify-format slack
- `--notify-on` é `new` por padrão: nada é enviado quando a execução emite zero
URLs, então uma execução silenciosa do cron permanece silenciosa. `always` envia
independentemente; `never` mantém a configuração mas desativa o envio.
- `--notify-format json` (padrão) envia o esquema do urx: `domains`,
`incremental`, `url_count`, `new_url_count`, `elapsed_ms`, uma lista
`providers` por provedor (os mesmos números que `--stats` imprime), e uma
`sample` de até 20 URLs emitidas com `sample_truncated` definido quando mais
foram encontradas. `slack` envia `{"text": ...}` e `discord` envia
`{"content": ...}` com uma mensagem curta legível por humanos; mensagens mais
longas do que o serviço permite são cortadas num limite de linha e terminam
com `[truncated: N lines cut ...]`.
- A entrega nunca altera o código de saída. As URLs já estão no stdout ou em
`--output` no momento em que o webhook é chamado, então um webhook morto é um
aviso no stderr e a execução ainda termina com 0. `--verbose` mostra o status
da resposta.
- O URL do webhook é uma credencial. O urx nunca imprime mais do que o seu
esquema e host — nem em `--verbose`, nem em avisos, nem em `--stats`. Para
mantê-lo fora de uma configuração que é versionada, coloque-o em
`URX_NOTIFY_URL` ou como `notify_url` no ficheiro de configuração do
provedor; `[notify].url` na configuração principal também funciona. A
precedência é CLI/env > configuração do provedor > configuração principal.
- O pedido respeita `--proxy`, `--proxy-auth`, `--timeout` e `--insecure`.
`--network-scope` não se aplica: ele particiona o tráfego direcionado ao alvo
e aos arquivos, e o webhook é o seu próprio endpoint.
- `--silent` ainda envia (esse é o principal caso de uso); apenas oculta os
diagnósticos.
## Integração com Outras Ferramentas
O Urx funciona bem em pipelines com outras ferramentas de segurança e reconhecimento:```bash
# Find domains, then discover URLs
echo "example.com" | urx | grep "login" > potential_targets.txt
# Combine with other tools
cat domains.txt | urx --patterns api | other-tool
Inspiração
Urx foi inspirado pelo gau (GetAllUrls), uma ferramenta que busca URLs conhecidas do Open Threat Exchange da AlienVault, da Wayback Machine e do Common Crawl. Embora compartilhe funcionalidades centrais semelhantes, o Urx foi construído do zero em Rust com foco em desempenho, concorrência e capacidades de filtragem expandidas.
Contribua
Urx é um projeto de código aberto e foi feito com ❤️
se você quiser contribuir com este projeto, consulte CONTRIBUTING.md e faça um Pull-Request com seu conteúdo legal.