Pergunta

Eu estou trabalhando em uma página web ASP que lida com uploads de arquivos. Apenas alguns tipos de arquivos podem ser carregados, como .XLS, .xml, .csv, .txt, .pdf, .ppt, etc.

Eu tenho que decidir se um arquivo realmente tem o mesmo tipo que os shows de extensão. Em outras palavras, se um trojan.exe foi renomeado para harmless.pdf e carregado, o aplicativo deve ser capaz de descobrir que o arquivo carregado não é um arquivo .PDF.

Quais as técnicas que você usaria para analisar esses arquivos enviados? Onde posso obter a melhor informação sobre o formato desses arquivos?

Foi útil?

Solução

Uma forma seria para verificar se há certas assinaturas ou números mágicos nos arquivos. Esta página tem uma lista acessível de assinaturas de arquivo conhecidos e parece bastante até à data:

http://www.garykessler.net/library/file_sigs.html

Outras dicas

Em outras palavras, se um trojan.exe foi renomeado para harmless.pdf e enviados, o aplicativo deve ser capaz de descobrir que o arquivo carregado não é um arquivo .PDF.

Isso não é realmente um problema. Se um .exe foi carregado como um .pdf e você servido corretamente, fazer backup para a downloader como application / pdf, todo o downloader iria receber seria um PDF quebrado. Eles teriam que redigitar manualmente para .exe para ficar prejudicado.

Os problemas reais são:

  1. Alguns navegadores podem cheirar o conteúdo do arquivo e decidir que eles sabem melhor do que você sobre que tipo de arquivo é. IE é particularmente ruim nisso, tendendo a preferir para tornar o arquivo como HTML se vê quaisquer tags HTML à espreita perto do início do arquivo. Isto é particularmente inútil, pois significa script pode ser injetado em seu site, potencialmente comprometer qualquer segurança em nível de aplicativo (bolinho roubar et al). Soluções alternativas incluem sempre servindo o arquivo como um anexo usando Content-Disposition, e / ou servir arquivos a partir de um nome de host diferente, por isso não pode cross-site-script de volta para o seu site principal.

  2. arquivos PDF não são de qualquer maneira segura! Eles podem estar cheio de scripting, e tiveram falhas de segurança significativas. Exploração de um buraco no plugin do navegador leitor de PDF é atualmente um dos meios mais comuns de instalar trojans na web. E não há quase nada que você normalmente pode fazer para tentar detectar as façanhas como eles podem ser altamente ofuscado.

Obter os cabeçalhos dos tipos de arquivos "seguros" de arquivos - executáveis ??sempre têm os seus próprios tipos de cabeçalhos, e provavelmente você pode detectar aqueles. Você teria que estar familiarizado com todos os formatos que você pretende aceitar, no entanto.

Eu sei que você disse C #, mas isso talvez pudesse ser portado. Além disso, tem um arquivo XML já contém muitos descritores para tipos de arquivos comuns.

É uma biblioteca Java chamado JMimeMagic. É aqui: http://jmimemagic.sourceforge.net/

Em ** * NIX sistemas temos um utilitário chamado arquivo (1) . Tente encontrar algo semelhante para o Windows, mas o utilitário arquivo se auto foi portado.

Talvez você poderia abordar esta questão de uma direção diferente. Em vez de identificar todos os tipos de arquivos que são enviados (Excel sozinho parece ser uma bagunça para mim, porque tem vários formatos estes dias), por que não Executar todos os envios através de um vírus do scanner ? Uma grande variedade de arquivos podem conter vírus e trojans. Pode ser mais trabalho para o servidor, mas é a solução mais segura.

Então é até os usuários a identificar corretamente seus tipos de arquivo, o que parece razoável. Adicionando em um monte de código (que terá de ser testado também) apenas para checar seus usuários parece ser um grande passo. Se eu digo que é um arquivo .pdf2 você renomeá-lo para .pdf? Se este for em um ambiente corporativo, então é razoável esperar que os usuários tenham extensões corretas em seus arquivos. Eu rastrear que carregou o bem. Se é público, então a digitalização para tipos de arquivos pode valer a pena, mas eu absolutamente fazer a verificação de vírus também.

