Узнайте реальный тип файла - PullRequest
7 голосов
/ 16 января 2009

Я работаю над веб-страницей ASP, которая обрабатывает загрузку файлов. Допускается загрузка только определенных типов файлов, таких как .XLS, .XML, .CSV, .TXT, .PDF, .PPT и т. Д.

Я должен решить, действительно ли файл имеет такой же тип, как показано в расширении. Другими словами, если trojan.exe был переименован в mageless.pdf и загружен, приложение должно быть в состоянии определить, что загруженный файл НЕ является файлом .PDF.

Какие методы вы бы использовали для анализа этих загруженных файлов? Где я могу получить лучшую информацию о формате этих файлов?

Ответы [ 7 ]

4 голосов
/ 16 января 2009

Другими словами, если trojan.exe был переименован в безвредный.pdf и загружен, приложение должно быть в состоянии определить, что загруженный файл НЕ является файлом .PDF.

Это на самом деле не проблема. Если файл .exe был загружен в формате .pdf, и вы правильно подали его обратно в загрузчик как application / pdf, загрузчик получит только поврежденный PDF. Им придется вручную перепечатать его в .exe, чтобы получить вред.

Реальные проблемы:

  1. Некоторые браузеры могут прослушивать содержимое файла и решать, что они знают лучше, чем вы, о том, какой это тип файла. В IE это особенно плохо, он предпочитает отображать файл как HTML, если он видит какие-либо HTML-теги, скрывающиеся в начале файла. Это особенно бесполезно, так как это означает, что скрипт может быть внедрен на ваш сайт, потенциально ставя под угрозу любую безопасность на уровне приложения (cookie-кража и др.). Обходные пути включают в себя всегда обработку файла в качестве вложения с использованием Content-Disposition и / или обслуживание файлов с другого имени хоста, чтобы он не мог выполнять межсайтовый сценарий обратно на ваш основной сайт.

  2. PDF-файлы в любом случае не безопасны! Они могут быть полны сценариев и имеют значительные дыры в безопасности. Использование дыры в плагине браузера для чтения PDF-файлов в настоящее время является одним из наиболее распространенных способов установки троянов в Интернете. И вы почти ничего не можете сделать, чтобы попытаться обнаружить эксплойты, поскольку они могут быть сильно запутаны.

4 голосов
/ 16 января 2009

Один из способов - проверить наличие определенных подписей или магических чисел в файлах. На этой странице есть удобный список известных сигнатур файлов, и он выглядит довольно актуально:

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

3 голосов
/ 16 января 2009

Получите заголовки файлов «безопасных» типов файлов - исполняемые файлы всегда имеют свои собственные типы заголовков, и вы, вероятно, можете их обнаружить. Однако вы должны быть знакомы с каждым форматом, который вы намереваетесь принять.

2 голосов
/ 16 января 2009

Я знаю, что вы сказали C #, но это может быть перенесено. Кроме того, в нем есть файл XML, уже содержащий множество дескрипторов для общих типов файлов.

Это библиотека Java, которая называется JMimeMagic. Это здесь: http://jmimemagic.sourceforge.net/

1 голос
/ 16 января 2009

В системах ** NIX * у нас есть утилита под названием file (1) . Попробуйте найти что-то подобное для Windows, но утилиту файлов, если self был портирован.

1 голос
/ 16 января 2009

Может быть, вы могли бы подойти к этому с другой стороны. Вместо того, чтобы идентифицировать все типы файлов, которые загружаются (один Excel для меня кажется беспорядком, потому что он имеет несколько форматов в наши дни), почему бы не запустить все загрузки через сканер вирусов ? Большое разнообразие файлов может содержать вирусы и трояны. Это может быть больше работы для вашего сервера, но это самое безопасное решение.

Тогда пользователи должны правильно определить типы файлов, что кажется разумным. Добавление большого количества кода (который также должен быть протестирован) просто для двойной проверки ваших пользователей кажется большим шагом. Если я скажу, что это файл .pdf2, вы переименуете его в .pdf? Если это в корпоративной среде, то разумно ожидать, что пользователи будут иметь правильные расширения в своих файлах. Я бы отследил, кто что загрузил. Если это общедоступно, тогда может быть целесообразно выполнить сканирование на наличие типов файлов, но я бы также сделал проверку на вирусы.

0 голосов
/ 15 марта 2011

Вам может помочь следующий код C ++:

//-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;
}
...