2013-02-10 24 views
7

Mam przypadek użycia, w którym zezwalamy użytkownikom na przesyłanie plików. Teraz w java z tyłu (kontroler, który wyodrębnia plik z żądania HTTP i kontroli), chcę wykryć, czy użytkownik przesyła dowolny plik wykonywalny. Jeśli przesyła, muszę odrzucić ten plik. Mam googleed to, ale nie mogłem znaleźć dobrego rozwiązania. Niektórzy sugerowali weryfikację rozszerzenia (.exe). Ale nie jestem pewien, jak daleko będzie filtrować pliki exe. Chcę całkowicie zablokować pliki wykonywalne przed przesłaniem.Wykrywanie pliku wykonywalnego w java

Jeśli któryś z Państwa natknął się na ten scenariusz lub ma rozwiązanie tego problemu, proszę dać mi znać. Byłbym ci wdzięczny.

Byłbym bardziej szczęśliwy, jeśli możesz wskazać mi dowolną implementację JAVA lub interfejs API języka Java lub algorytm, który to robisz.

+0

Jakieś inne sugestie? – Rajeev

Odpowiedz

9

podejrzewam, że, oprócz metody sprawdzania rozszerzenia, o której już wspomniałeś, nie będzie możliwości złapania wszystkich możliwych przypadków. Pliki wykonywalne są w ostateczności ciągami instrukcji maszynowych, które w znacznym stopniu odróżniają je od innych danych.

Mimo to istnieją pewne rzeczy, których można szukać w niektórych typach z pliku wykonywalnego. Na przykład:

  • Windows używa formatu na Portable Executable, które zawsze należy rozpocząć od magicznej liczby 4d5a (znaki ASCII MZ) format
  • ELF wykonywalnego używanych przez Linux początek 7f454c46
  • Java class files zawsze zaczynają cafebabe (to jest hex, a nie ASCII!).
  • O ile widzę, plików Mach-O używane przez Mac-OS X mają magiczną liczbę feedface (HEX ponownie)

Proponuję utworzyć FileInputStream lub podobny i przeczytać kilka pierwszych bajtów plik, sprawdzanie tych magicznych liczb. Nie wykrywa żadnego pliku zawierającego kod wykonywalny, ale powinien zatrzymać pliki w tych standardowych formatach wykonywalnych, co jest moim zdaniem oczekiwane.

Tak na przykład:

public static boolean isExecutable(File file) { 
    byte[] firstBytes = new byte[4]; 
    try { 
    FileInputStream input = new FileInputStream(file); 
    input.read(firstBytes); 

    // Check for Windows executable 
    if (firstBytes[0] == 0x4d && firstBytes[1] == 0x5a) { 
     return true; 
    } 
    return false; 
    } 
    catch (Exception e) { 
    e.printStackTrace(); 
    } 
} 

Uważaj też, że jest możliwe, aby uzyskać fałszywie dodatni, gdzie można odrzucić plik wykonywalny, który nie był. Nie wiem, jaki typ pliku zamierzasz przesłać, więc powinieneś zastanowić się, jakie jest prawdopodobieństwo, że tak się stanie.

+0

dzięki za twoją sugestię. Przeszedłem przez wiki i znalazłem podobne rozwiązania. Poniżej znajdują się wiki: http://www.csn.ul.ie/~caolan/publink/winresdump/winresdump/doc/pefile2.html Byłbym naprawdę bardziej szczęśliwy, jeśli możesz mnie poprowadzić, jak sprawdzić powyższe trzy konidcje wymienione w java – Rajeev

+0

Tak, to potwierdza to, co znalazłem: pliki wykonywalne Windows zawsze zaczynają się od ASCII 'MZ' (lub hex' 4d5a'). Zaktualizowałem swoją odpowiedź, dodając do Mac OSX również – jazzbassrob

+0

Zaktualizowałem przykład kodu dla systemu Windows. Zostawię to wam, abyście mogli przetestować pozostałe. Nadzieja, która pomaga. – jazzbassrob

0

Plik wykonywalny systemu Windows zawsze rozpoczyna się od magicznej liczby MZ. Prawdopodobnie możesz to sprawdzić.

+0

Przeszedłem przez wiki i znalazłem poniżej dwie wiki: http://www.delphidabbler.com/articles?article=8&part=1 http://stackoverflow.com/questions/2863683/how-to-find-if -a-file-is-an-exe Ale nie tak wyraźnie. Oni zasugerowali dla chekinga PE..Ale potrzeba więcej informacji na ten temat jak sprawdzać i implementować – Rajeev

0

O ile widziałem, najbardziej powszechnym podejściem jest weryfikacja rozszerzenia. Na przykład zauważyłem, że klienci poczty zazwyczaj akceptują wysyłanie pliku wykonywalnego, jeśli jest on zmieniony np. na suwak lub inne rozszerzenie.
Uważam, że to wydaje się odpowiednie, ponieważ problem z bezpieczeństwem polega na tym, że użytkownik przypadkowo uruchomi plik wykonywalny. Zmieniając nazwę pliku na nieznane/inne rozszerzenie, użytkownik nie może tego zrobić przypadkowo, więc niebezpieczeństwo jest w jakiś sposób "złagodzone".
W przeciwnym razie wymyślimy sposób na sprawdzenie zawartości pliku, aby ustalić, czy rzeczywiście masz plik wykonywalny, nie wiem jak to możliwe/przenośne/niezawodny to

0

Sprawdźcie tutaj:

Is there a good way to determine if a file is executable in Java

Wygląda tego polecenia może pomóc: java.io.File.canExecute()

+1

Niestety, to tylko określa, czy plik ma * uprawnienia * do wykonania - nie, czy faktycznie zawiera kod wykonywalny – jazzbassrob

+0

Jak powiedział jazzbassrob, to nie pomoże. Nie może wykryć plików wykonywalnych, które są w pliku – Rajeev

+0

i już przeszły przez link, o którym wspomniałeś. Nie jest to związane z pytaniem, które zadaję właśnie .... – Rajeev

0

Należy pamiętać, że plik wykonywalny Windows są nie tylko .exe plików więc sprawdzanie rozszerzenia nie będzie wystarczająco

Jeśli chcesz coś zaawansowane i trudno oszukać, można użyć narzędzia innej firmy jak File for Windows jest to popularne narzędzie wiersza poleceń, które zostało przeniesione z Linuksa.

na przykład, jeśli chcesz sprawdzić jakiś plik program.exe

C:\file -b "program.exe" 

Rezultatem będzie coś

PE32 executable for MS Windows <GUI> Intel 

można uruchomić to narzędzie z programu Java za pomocą Runtime.getRuntime().exec()

Zobacz this question, aby dowiedzieć się, jak uruchomić program wiersza poleceń i uzyskać dane wyjściowe w języku Java

Możesz również sprawdzić Apache Tika, aby uzyskać typ pliku z jego zawartości.

+0

Jak mogę to zrobić w Javie? – Rajeev

+0

Jaka jest zależność, którą muszę dodać ... Będzie bardziej przydatna dla wszystkich, jeśli możesz dostarczyć przykładowy program wykrywający pliki wykonywalne?Również wdzięczny, jeśli możesz rzucić światło na negatywy użycia tej metody, takie jak przypadki brzegowe, na które można go nie zauważyć lub traktować normalny plik jako plik wykonywalny. – Rajeev

+0

Nie musisz dodawać niczego w Javie (np. Słoiki), jeśli jesteś w stanie uruchomić polecenie z 'cmd' możesz po prostu wywołać je bezpośrednio z Java używając' getRuntime(). Exec() ' – iTech

Powiązane problemy