Encontra links externos quebrados que podem ser sequestrados.

Contexto

O Broken Link Hijacking ocorre quando um site possui links para domínios externos que não existem mais ou que expiraram. Um Pentester utiliza esta ferramenta para:

  • Identificar Links de Redes Sociais: Se um site aponta para um Twitter ou canal de YouTube que foi deletado, o atacante pode criar uma conta com o mesmo nome e herdar a confiança dos usuários.
  • Prevenir Sequestro de Domínios: Se o site linka para um script (.js) em um domínio que expirou, o atacante pode comprar esse domínio e servir código malicioso diretamente no site alvo.
  • Limpeza de SEO: Do ponto de vista defensivo, ajuda a manter a integridade e a autoridade do site.

Possibilidades de Implementação

  • Web Crawling: O script percorre o HTML do site alvo buscando todas as tags <a>, <img>, <script> e <link>.
  • Validação de Status: Para cada link externo encontrado, o script faz uma requisição para verificar se o domínio ainda responde (Status 200) ou se retorna erro de DNS/Conexão (Status 404 ou erro de resolução).
  • Filtro de Domínios Externos: O script ignora links internos (do próprio site) para focar apenas em ativos de terceiros que podem ser "comprados" ou "recriados".

Código

Este módulo utiliza BeautifulSoup para extrair os links e requests para validar o status de cada um deles.

Requisitos: pip install requests beautifulsoup4

import requests
from bs4 import BeautifulSoup
from urllib.parse import urlparse

def get_external_links(url):
    """
    Extrai todos os links externos de uma página.
    """
    links = set()
    domain = urlparse(url).netloc

    try:
        response = requests.get(url, timeout=5)
        soup = BeautifulSoup(response.text, 'html.parser')

        for a_tag in soup.find_all("a", href=True):
            href = a_tag['href']
            parsed_href = urlparse(href)

            # Verifica se o link é absoluto e se o domínio é diferente do alvo
            if parsed_href.scheme and parsed_href.netloc != domain:
                links.add(href)

    except Exception as e:
        print(f"[!] Erro ao acessar a página principal: {e}")

    return links

def check_link_status(link):
    """
    Verifica se o link externo está quebrado ou acessível.
    """
    try:
        # allow_redirects=True para seguir encurtadores de URL
        response = requests.head(link, timeout=5, allow_redirects=True)

        # Se o status for 404 ou o domínio não existir, o link está quebrado
        if response.status_code >= 400:
            print(f"[!] LINK QUEBRADO ENCONTRADO: {link} (Status: {response.status_code})")
            return True
    except requests.exceptions.RequestException:
        # Erros de conexão ou DNS indicam que o domínio pode estar disponível para compra
        print(f"[!] DOMÍNIO NÃO RESOLVIDO/INEXISTENTE: {link}")
        return True

    return False

def main():
    print("=" * 60)
    print("Módulo: Broken Link Checker | Projeto: 30 Lessons in Python")
    print("=" * 60)

    target_url = "https://example.com" # Substitua pelo site alvo
    print(f"[*] Analisando links externos em: {target_url}\n")

    external_links = get_external_links(target_url)
    print(f"[*] Foram encontrados {len(external_links)} links externos. Iniciando validação...\n")

    broken_count = 0
    for link in external_links:
        if check_link_status(link):
            broken_count += 1

    print("\n" + "=" * 60)
    print(f"[*] Scan finalizado. Total de links perigosos: {broken_count}")

if __name__ == "__main__":
    main()

Observações

  • Falsos Positivos: Alguns sites bloqueiam requisições do tipo HEAD (usadas para economizar banda). Se falhar, o script deve tentar um GET completo.
  • Recursividade: Para um projeto profissional, o script poderia navegar por todas as páginas do site (crawling) em vez de analisar apenas a página inicial.
  • Riscos de Segurança: Encontrar um link para um arquivo .js quebrado é uma descoberta de Severidade Alta, pois permite o controle total do navegador do usuário (XSS via arquivo externo).