Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

URL Obfuscation via userinfo + homoglyphs de barra /

ARTIGO COMPLETO:

Este repo documenta e gera um catálogo de técnicas de ofuscação de URL baseadas no componente userinfo da authority (o trecho antes do @), com foco em uma variação: usar caracteres Unicode que parecem a barra / para simular um caminho de pastas inteiramente dentro do userinfo, fazendo a URL aparentar apontar para um site conhecido enquanto resolve para outro host.

O gerador é o probe.py: ele constrói cada caso, imprime no console e escreve uma página urls.html com os links. Todos os domínios são placeholders (exemplo-malicioso.com), nunca hosts reais.


1. Anatomia da URL: o componente authority (RFC 3986 §3.2 / §3.2.1)

Referência: https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1

         userinfo         host        port
         ┌──┴───┐ ┌────────┴───────┐ ┌┴┐
 https://john.doe@www.example.com:123/forum/questions/
 └─┬─┘   └────────────┬───────────────┘└──────┬───────┘
 scheme          authority                   path

Gramática (ABNF) relevante:

; authority: parte entre "//" e o proximo "/", "?" ou "#".
; [ ... ] = opcional; so ha userinfo se existir um "@" antes do host.
authority    = [ userinfo "@" ] host [ ":" port ]

; userinfo: o que vem ANTES do "@". *( ... ) = zero ou mais dos itens abaixo.
; Aceita apenas: unreserved, pct-encoded, sub-delims e ":". Repare: "/" NAO entra.
userinfo     = *( unreserved / pct-encoded / sub-delims / ":" )

; unreserved: caracteres "seguros" (letras, digitos e - . _ ~).
; Nunca sao delimitadores e nunca precisam de escape.
unreserved   = ALPHA / DIGIT / "-" / "." / "_" / "~"

; pct-encoded: um byte escrito como "%" + 2 digitos hexadecimais.
; Ex.: %2F representa "/" como DADO, sem ele agir como delimitador.
pct-encoded  = "%" HEXDIG HEXDIG

; sub-delims (sub-delimitadores): pontuacao PERMITIDA dentro de um componente
; (userinfo, host, path...). Tem sentido especifico de cada esquema; nao
; separa um componente do outro.
sub-delims   = "!" / "$" / "&" / "'" / "(" / ")"
             / "*" / "+" / "," / ";" / "="

; gen-delims (delimitadores gerais): separam os GRANDES componentes da URI
; (scheme, authority, path, query, fragment). Sao eles que "cortam" a URL:
; o "@" encerra o userinfo e o "/" inicia o path.
gen-delims   = ":" / "/" / "?" / "#" / "[" / "]" / "@"

; reserved: o conjunto completo de caracteres com papel estrutural
; (gen-delims + sub-delims). Para virarem dado literal, precisam de pct-encoded.
reserved     = gen-delims / sub-delims

; ALPHA (A-Z a-z), DIGIT (0-9) e HEXDIG (0-9 A-F) sao regras-base do ABNF (RFC 5234).

Três fatos da especificação sustentam as técnicas:

  1. O @ delimita. Havendo um @ na authority, tudo antes dele é userinfo e o host é o que vem depois. Um humano lê da esquerda para a direita e para no primeiro domínio que reconhece; o parser lê o host depois do @.
  2. user:password é obsoleto, mas ainda é parseado (§3.2.1: "Use of the format 'user:password' in the userinfo field is deprecated."). Deprecado ≠ rejeitado; navegadores continuam aceitando.
  3. A barra / (U+002F, SOLIDUS) é um gen-delim e não faz parte do userinfo. Um / real encerra a authority e inicia o path.

A §7.6 (Semantic Attacks) da própria RFC descreve o abuso: como o userinfo aparece antes do host, dá para construir uma URI que engana o humano, parecendo apontar para uma autoridade confiável enquanto aponta para outra. Exemplo da RFC: ftp://cnn.example.com&story=breaking_news@10.0.0.1/top_story.htm.


