Bem vindos ao Blog da comunidade ITsafe



Boa Leitura


Blog em em português sobre construção . Por favor se encontrar algo que necessite correção entre em contato. Os vídeos do blog ainda estão em hebraico, mas em breve estaremos traduzindo com a mesma qualidade que traduzimos os cursos.


Injeção de código malicioso no Facebook

Neste blog, apresentarei a vocês um estudo que realizei junto com Dikla Barda. Neste estudo, fomos capazes de fazer upload de um arquivo malicioso para o CDN do Facebook manipulando o navegador e criando um Fuzzer simples que nos ajudou a contornar o Analisador de Imagens do Facebook, que excluía o código malicioso da imagem..

Neste estudo, apresentamos um método interessante pelo qual um arquivo malicioso pode ser inserido em uma imagem e armazenado no CDN do Facebook e, assim, basicamente contornar todos os mecanismos de assinatura, uma vez que o Facebook é considerado um domínio confiável, não havera nenhum bloqueio de links provenientes dele-Facebook.
Para tirar proveito da falha de segurança, tivemos que localizar e contornar uma série de fatores:

  • Falha de segurança do lado do servidor
  • Realizar manipulação e pesquisa sobre o próprio navegador
  • Contorne o intérprete de imagem que comprime as imagens novamente e reduz a imagem

Vídeo de demonstração:


Part 1

Quando você carrega uma imagem para o Facebook, a imagem é carregada para o CDN para desempenho e tempos de resposta mais rápidos, uma vez que você carrega uma imagem com uma resolução acima de 962x541, a imagem é carregada para o CDN sem parâmetros que identificam a imagem com qualquer conta. assim que é:

`` https://scontent-lhr3-1.xx.fbcdn.net/t31.0-8/14102894_1137188709676282_2198558191558447569_o.jpg`

Se a resolução for menor do que isso obteremos um link com parâmetros que não podem ser modificados:

`` https://scontent-lhr3-1.xx.fbcdn.net/t31.0-8/14102894_1137188709676282_2198558191558447569_o.jpg?_nc_cat=0&oh=2d6cfd727aa2e63c31b3a10e34872ffa&oe=5BA12209`

Nosso primeiro passo foi fazer upload de diferentes fotos no Facebook em diferentes resoluções e examiná-las. Assim que encontramos a resolução apropriada, que é acima da resolução de 962x541, passamos para a próxima etapa, a de inserção de código na imagem. Apenas para fins de demonstração:

    WshShell=new ActiveXObject("WScript.Shell");
    WshShell.Run('c:/windows/system32/calc.exe',1,false);

O resultado fica assim:
injeção de código ActiveX em uma imagem
Carregamos o arquivo no Facebook e baixamos de volta depois que passou pelo processo de conversão de imagem do Facebook pelo leitor de fotos (Image Parser).
Carregamos uma imagem no Facebook que contém o código-ActiveX
Esperávamos que pelo menos parte do código inserido permanecesse, mas o resultado foi um tanto problemático: Todo o código que inserimos na imagem foi substituído pelo intérprete de imagem que compactou a imagem para economizar espaço.
verificando se o código permanece na imagem e não foi excluído
Como contornar algo assim?

Primeiro tentamos pegar o arquivo compactado que passa pelo interpetre e inserir o código nele, porque um arquivo que já foi compactado usando o lado do servidor do Facebook não será compactado novamente na mesma extensão e mais caracteres permanecerão no arquivo.

Depois de modificar o arquivo compactado, pudemos ver pelo menos uma pequena parte do código que inserimos.

Como progredir a partir daqui?

Depois de muito pensar, ocorreu-nos escrever um fuzzer que usa uma API gráfica que executa as seguintes etapas:

    1. Define um local no arquivo e insere nosso código nele.
    1. Carrega imagem para-Facebook.
    1. Baixa a imagem de volta depois de compactada.
    1. Verifica se nosso código está na imagem.
    1. Se o código não for encontrado movemos um byte para a direita ou para a esquerda de acordo com o melhor resultado.
    1. Paramos após 50 tentativas para diagnosticar os resultados e atualizar o-fuzzer.

Abaixo está a principal função do código escrito:

                                                ``
