Як завантажувати файли на сервер, безпека

Як завантажувати файли на сервер, безпека
«... або чому фільтрація по чорному списку це погано?»

Уявімо звичайну завантаження файлів за допомогою php. Я думаю всі з цим стикалися. Відкинемо збочені варіанти, типу зберігання файлів в базі, їх перейменування та інше. Візьмемо саме звичайну найпростіший форму завантаження файлів.

Зазвичай це форма на хтмл, потім серверна валідація по розширенню завантаження і наступний перенос завантаженого файлу з тимчасової папки в папку завантажень. Відкинемо всі мільйони помилок, які здійснюють програмісти в цих, здавалося б найпростіших, речах, і порахуємо що цей функціонал реалізований грамотно і без помилок.

Постає питання, а як саме фільтрувати розширення файлів? Існують два варіанти:

  • По білому списку - складаємо список допустимих розширень файлів, а всі інші блокуємо
  • По чорному списку - складаємо список заблокованих розширень, а всі інші завантажуємо

Біда в тому що для реалізації фільтрації по білому списку потрібно передбачити всі можливі варіанти потрібних розширень які буде завантажувати наш скрипт. І якщо для місць де необхідно завантажувати тільки картинки - все просто, то в багатьох інших випадках прийдеться скласти досить великий список легітимних розширень. Тому багатьом розробникам здається, що слід піти від зворотного, і заборонити небезпечні розширення.

І якщо в першому випадку багато хто впевнений, що будуть залиті файли тільки з необхідними розширеннями (в статті я розповім вам як можна обійти і це), то от у другому випадку не все так просто.


Почнемо ми з проблем фільтрації по чорному списку.

купа розширень

Перша проблема полягає в тому, що Апачем по дефолту (хоча може і не по дефолту, але принаймні дуже часто) обробляється купа файлів з різними розширеннями як php скрипти. Ви як і раніше вважаєте що досить блокувати лише «.php»? А ось фигушки, ось неповний список можливих розширень:

php .phtml .php4 .php5 .html

Так, так, в деяких конфігураціях апача «.html» може обрабативатся як php скрипт.

А ще ми ж забули про cgi, перл та інші ласощі для хакерів. Так, звичайно їх запуск можливий тільки з папки «/ cgi-bin», але хто знає, може бути саме ваш сервер налаштований інакше ...

І досить упустити хоч одне розширення, і зловмисник, при спробі злому, напевно спробує залити файл з таким розширенням і потім його виконати, що швидше за все призведе до повного злому вашого сайту.

Міняємо конфиг під себе

Ну все, адмін виявився параноїком і додав в фільтр всі виконувані розширення. Але, як то кажуть, на кожен хитрий болт знайдеться своя хитра гайка. Адже адміну навіть не подумалося додати розширення «.htaccess» (якщо це звичайно можна назвати розширенням: D) в список фільтра.

Пробуємо завантажити файл з ім'ям «.htaccess» такого змісту:

AddType application / x-httpd-php .doc

І тепер в папці куди був завантажений цей файл, всі файли з розширенням «.doc» будуть інтерпетіроваться як php скрипти і відповідно виконуватися. Залишилося завантажити php скрипт з цим розширенням і він буде успішно виконано.

ллємо php.ini

Припустимо адмін пішов далі, і додав до списку розширення «.ht *» або допустимо перевірку на не порожнє ім'я файлу (це теж не дасть завантажити файл «.htaccess»).

Не так давно я писав про цікаву особливість зв'язки php + cgi (і до речі fastcgi теж): PHP і CGI. Обхід обмежень безпеки

Для виконання даної атаки ми повинні мати наступне збіг обставин:

  • Php повинен бути підключений через CGI
  • Папка куди завантажуються файли повинен містити хоча б один php скрипт (припустимо index.php)
  • Фільтр не повинен різати розширення .ini (тобто у нас повинно вийти завантажити файл php.ini)

В php є така цікава опція, яка називається auto_prepend_file:

Визначає ім'я файлу, який буде автоматично оброблятися перед основним файлом. Файл викликається так, ніби він був підключений за допомогою функції require, так що include_path також використовується.

Якщо в двох словах, то перед кожним виконанням будь-якого скрипта, буде здійсняться спочатку скрипт вказаний в «auto_prepend_file». Здогадуєтеся до чого я хилю?

; Включаємо читання віддалених файлів (це вимагає allow_url_include)
allow_url_fopen = 1

; Включаємо можливість віддаленого інклуд
allow_url_include = 1