O seguinte código C ++ poderia ajudá-lo:

//-1 : File Does not Exist or no access
//0 : not an office document
//1 : (General) MS office 2007
//2 : (General) MS office older than 2007
//3 : MS office 2003 PowerPoint presentation
//4 : MS office 2003 Excel spreadsheet
//5 : MS office applications or others 
int IsOffice2007OrOlder(wchar_t * fileName)
{
    int iRet = 0;
    byte msgFormatChk2007[8]    = {0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00};     //offset 0 for office 2007 documents
    byte possibleMSOldOffice[8] = {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1};     //offset 0 for possible office 2003 documents

    byte msgFormatChkXLSPPT[4]  = {0xFD, 0xFF, 0xFF, 0xFF};     // offset 512: xls, ppt: FD FF FF FF 
    byte msgFormatChkOnlyPPT[4] = {0x00, 0x6E, 0x1E, 0xF0};     // offset 512: another ppt offset PPT   
    byte msgFormatChkOnlyDOC[4] = {0xEC, 0xA5, 0xC1, 0x00};     //offset 512: EC A5 C1 00 
    byte msgFormatChkOnlyXLS[8] = {0x09, 0x08, 0x10, 0x00, 0x00, 0x06, 0x05, 0x00};     //offset 512: XLS

    int iMsgChk = 0;
    HANDLE fileHandle = CreateFile(fileName, GENERIC_READ,
        FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL  );
    if(INVALID_HANDLE_VALUE == fileHandle) 
    { 
        return -1; 
    }

    byte buff[20];
    DWORD bytesRead;
    iMsgChk = 1;
    if(0 == ReadFile(fileHandle, buff, 8, &bytesRead, NULL )) 
    { 
        return -1; 
    }

    if(buff[0] == msgFormatChk2007[0]) 
    {
        while(buff[iMsgChk] == msgFormatChk2007[iMsgChk] && iMsgChk < 9)
            iMsgChk++;

        if(iMsgChk >= 8) {  
            iRet = 1; //office 2007 file format
        }
    } 
    else if(buff[0] == possibleMSOldOffice[0])
    {
        while(buff[iMsgChk] == possibleMSOldOffice[iMsgChk] && iMsgChk < 9)
            iMsgChk++;

        if(iMsgChk >= 8)
        {   
            //old office file format, check 512 offset further in order to filter out real office format
            iMsgChk = 1;
            SetFilePointer(fileHandle, 512, NULL, FILE_BEGIN);
            if(ReadFile(fileHandle, buff, 8, &bytesRead, NULL ) == 0) { return 0; }

            if(buff[0] == msgFormatChkXLSPPT[0])
            {
                while(buff[iMsgChk] == msgFormatChkXLSPPT[iMsgChk] && iMsgChk < 5)
                    iMsgChk++;

                if(iMsgChk == 4)
                    iRet = 2;
            }
            else if(buff[iMsgChk] == msgFormatChkOnlyDOC[iMsgChk])
            {
                while(buff[iMsgChk] == msgFormatChkOnlyDOC[iMsgChk] && iMsgChk < 5)
                    iMsgChk++;
                if(iMsgChk == 4)
                    iRet = 2;

            }
            else if(buff[0] == msgFormatChkOnlyPPT[0])
            {
                while(buff[iMsgChk] == msgFormatChkOnlyPPT[iMsgChk] && iMsgChk < 5)
                    iMsgChk++;

                if(iMsgChk == 4)
                    iRet = 3;
            }
            else if(buff[0] == msgFormatChkOnlyXLS[0])
            {

                while(buff[iMsgChk] == msgFormatChkOnlyXLS[iMsgChk] && iMsgChk < 9)
                    iMsgChk++;

                if(iMsgChk == 9)
                    iRet = 4;
            } 

            if(0 == iRet){
                iRet = 5;
            }
        }
    }


    CloseHandle(fileHandle);

    return iRet;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top