def payload_check():
    # Send Picture to Facebook
    r = requests.post("https://graph.facebook.com/v2.7/me/photos?access_FBToken={}&caption={}&url={}".format(FBToken,message,URLToImage))

    # Get the Picture Back
    r = requests.get('https://graph.facebook.com/v2.7/me/posts?access_FBToken={}&debug=all&fields=message,object_id,type&format=json&limit=1&method=get&pretty=0&suppress_http_code=1&with="{}"'.format(FBToken,message))
    image_code = json.loads(r.text)["data"][0]["object_id"]

    r = requests.get('https://graph.facebook.com/v2.7/{}/picture?access_FBToken={}&debug=all&format=json&method=get&pretty=0&redirect=false&suppress_http_code=1'.format(image_code,FBToken))
    # This URL will not contain the Payload, We need the full size one :)
    # print json.loads(r.text)["data"]["url"]

    # This url may contain the Payload!
    good_url = str(json.loads(r.text)["data"]["url"]).replace("s720x720/","")
    download_file(good_url)

    # Check if we see some part of the payload to enhance the positions
    with open("image.jpg","r") as f:
        if half_payload in f.read():
            print "[+] Found! Values:"
            print "Counter1: {}, Counter2: {}, Cursor: {}, half_payload: {}, Index: {}".format(counter1, counter2, cursor, half_payload, index)
            return True

        else:
            return False` 
                                            

Observe que a API Graph retorna uma imagem no formato s720x720, a imagem é menor, o que significa que estão faltando caracteres! Para acessar a imagem original, devemos excluir o s720x720 do URL e, em seguida, acessar a imagem.

Após a primeira execução, conseguimos encontrar um local que nos permite fazer upload de quase todo o código em sua totalidade, enquanto na segunda execução nosso Fuzzer foi capaz de encontrar um local exato que nos permite fazer upload de todo o código! No qual ficou assim:

Adicionamos alguns caracteres A antes e depois do código para localizar facilmente o código Os caracteres ‘A’ O que você vê é, na verdade, o padding que o fuzzer executou.

Então, conseguimos fazer o upload do código para uma imagem .jpg próxima ao servidor, mas isso é apenas o começo, agora temos que fazer o arquivo finalizar com a extensão .hta para que o arquivo seja executado, caso contrário, o que faríamos com ele?

Se examinarmos a resposta do servidor, parece que seu content-type (tipo de conteúdo) é image/jpeg Então, se baixarmos o arquivo, obteremos um arquivo de imagem, então precisamos encontrar uma maneira de converter o content-type para outra coisa, como application/octet-stram

As fotos são enviadas para o Facebook com o content-type que é jpg
Depois de várias tentativas, descobrimos que é possível adicionar um ponto à extensão da url para obter o content-type desejado:
Adicionar um ponto no url mudará o content-type para-octet stream
Uma vez que tenhamos conseguido controlar o tipo de conteúdo, temos que fazer a imagem ser baixada pela URL, para fazer isso vamos adicionar o parâmetro dl=1 O que indica fazer download, o que será assim:
Adicionar dl=1 Fará com que a imagem seja baixada
Voltamos para burp suite para analizar o pacote, você pode ver que o o parâmetro dl=1 Adiciona o título à URL
`` Content-Disposition: attachment`

O que indica o download do arquivo
A imagem foi baixada devido à content-dispostion que é attachment
Como o Facebook não anexou o nome do arquivo ao content-dispostion, o navegador terá que decidir qual será o nome do arquivo que pretende baixar do site..

Part 2

Para entender em que base o navegador conclui qual será o nome do arquivo, vamos olhar o código-fonte do projeto chromium:

`` https://cs.chromium.org/chromium/src/content/renderer/loader/web_url_loader_impl.cc`

Começaremos com a função PopulateURLResponse, que sua função é abordar as informações provenientes do servidor.

O código da função PopulateURLResponse
Esta função gerencia todas as informações recebidas e responde aos títulos de acordo, ela também determina o nome do arquivo se tivermos content-disposition nos títulos da resposta do servidor.

Se houver realmente um content-disposition, esta função chama a função GetSuggestedFileName :

O código da função GetSuggestedFileName
Na função headers->EnumerateHeader Verifiqqa se existe um nome de arquivo no content-disposition e se não existe o valor que é a segunda variável da função GetSuggestedFilename estará realmente vazio.
Se olharmos para esta função, parece que ela apenas envolve o GetSuggestedFilenameImpl:
O código da função GetSuggestedFilename Esta função verifica se content_disposition está vazio e, se estiver, entra na função GetFileNameFromURL
O código da função GetSuggestedFilenameImpl
Esta função verifica se a chamada é realmente uma chamada normal e não data:// ou about:// Em seguida, chama a-ExtractFileName
O código da função GetFileNameFromURL
Que só envolve DoExtractFileName
O código da função GetFileNameFromURL O código da função ExtractFileName
A função DoExtractFileName é assim: O código da função DoExtractFileName
Ele tenta localizar o nome do arquivo do final da URL até a última barra, mas se tivermos um ponto e vírgula ";" Portanto, o nome do arquivo é determinado da última barra até a vírgula dessa forma:
`` /filename.extension;`

Part 3

Com base nessas informações, podemos basicamente controlar o nome do arquivo que queremos selecionar pelo navegador. por exemplo:
Usando a técnica anterior e renomeando o arquivo para-facebook_password.exe
O URL ficará assim:
`` https://scontent-lhr3-1.xx.fbcdn.net/t31.0-8/14102894_1137188709676282_2198558191558447569_o.jpg/facebook_password.exe;.?dl=1`

É claro que um arquivo exe não será executado porque o cabeçalho do arquivo não corresponde ao cabeçalho PE, mas o que podemos fazer é alterar o arquivo para uma extensão .hta que executará o código javascript que inserimos no arquivo anteriormente na primeira parte.

que será assim:
Renomear arquivo para-facebook_password.hta Só nos resta copiar e enviar o link, e quem clicar no link executará nosso código armazenado nos servidores do CDN. Facebook.

Enviando o link pelo messenger do Facebook

Baixar o arquivo e clicar nele irá ativar a calculadora, pois foi isso que fizemos em nosso código:

Abrir o link executa o código

Part 4

Ao esconder o link no messenger, tentamos verificar se é possível ocultar o link no messenger de alguma forma e chegamos ao seguinte truque:

Fazemos upload da imagem que contém o código JavaScript que mostrei antes, mas desta vez fazemos upload para-Messenger:
Enviar arquivo hta em-messanger Modificaremos o tipo de conteúdo e extensão de arquivo, para o tipo de conteúdo escolhido image/svg+xml E para o nome do arquivo é selecionado novamente .hta então:

Alterar o content-type do arquivo faz ele parecer uma imagem

Vamos enviar o arquivo, e parece que nem precisamos de um link, podemos enviar uma foto regular em-Messenger:

facebook Exibe o arquivo como uma imagem

Clicando na imagem vai baixar o arquivo e renomeá-lo para .hta pois é o sufixo que escolhemos para o arquivo e desta vez ele aparece em-content-disposition:

Clicando na imagem baixa o arquivo My_Facebook_password.hta

Clicar no arquivo ativará o código e, assim, executará calculadora:

Clicar no arquivo executa o código

Compartilhe este post