Залили файл? Відмінно! Тепер звертаємося до будь-якого php скрипту який є в Директорії куди заливаються всі файли (саме для цього я писав що потрібен php скрипт в цій папці). При зверненні до скрипту з цієї папки в першу чергу буде виконаний файл вказаний в auto_prepend_file.

«Подвійне» розширення

«MIME-код - довідка, що ти не верблюд.»
несмішний штука з журналу] [akep

А ви знаєте що кожен файл з кожним розширенням має свій mime-тип? І коли ви завантажуєте будь-якої файл, то веб сервер говорить браузеру який тип у даного файлу. Цей mime-тип визначається Апачем по розширенню файлу за допомогою спеціальної таблиці відповідності. На основі певного типу веб сервер може виконувати з даними файлом певні дії, наприклад виконати цей файл як php скрипт або perl скрипт або просто віддати його вміст без обробки і т.д.

До речі в розділі про .htaccess ми додавали свій mime тип для файлів doc, тим самим змушуючи веб сервер обробляти дані файли як php скрипти. Але в загальному мова не про це.

Справа в тому що апач взагалі «унікальний» веб сервер. Начебто логічно перевірити тільки розширення файлу і заспокоїтися, вірно? Але ось фіг! Якщо раптом виявиться що даного розширення немає серед зареєстрованого, то апач перевіряє наявність точки в імені файлі і виділяє друге розширення. Тобто mime тип буде визначаться вже по частині імені файлу а не по його «класичному» розширенню. І так поки не буде визначено mime-тип, або не закінчаться «розширення» в імені файлу.

Так як мало хто знає про таку особливість, то саме цей спосіб дає можливість успішно обходити фільтри, як і по білому списку (в деяких випадках) так і по чорному списку (практично завжди). Для обходу білого списку нам необхідно знайти допустиме до завантаження розширення, для якого mime тип не визначений, зазвичай це розширення - «.rar» (Ось погодьтеся, ви б ніколи не подумали б що дозволивши «.rar» до завантаження ви відкриваєте величезний пролом в безпеки?).

Беремо якийсь скрипт, перейменовуємо його в «script.php.rar» і заливаємо на сервер. І о диво! Цей файл інтерпретується як php скрипт!

Зауважте ця фішка апача небезпечна тим що це не зовсім логічне поведінку веб сервера, і мало хто про неї знає. І саме вона дозволяє обходити безліч фільтрів.

А як же захиститися?

В ідеальному випадку це звичайно повністю перейменовувати файл (включаючи розширення) в якийсь ідентифікатор, а інформацію про фото зберігати в БД. Потім, використовуючи додатковий обробник, видивать потрібний файл і його дані за його ідентифікатором. Але цей спосіб поганий тим що вимагає використання додаткового обробника.

А ось спосіб з прямим збереженням файлів і подальшої їх віддачею тільки за допомогою веб сервера, набагато простіше і менш ресурсоемок, хоча і більш небезпечний. Для того щоб зробити нормальну фільтрацію для цього способу, необхідно використовувати: по-перше фільтрацію по білому списку, а по-друге видаляти / замінювати все спецсимволи в імені файлу (точки, слеші, нулбайти та ін).

Як завантажувати файли на сервер, безпека

А як Ви завантажуєте файли на сервер?

Дивіться також

  • Концепт захисту PHP сайту

Опис захисту від завантаження і виконання довільного коду. Як захистити php сайт від злому за допомогою auto_prepend_file. Блокування недозволених скриптів.

Всі ми, так чи інакше, хотіли б бути впевнені в тому, що наш сайт або блог ніхто не зможе зламати.

  • Дослідження вразливості PHP include

    Правильне проведення атаки php including при додаванні слешів в кінець. Альтернатива Нулла байту. Чому не працюють слеші при php інклудінге.

    Крім програмування, я захоплююся дослідженнями в області безпеки web додатків. Займаюся аудитом на замовлення і так далі. І ось на.

  • Незвичайна захист від PHP Include

    Приклад захисту від PHP include. Спосіб запобігти виявлення і проведення атаки хакером.

    Давайте з вами подумаємо хто такий хакер? Хакер - це не зломщик! Люди часто плутають ці поняття. Хакер - це.

  • PHP і CGI. Обхід обмежень безпеки

    Опис способу обходу safe mode і open basedir. Обхід обмежень безпеки при підключенні php через cgi.

    Сьогодні прийшло ось в голову що непогано було б розповісти про таку цікаву особливості зв'язки php і cgi (і fastcgi.

    Не завантажуйте, користуємося фрі ресурси сторонніх сервісів)

    Теж як варіант) Тільки він, на жаль, підходить далеко не у всіх випадках

    Щодо подвійного розширення це жесть ... Не знав ... Зараз перевірив і здивувався сильно

    Про подвійні розширення ви налякали не на жарт ...
    Але очевидно це новина з підручників історії. Тільки що перевірив на своєму Apache 2.2.17 (якому до речі вже більше двох років), на спробу відкрити файл script.php.rar він відповів пропозицією його завантажити, з поясненням Type: Unknown File type, 13 bytes
    Або навпаки це фішка найновіших версій?

    У мене mod_mime включений.
    Може у нас з вами розрізняються його настройки?
    У вас в httpd.conf включено: MIMEMagicFile conf / magic?

    І ще з приводу підхоплення php.ini в кожній директорії, хотів поцікавитися, може вказівку PHPIniDir в httpd.conf заборонятиме шукати php.ini в іншому місці?

    Спробуйте змінити файлу яке-небудь нестандартне розширення типу «1.php.trololo», може для розширення * .rar у вас визначено обробник.

    Якщо не помиляюся то mod_mime_magic визначає mime тип по його вмісту, тобто MIMEMagicFile не повинен впливати на проблему. Але якщо що, то він у мене відключений.

    А щодо підхоплення php.ini я не можу вам підказати. На локалке і на dev-сервері у мене php підключений через mod_php а не через cgi, відповідно перевірити не можу.

    Я з цього і запитав про PHPIniDir бо подумав що у вас PHPasCGI (у мене завжди був тільки як модуль).

    Хм ... Виявляється rar дійсно у мене визначений в mime.types
    Я навіть не подумав перевірити бачачи на екрані рядок - Type: Unknown File type, 13 bytes (а виявилося що це мій Віндоус не знав що таке rar). Варіант з 1.php.trololo действіетльно відкрився.

    Коли закачіваеш через адмінку - ще можна поміняти точки на прочерки, а коли клієнту дана возможноть файли заливають через ftp - вже ні чим не здатна захиститися ...

    Я б повністю змінював ім'я файлу разом з розширенням, а оригінальне ім'я файлу зберігав би в БД. Від гріха подалі скажімо так.

    А щодо ftp - тут як не крути, якщо і надавати можливість, то завантажувати файли тільки на інший сервер, де відключені php, perl, cgi та інше що можна виконати. Ну або написати свій ftp демон)

    А в налаштуваннях Апача можна задати демілітаризовану зону в якій не виконуються ніякі скрипти?
    Я поки придумав тільки один варіант: FTP закидає файли в папку яка недоступна з інтернету, а файли дістає спеціальна функція. Хоча знову ж таки - там буде головний біль, щоб людина якимось дивом не відправив щось типу:
    МойСайт / GetFile.php? X = 123 /../../../../ passwords

    А в налаштуваннях Апача можна задати демілітаризовану зону в якій не виконуються ніякі скрипти?

    Чисто теоретично можливо. Але справа в тому що людина зможе залити свій .htaccess в якому він може перевизначити цю заборону.

    Я поки придумав тільки один варіант: FTP закидає файли в папку яка недоступна з інтернету, а файли дістає спеціальна функція.

    Теж цілком розумний варіант)

    А що якщо власнику сайту залити в папку ще один .htaccess і виставити на нього права «тільки читання»? Або від завантаження іншого .htaccess це все одно не врятує?

    Можу помилятися, але по ідеї в такому випадку все одно залишиться можливість даний .htaccess просто видалити як файл. І створити новий.

    Хіба не можна в .htaccess папки для завантажень просто вимкнути всі обробники для всіх мов?

    І ще, у мене чомусь складається враження, що в PHP і Apache аж надто забагато цих тонкощів, так критично впливають на безпеку

    В принципі необов'язково завантажувати файл поза public_html. Можна завантажувати і в public_html але перейменовувати файл наприклад в випадковий md5 хеш, або поточний timestamp, зберігши при цьому дані про оригінальний імені в БД, і віддавати його скриптом download.php
    Цим самим вб'ємо двох зайців - і безпечно, і на всякі UTF-8 і спецсимволи в імені файлу пофіг.

    Також варіант. Можна буде і вбити всі проблеми з розширеннями

    Я зви-ний веб-раз-ра-бот-чик. Пі-шу тут про те, що мені інституті-рес-но, з чим я ви-нуж-ден став-ки-вать-ся в сфе-рі WEB, свої мис-ли, рас-суж-де-ня , раз-ме-щаю соб-ного-ні ста-тьі.

    Не забувайте підписуватися:

    І дуже про-шу, не за-б-вай-ті залишати-лять кому-мен-та-рії до про-чи-тан-ним за-пі-сям.