Уявімо звичайну завантаження файлів за допомогою 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 including при додаванні слешів в кінець. Альтернатива Нулла байту. Чому не працюють слеші при php інклудінге.
Крім програмування, я захоплююся дослідженнями в області безпеки web додатків. Займаюся аудитом на замовлення і так далі. І ось на.
Приклад захисту від PHP include. Спосіб запобігти виявлення і проведення атаки хакером.
Давайте з вами подумаємо хто такий хакер? Хакер - це не зломщик! Люди часто плутають ці поняття. Хакер - це.
Опис способу обходу 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, свої мис-ли, рас-суж-де-ня , раз-ме-щаю соб-ного-ні ста-тьі.
Не забувайте підписуватися:
І дуже про-шу, не за-б-вай-ті залишати-лять кому-мен-та-рії до про-чи-тан-ним за-пі-сям.