2. As técnicas

2.1. Baseline: userinfo@host

http://www.google.com@exemplo-malicioso.com

O olho lê google.com; o parser resolve host = exemplo-malicioso.com (www.google.com é apenas um "usuário"). Limitação: assim que aparece um /, ? ou # real, a authority termina e o disfarce quebra. Por exemplo, http://www.google.com/@exemplo-malicioso.com resolve para www.google.com.

2.2. Homoglyphs de / simulando um caminho (técnica principal)

A ideia é substituir cada / por um caractere Unicode diferente que se parece com uma barra. Para o parser, esse caractere é "mais uma letra" do userinfo (não é o gen-delim U+002F, logo não encerra a authority); para o olho, é uma barra de caminho. Assim dá para montar um caminho falso plausível, inteiro dentro do userinfo, imitando uma URL real:

http://www.google.com╱mail╱u╱0╱inbox@exemplo-malicioso.com
                     ╲__________________╱
              tudo isto é userinfo (as "barras" são U+2571, não U+002F)

O usuário lê "google.com/mail/u/0/inbox" (cara de caixa de entrada) e confia, mas o host verdadeiro continua depois do @.

2.3. Outras famílias geradas pelo probe.py

Variações no mesmo componente userinfo, cobertas para comparação:

  • Bytes de controle C0 + DEL, tanto percent-encoded (%00..%1F, %7F) quanto crus.
  • Invisíveis / zero-width (NBSP, ZWSP, BOM, RLO U+202E, etc.).
  • Sinais ASCII no userinfo (`~ ' ! $ & * + , ; = ( ) [ ] { } | ^ < > " ``).
  • Ambiguidade estrutural (\@, /@, %2F@, %5C@, múltiplos @, %40, ?@, #@).
  • Letras de outros idiomas (incl. o cirílico а U+0430, homoglyph do a latino).
  • "Primas": host em IP hex/decimal, fragmento e path como isca.

3. Por que usar os Unicodes parecidos com /

O motivo é direto e decorre da regra 3 acima:

  • A barra ASCII / (U+002F) derruba o ataque. Sendo um gen-delim, ela encerra a authority: tudo após ela vira path, e o navegador vai para o host legítimo (www.google.com). Ou seja, um caminho "de verdade" com / não serve para o disfarce.
  • Os homoglyphs não são U+002F. (U+2571), (U+2044), (U+2215), (U+FF0F) e dezenas de outros são caracteres comuns, não delimitadores. O parser os mantém dentro do userinfo: a authority continua até o @.
  • Resultado: o "caminho" inteiro (╱mail╱u╱0╱inbox) fica no userinfo, o host real permanece o que está depois do @, e visualmente a URL parece um deep link para um serviço confiável.
  • Alguns são letras que gente digita. Katakana , o traço CJK 丿 e afins se misturam a textos legítimos e não chamam atenção como um "símbolo estranho", o que os torna os mais perigosos do conjunto.

Prova (parser WHATWG-alinhado, urllib.parse.urlsplit)

URL visivel : http://www.google.com╱mail╱u╱0╱inbox@exemplo-malicioso.com
  host real : exemplo-malicioso.com
  userinfo  : www.google.com╱mail╱u╱0╱inbox
  path      : ''

Contraste trocando só (U+2571) pela barra ASCII / (U+002F):

URL visivel : http://www.google.com/mail/u/0/inbox@exemplo-malicioso.com
  host real : www.google.com          ← resolve para o host legítimo
  userinfo  : None
  path      : '/mail/u/0/inbox@exemplo-malicioso.com'

Visualmente quase idênticos; para o parser, opostos.

Comportamento nos navegadores

Esses homoglyphs também não são caracteres válidos de userinfo pela ABNF estrita, mas os parsers reais (WHATWG URL) são permissivos: em vez de rejeitar, percent-encodam o caractere dentro do userinfo e seguem. A navegação vai para o host depois do @ do mesmo jeito.


4. Catálogo de homoglyphs de /

4.1. Letras/pontuação de escritas reais: barras_escritas()

Code point Char Escrita Nome Unicode
U+30CE Katakana (japonês) KATAKANA LETTER NO
U+4E3F 丿 Han (CJK) CJK IDEOGRAPH-4E3F (traço piě)
U+2F03 Han (radical Kangxi) KANGXI RADICAL SLASH
U+2CC6 Copta COPTIC CAPITAL LETTER OLD COPTIC ESH
U+1735 Filipina (Baybayin) PHILIPPINE SINGLE PUNCTUATION
U+3033 Kana (japonês) VERTICAL KANA REPEAT MARK UPPER HALF
U+1D23A 𝈺 Notação musical grega GREEK INSTRUMENTAL NOTATION SYMBOL-47

4.2. Símbolos compartilhados (script COMMON): barras_simbolos()

Code point Char Nome Unicode
U+2044 FRACTION SLASH
U+2215 DIVISION SLASH
U+27CB MATHEMATICAL RISING DIAGONAL
U+29F8 BIG SOLIDUS
U+2571 BOX DRAWINGS LIGHT DIAGONAL (usado no exemplo)
U+31D3 CJK STROKE SP
U+2041 CARET INSERTION POINT
U+FF0F FULLWIDTH SOLIDUS
U+1F67C 🙼 VERY HEAVY SOLIDUS
U+29F6 SOLIDUS WITH OVERBAR
U+2E4A DOTTED SOLIDUS
U+233F APL FUNCTIONAL SYMBOL SLASH BAR
U+2AFD DOUBLE SOLIDUS OPERATOR
U+2AFB TRIPLE SOLIDUS BINARY RELATION
U+2CFD COPTIC FRACTION ONE HALF

5. O script (probe.py)

Só depende da biblioteca padrão (os, html). A estrutura é uma função por família de técnica; cada uma gera seus casos e chama o helper emitir(valor, url), que imprime a linha e acumula um link para o HTML.

Função Conteúdo
baseline @ e user:pass@ falsos
hexa bytes de controle percent-encoded
raw os mesmos bytes, crus
invisiveis invisíveis / zero-width
estruturais ambiguidade em torno do delimitador
sinais sinais ASCII no userinfo
barras_escritas homoglyphs de / que são letras de escritas reais
barras_simbolos homoglyphs de / do script COMMON
letras_idiomas uma letra representativa de várias escritas
cousins IP hex/decimal, fragmento e path como isca

Constantes no topo: ISCA (prefixo-isca) e ALVO (host real após o @); mudá-las reaponta toda a matriz.

Os caracteres perigosos nunca são colados literais no fonte: são construídos em runtime via chr(codepoint). Um invisível ou um U+202E (RLO) literal no código poderia reordenar ou esconder o próprio fonte.


6. Como usar

python3 probe.py

Sem dependências externas. Diretório de saída: a pasta do script por padrão; sobrescreva com OUTDIR=/caminho python3 probe.py.


7. Defesa e mitigação

  • Mostrar o host de forma inequívoca: destacar o domínio registrável e esconder/realçar o userinfo.
  • Normalizar e detectar confusables (Unicode UTS #39); aplicar IDNA/Punycode; sinalizar rótulos com mistura de scripts e caracteres fora do esperado.
  • Tratar userinfo com desconfiança: muitas libs permitem desabilitar credenciais embutidas na URL.
  • Não confiar no prefixo visual: o host real é o trecho logo depois do último @ e imediatamente antes do primeiro /, ?, # real ou fim. Como a vítima não distingue um / real de um homoglyph, a defesa não pode depender só do olho.

8. Referências

👨‍💻 AUTOR

MrCl0wn


⭐ Se este projeto foi útil, considere dar uma estrela!

💡 Sugestões e feedbacks são sempre bem-vindos!

💀 Hacker Hackeia!

About

Este repo documenta e gera um catálogo de técnicas de ofuscação de URL baseadas no componente userinfo da authority (o trecho antes do @),

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages