Проблеми със сигурността на PHP приложения от гледна точка на програмиста и администратора
Представена от Георги Чорбаджийски (georgi@unixsol.org)
на 24 май 2005 на WebTech'05 в София
Презентацията се намира на адрес: http://georgi.unixsol.org/texts/presentations/
Сигурност?
Сигурността не е нещо, което се купува
Сигурността е процес
Сигурността е компромис
Сигурността трябва да е основна част от дизайна на приложението
"Тестването може да открие присъствието на грешки, но не и отсъствието им" - Dijkstra
За да може вашето приложение да е сигурно, трябва да сте ИНФОРМИРАНИ!
Security through obscurity - НЕ РАБОТИ!
ПРОВЕРЯВАЙТЕ ВСИЧКО!
Мислете като "лошите"
Противоречия
Програмистът
иска бързо да си свърши работата
иска да пише на език с много възможности и да използва всяка една от тях
ако е възможно ползва всички ресурси
девизът му е: мързелът е добродетел (lazyness is virtue)
Администраторът
иска машините да са сигурни, а при проблем пораженията да са минимални
иска потребителите да не си пречат един на друг
трябва да осигури ресурси за всички
девизът му е: параноята е добродетел (paranoia is a vitue)
Общи проблеми в web приложенията
Топ 10 според Open Web Application Security Project
1. Невалидирани параметри
2. Грешки при контрола на достъпа
3. Грешки при контрола на сесиите и акаунтите
4. Cross-Site Scripting (XSS) уязвимости
5. Препълване на буфера
6. Злонамерено вмъкване на команди
7. Проблеми при обработка на грешки
8. Несигурно ползване на криптография
9. Грешки при отдалечено администриране
10. Грешки при конфигурация на web сървъра
За повече информация
http://www.sklar.com/page/article/owasp-top-ten
Cross site scripting (XSS)
Какъв е проблемът?
Атака върху потребителя
Експлоатира се доверието на потребител към даден сайт
Чрез XSS се краде информация от потребителска сесия или самата сесия
Реализира се чрез вмъкване на HTML тагове и JavaScript
Програмни решения
Не показвайте директно данни, идващи от потребителите
Филтрирайте или нормализирайте показваните данни
PHP специфични решения
htmlspecialchars, htmlentities, strip_tags
За повече информация
http://blog.bitflux.ch/wiki/XSS_Prevention
http://ha.ckers.org/xss.html
Cross site request forgery (CSRF)
Какъв е проблемът?
Точно обратният на XSS
Атака върху сървъра
Възползва се от доверието на сървъра към потребителя, като на злонамерен сайт се поставя връзка към сайта, в който сте логнат
Пример
Програмни решения
Не правете важните действия тривиални
Изисквайте парола за извършване на важни действия
Използвайте POST вместо GET, където е възможно
Проверявайте Referrer на важните форми
Подсигурете формите, чрез уникални данни в тях
За повече информация
http://shiflett.org/articles/foiling-cross-site-attacks
SQL Injection
Какъв е проблемът?
Възможно е пълно компроментиране на базата данни
При някои бази данни може да доведе до изпълнение на команди на сървъра
При някой бази може да доведе до четене и писане на файлове, за които DB сървъра има права
Пример
Програмни решения
Никога не ползвайте в SQL заявка данни, които не сте "почистили"
Prepared queries
Ограничавайте правата на потребителя, който ползвате за достъп до базата
PHP специфични решения
addslashes
mysql_escape_string, mysql_real_escape_string
pg_escape_string
НЕ РАЗЧИТАЙТЕ НА magic_quotes_gpc!
За повече информация
http://php.net/manual/en/security.database.sql-injection.php
http://www.unixwiz.net/techtips/sql-injection.html
Command Injection
Какъв е проблемът?
Възможно е изпълнение на нежелани команди на сървъра
Пример
Програмни решения
При извикване на външни команди не ползвайте параметри, контролирани от потребителя
Филтрирайте командите и параметрите
PHP специфични решения
escapeshellcmd
escapeshellarg
PHP специфични проблеми
Глобални променливи (register_globals)
Качване на файлове (стар начин)
Отдалечени файлове
"Библиотечни" файлове
Сесийни файлове
Magic quotes
Глобални променливи
Атака
http://server/show_secret_info.php?validated=1
Решения
Винаги инициализирайте променливите
Настройки
register_globals = off (във версии >= 4.2.0 е така)
error_reporting = E_ALL;
Качване на файлове (стар начин)
Атака
http://server/upload.php?up=/etc/passwd&.....&submit=Send
Решения
Използване на новия начин за качване на файлове
$_FILES, is_uploaded_file, move_uploaded_file
Внимавайте с разширенията на качваните файлове и къде ги слагате
Настройки
file_uploads, upload_max_filesize, upload_tmp_dir
post_max_size, memory_limit
Отдалечени файлове
Използване и странични ефекти на функциите
include, include_once, require and require_once
fopen, readfile, file
imagecreatefromXXX
Примери
include('file.php');
include('http://server/file.php');
file('ftp://user:pass@server/file.txt');
Решения
Филтриране на изходящите връзки от сървъра
Не използвайте тези функции с данни контролирани от потребителя
Настройки
allow_url_fopen = off
"Библиотечни" файлове
Слагане на библиотеките, видими в web дървото
Използване на "странни" (.inc, .lib, etc...) разширения
Непредвиждане, че файл може да се извика директно
Решения
За код винаги ползвайте самo регистрираните разширения (.php)
Не пишете код, който разчита на включен register_globals
Библиотеките се слагат извън web дървото или в недостъпна директория
Дефинирайте константи и ги проверявайте, за да сте сигурни, че файлът е извикан откъдето трябва
Сесийни файлове
По подразбиране се съхраняват в /tmp
Възможно е други потребители на сървъра да имат достъп до тях
Решения
Всеки host работи под различен потребител
Ползване на частна директория за сесиите на потребителя
Пазене на сесиите в базата данни
Настройки
session.save_path
Magic quotes
Какво правят?
Защо не трябва да се ползват?
Настройки
magic_quotes_gpc
magic_quotes_sybase
magic_quotes_runtime
Функции
addslashes
stripslashes
Административни проблеми
PHP като CGI
--enable-force-redirect
PHP като Apache модул
Достъп до файловата система
Достъп до бази данни
Външни библиотеки
PHP ограничения
safe_mode, safe_mode_gid
open_basedir
file_uploads
allow_url_fopen
disable_functions
display_errors
enable_dl
expose_php
Опасни PHP функции
Функции, които е добре да изключите (disable_functions=...)
Изпълнение на външни програми
exec, passthru, proc_open, shell_exec, system, popen, pcntl_fork, pcntl_exec
Отваряне на връзки
fsockopen, pfsockopen
socket_bind, socket_accept, socket_listen, socket_create
stream_socket_client, stream_socket_server
Разни
dl, glob, posix_*
Други...
Функции, ползващи отдалечени файлове
include, include_once, require and require_once
fopen, readfile, file
imagecreatefromXXX
Специални функции
phpinfo, eval
Административни ограничения
Изходящи връзки от web сървъра
Limits
chroot
suexec
Препоръки за сигурна настройка на PHP
Глобални настройки в php.ini
engine = off
register_globals = off
magic_quotes_gpc = off
safe_mode = on
allow_url_fopen = off
file_uploads = off
display_errors = off
log_errors = on
expose_php = off
error_reporing = E_ALL
Препоръки за сигурна настройка на Apache с PHP модул
suexec
user patch за Apache 1.3
mpm_perchild за Apache 2
Настройки за всеки виртуален хост
Конкректни настройки за PHP
Име и парола за базата данни в отделен файл достъпен само за root
Пример (/usr/local/apache/conf/example.com-vhost.conf):
SetEnv DB_USER "dbuser"
SetEnv DB_PASS "dbpass"
Настройки на виртуалния хост
ServerName example.com
ServerAlias *.example.com
User exampleuser
Group examplegroup
DocumentRoot /hosting/example.com/htdocs
CustomLog "|/usr/bin/cronolog /wwwlog/example.com/%Y-%m-%d/access.log" combined
ErrorLog "|/usr/bin/cronolog /wwwlog/example.com/%Y-%m-%d/errors.log"
AllowOverride AuthConfig Indexes Limit Options
Allow from all
Include /usr/local/apache/conf/example.com-vhost.conf
php_admin_flag engine on
php_admin_value open_basedir "/hosting/example.com/:/usr/lib/php/"
php_admin_value doc_root /hosting/example.com/htdocs
php_admin_value session.save_path /hosting/example.com/tmp
php_admin_value upload_tmp_dir /hosting/example.com/tmp
php_admin_value sendmail_from admin@example.com
# php_admin_value file_uploads on
# php_admin_value upload_max_filesize 10M
# php_admin_value post_max_size 10M
Заръки за програмиста
Проверявай винаги и всичко!
Прави проверки, така че да не могат да бъдат избегнати
Не вярвай на данни, идващи от външен източник (потребители, db, файлове и т.н.)
Инициализирай променливите си
Пиши код, който работи без грешки при error_reporting = E_ALL
Внимавай когато даваш достъп до данни, предоставени от потребителя
Не слагай на публично достъпни места конфиденциални данни
Заръки за администратора
На работещ сайт записвай грешките, но не ги показвай на гледащия страницата
Всеки сайт трябва да работи с различен потребител
Всеки потребител трябва да вижда само собствените си файлове
Забрани функциите, които е лесно да бъдат използвани неправилно
Следи логовете си!
Повече информация
За сигурно програмиране
http://www.dwheeler.com/secure-programs/
За сигурност в PHP
http://www.php.net/manual/security.php
http://www.securereality.com.au/studyinscarlet.txt
http://phpsec.org/
http://www.phpsecure.info/
http://shiflett.org/article/
http://www.modsecurity.org/db/resources/category.php?id=7
http://www.hardened-php.net/
За сигурност в Apache
http://www.devet.org/apache/chroot/
http://luxik.cdi.cz/~devik/apache/
TODO:
Directory & File browsing (dot dot attack, poison NULL byte)
mail() Injection
http headers Injection