روش های ایمن سازی php در سرور
مقدمه
PHP یک زبان برنامه نویسی سمت سرور Open-Source میباشد که بصورت گسترده مورد استفاده قرار گرفته است. وب سرورهای Apache/Nginx/Lighttd با استفاده از پروتکل HTTP و یا HTTPS اجازه دسترسی به فایل های روی سرور را به کاربر میدهد، با درخواست کاربر اسکریپت PHP سمت سرور کامپایل شده و نتیجه ان بصورت HTML و … به سمت کاربر ارسال میشود. یک نقص در کانفیگ زبان های اسکریپتی سمت سرور میتواند انواع مشکلات را بوجود بیاورد. به همین دلیل PHP نیز باید با احتیاط مورد استفاده قرار بگیرد. در این اموزش راه حل جامع برای ادمین سرور ها اموزش داده شده است تا از این اسکریپت با امنیت بیشتری استفاده شود. توجه داشته باشید همانطور که گفته شد مواردی که در ادامه میخوانید جامع بوده و باید با توجه به سرویس دهی شما مورد استفاده قرار بگیرد تا در سرویس دهی مشکل ایجاد نکند.
زمانی که از کنترل پنل استفاده میشود برخی از مراحل امنی سازی توسط کنترل پنل انجام میشود و یا ممکن است ادرس برخی از فایل تنظیمات در سیستم عامل های متفاوت فرق داشته باشد. در این اموزش از این موارد استفاده میکند:
- پوشه روت وب سرور در ادرس var/www/html میباشد.
- وب سرور پیش فرض Apache میباشد.
- فایل کانفیگ PHP.ini در آدرس etc/php.ini قرار دارد.
- افزونه های php در ادرس /etc/php.d قرار دارد.
- نمونه فایل کانفیگ امنیتی در ادرس etc/php.d/security.ini قرار دارد. البته این فایل بصورت پیشفرض وجود ندارد و باید با استفاده از ویرایشگر متنی ایجاد شود.
- سیستم عامل پیشفرض لینوکس توضیع CentOS است. البته تفاوت چندانی در نسخه های دیگر ندارد.
تقریبا برای اجرای اکثر دستورات مانند دستور زیر نیاز است تا دسترسی root به سرور داشته باشید:
1
|
#php -v
|
خروجی:
1
2
3
|
PHP 5.4.45 (cli) (built: Jul 22 2016 19:13:31)
Copyright (c) 1997–2014 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998–2014 Zend Technologies
|
نسخه سیستم عامل مورد استفاده شده در این اموزش:
1
|
#cat /etc/redhat-release
|
خروجی:
1
|
CentOS release 6.8 (Final)
|
مرحله اول – آشنایی با حملات روی PHP
شما زمانی میتوانید حملات را ردگیری و یا با ان مقابله کنید که متد های ان را بشناسید و با رفع ان اشنایی داشته باشید. برای شناخت برخی از حملات شایع در php را بصورت مختصر معرفی میکنم.
- XSS – اسیبپذیری XSS یا Cross-Site-Scripting یک اسیبپذیری در برنامه های PHP میباشد که توسط ان هکر میتوانید اطلاعات کاربران را سرقت نمایید. شما میتوانید با کانفیگ درست اپاچی و نوشتن اسکریپت PHP امن که ورودی کاربر را برسی میکند از این حمله جلوگیری کنید.
- SQL-Injection – این گونه حملات در لایه دیتابیس برنامه های PHP انجام میشود. زمانی که ورودی کاربر به درستی فیلتر نشود دستورات sql پیشبینی نشده میتواند توسط برنامه اجرا شود. این گونه دستورات میتواند باعث نمایش اطلاعاتی نظیر پسوررد، اطلاعات کاربر دیگر اطلاعات موجود شود. اینگونه حملات میتوان با کدنویسی امن و استفاده از توابعی نظیر mysql_real_escape_string ورودی کاربر را در برنامه برسی و قبل از ارسال به دیتابیس ان را متوقف نمایید.
- File-upload – زمانی که کاربر امکان اپلود فایل را داشته باشد ممکن است بجای اپلود تصویر و یا فایل مشخص شده فایل های مخرب نظیر Shell یا دیگر اسکریپت های مخرب را اپلود نمایید. این فایل های مانند دیگر فایل های PHP روی سرور میتواند از سمت کاربر اجرا شده و باعث حذف و یا سرقت اطلاعات شما شوند. این اسیبپذیری جدی بوده و ممکن است خسارات جبران ناپذیری به شما وارد کند.
- Including local and remote files – هکر با استفاده از این اسیبپذیری میتواند کد های PHP را بصورت Remote در سرور اجرا نمایید. این اسیبپذیری امکان اپلود فایل، نصب Backdoor و حذف فایل را نیز در سرور فراهم میکند.
- ()eval – فرمت String را مانند کد های PHP پردازش میکند. با استفاده از امکان تابع هکر میتواند ابزار و یا کد های خود را در سرور پنهان سازد. برای جلوگیری میتوانید از امکان را در php غیر فعال سازید.
- Sea-surf Attack – نام دیگر این حمله CSRF نیز میباشد. این اسیبپذیری کاربر وارد شده را وادار میکند تا فعالیت های مورد نظر شخص هکر را در برنامه های تحت وب انجام دهد. این اسیبپذیری این امکان را فراهم میکند تا بتوان اطلاعات و دسترسی ها کاربر را سرقت نمود. اگر کاربر ادمین سایت باشد تمامی وبسایت در دسترس هکر قرار خواهد گرفت.
مرحله دوم – حذف/نصب ماژول های داخلی PHP
جهت مشاهده ماژول های داخلی php دستور زیر را در محیط ssh وارد نمایید:
1
|
#php -m
|
نمونه خروجی (ممکن است خروجی در هر سرور و نسخه PHP متفاوت باشد):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
[PHP Modules]
bz2
calendar
Core
ctype
curl
date
ereg
exif
fileinfo
filter
ftp
gettext
gmp
hash
iconv
ionCube Loader
json
libxml
mbstring
mhash
mysql
mysqli
openssl
pcntl
pcre
PDO
pdo_mysql
pdo_sqlite
Phar
readline
Reflection
session
shmop
SimpleXML
sockets
SPL
sqlite3
standard
tokenizer
xml
zip
zlib
|
توصیه ما این است تا ماژول هایی که نیاز ندارید را غیر فعال کنید تا سرعت و امنیت افزایش یابد، بطور مثال در صورتی که به sqlite3 نیاز تدارید میتوانید ان را با حذف، تغییر نام و یا جا به جایی فایل کانفیگ، در پوشه etc/php.d ماژول مورد نظر را غیر فعال نمایید.
برای مثال :
1
|
# rm /etc/php.d/sqlite3.ini
|
یا :
1
|
# mv /etc/php.d/sqlite3.ini /etc/php.d/sqlite3.disable
|
ماژول های compiled-in نیز میتوانید با حذف و نصب مجدد با استفاده از کانفیگ جدید کاهش یابد. شما میتوانید سورس PHP را دنلود کرده و با ماژول های مورد نیاز کامپایل نمایید :
1
2
3
4
5
6
7
|
./configure —with–libdir=lib64 —with–gd —with–mysql —prefix=/usr —exec–prefix=/usr \
—bindir=/usr/bin —sbindir=/usr/sbin —sysconfdir=/etc —datadir=/usr/share \
—includedir=/usr/include —libexecdir=/usr/libexec —localstatedir=/var \
—sharedstatedir=/usr/com —mandir=/usr/share/man —infodir=/usr/share/info \
—cache–file=../config.cache —with–config–file–path=/etc \
—with–config–file–scan–dir=/etc/php.d —enable–fastcgi \
—enable–force–cgi–redirect
|
با استفاده از کانفیگ بالا ماژول های GD,fastcgiT و MySQL Support نیز فعال میشود.
مرحله سوم – محدودیت نمایش اطلاعات PHP سمت سرور
برای جلوگیری از نشت اطلاعات PHP متغیر expose_php باید غیر فعال شود. برای غیر فعال کردن این متغیر باید فایل etc/php.d/security.ini را ویرایش کرده و دستور زیر را در ان اضافه میکنید. [جهت اعمال تغییرات در تنظیمات PHP باید سرویس اپاچی ریستارت شود]
1
|
expose_php=Off
|
البته میتوانید این متغیر را در etc/php.ini نیز غیر فعال نمایید که برای نظم و بهتر است تنظیمات را بصورت متمرکز در یک فایل انجام دهید. زمانی که ای متغییر فعال باشد اطلاعات مربوط به نسخه php را به محدوده خارج سرور نمایش میدهد، به راحتی میتوان با استفاده از افزونه های مختلف برای مرور گر و ابزار های سیستم عامل اطلاعات php را خارج از سرور مشاهده کرد. به عنوان مثال با استفاده از دستور curl -I میتوانید اطلاعات مختصری در مورد وب سرور، زمان سرور، نسخه php و … را مشاهده نمود.
1
|
#curl -I http://www.wikiconfig.ir/index.php
|
خروجی:
1
2
3
4
5
6
|
HTTP/1.1 200 OK
Date: Thu, 13 Oct 2016 06:18:40 GMT
Server: Apache
X–Powered–By: PHP/5.5.45
Vary: Accept–Encoding
Content–Type: text/html; charset=UTF–8
|
مرحله چهارم – لاگ گرفتن از ارور های PHP
ارور های اسکریپت PHP شما نباید در معرض عموم قرار بگیرد. برای این کار باید display_error را غیر فعال نمایید. برای غیر فعال کردن این متغیر، دستور زیر را در فایل etc/php.d/security.ini وارد نمایید.
1
|
display_errors=Off
|
با وارد کردن دستور بالا در فایل Security.ini دیگر ارور های اسکریپت شما نمایش داده نخواهد شد، به این ترتیب باگ های شما برای عموم توسط ارور قابل مشاهده نخواهد بود. سپس برای برای نگهداری و برسی بهتر است لاگ php را در یک فایل ذخیره نمایید. برای لاگ کردن Event ها و error ها دستور زیر را در فایل مورد نظر وارد نمایید.
1
2
|
log_errors=On
error_log=/var/log/httpd/php_scripts_error.log
|
مرحله پنجم – جلوگیری از آپلود فایل
اگر اسکریپت شما نیازی به اپلود فایل ندارد بهتر است ای مورد را غیر فعال نمایید. برای غیر فعال سازی فایل security.ini را باز کنید و دستور زیر را در ان وارد نمایید
1
|
file_uploads=Off
|
اگر نیاز به اپلود فایل از سمت اسکریپت خود را دارید میتوانید با دستور زیر ان را فعال و برای اپلود محدودیت حجمی تعریف کنید.
1
2
3
|
file_uploads=On
; user can only upload upto 1MB via php
upload_max_filesize=1M
|
مرحله ششم – غیر فعال کردن اجرای کد بصورت Remote
اگر allow_url_fopen فعال باشد فانکشن های مرتبط با file مانند file_get_contents میتوایند بصورت Remote از ftp و یا وب سایت اطلاعات دریافت نمایید. بسیاری از برنامه نویسان فراموش میکنند تا یک فیلتر برای قسمت اطلاعات ارسالی از سمت کاربر ایجاد کنند که این باعث اسیبپذیری Injection میشود. بسیاری از اسیبپذیری Code-Injection گزارش شده مربوط به فعال بودن این تابع میباشد. برای غیرفعال سازی دستورات زیر را در فایل security.ini وارد نمایید. (توصیه میشود allow_url_include هم غیر فعال شود)
1
2
|
allow_url_fopen=Off
allow_url_include=Off
|
مرحله هفتم – فعال سازی Safe-Mode برای MySQL
زمانی که Safe-mode فعال باشد. توابع mysql_connect و mysql_pconnect ارگومان های ارسالی به خود را نادیده میگیرند! به این نکته توجه داشته باشید با فعال شدن این مد ممکن است بعضی از اسکریپت ها و CMS ها دیگر مانند وردپرس قادر به کار کردن نباشند، پس نیاز است که در کد دستکاری کنید. همچنین غیر فعال سازی magic_quotes_gpc هم توصیه میشود. پس اگر با دقت این مد را فعال نمایید. برای فعال سازی Safe-Mode و غیر فعال سازی magic_quoates_gpc دستورات زیر را در فایل security.ini وارد نمایید.
1
2
|
sql.safe_mode=On
magic_quotes_gpc=Off
|
مرحله هشتم – کنترل مقدار اندازه POST
متد HTTP POST برای زمانی است که client که ممکن است کاربر و یا مرورگر باشد نیاز دارد تا اطلاعاتی را همراه Request به وب سرور ارسال نمایید، مانند زمانی که یک فایل همراه فرم اطلاعات شخصی برای وب سرور ارسال مشود. شخص محاجم ممکن است درخواست ها را شبیه سازی کرده و منابع سیستم را ببلعد! برای اعمال محدودیت در مقدار POST دستور زیر را در فایل Security.ini وارد نمایید.
1
2
|
; Set a realistic value here
post_max_size=1K
|
مرحله نهم – محدود سازی منابع (کنترل DOS)
شما میتوانید برای اجرای هر اسکریپت یک زمان مشخص تعیین نمایید. زمان مشخص شده به ثانیه میباشد، دیگر گزینه های قابل تنظیم میتوان به زمان سپری شده برای Pars کردن اطلاعات هر درخواست و بیشترین مقدار حافظه قابل استفاده برای هر اسکریپت اشاره کرد. برای تنظیم این موارد، دستورات زیر را در فایل security.ini وارد نمایید.
1
2
3
4
|
# set in seconds
max_execution_time = 30
max_input_time = 30
memory_limit = 40M
|
مرحله دهم – نصب سیستم امنیتی پیشرفته Suhosin برای PHP
Suhosin یک سیستم امنیتی پیشرفته برای PHP میباشد که برای محافظت سرور و کاربران از اسیبپذیری برنامه های تحت PHP و core آن میباشد. از Suhosin میتوانید بصورت جدا و یا ترکیبی استفاده نمایید. بصورت جدا میتواند بصورت patch بر ضد core باشد.، که تعداد محدودی از اسیبپذیری ها مانند BufferOverFollow و String-Vulnerabilities را متوقف سازد. نوع دوم بصورت یک extension بر روی PHP فعال شده و بصورت کاملتر اسیبپذیری ها را شناسایی میکند. نصب این افزونه در پست جداگانه ای اموزش داده خواهد شد.
مرحله یازدهم – غیر فعال کردن توابع فعال
در PHP توابع زیادی فعال میباشد که در صورتی که به درستی مورد استفاده قرار نگیرند میتوانید سرور را با مشکل مواجه کند. به همین منظور تعدادی از توابع خطرناک را غیر فعال نمایید. به این منظور دستور زیر را در فایل Security.ini وارد نمایید.
1
|
disable_functions =exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
|
مرحله دوازدهم – فعال کردن دستوراتFastCGI روی PHP
PHP میتواند با FastCGI نیز کار کند. استفاده از FastCGI باعث کاهش میزان مصرف رم شده اما همچنان شما همان سرعت و قدرت PHP را خواهید داشت. فعال کردن این گزینه در فایل کانفیگ باعث افزایش امنیت نیز خواهد شد. برای فعال کردن FastCGI وارد Security شده و دستور زیر را وارد نمایید.
1
2
|
; Enable cgi.force_redirect for security reasons in a typical *Apache+PHP–CGI/FastCGI* setup
cgi.force_redirect=On
|
مرحله سیزدهم – استفاده از یوزر ID و گروه ID در PHP
mod_fastcgi یک ماژول وب سرور اپاچی میباشد. این ماژول میتواند به یک سرور خارجی FastCGI نیز وصل شود، به همین دلیل باید اطمینان حاصل نمایید که PHP تحت یوزر root اجرا نشود. زمانی که PHP تحت یوزر روت اجرا شود ممکن است به فایل های سیستمی نیز دسترسی داشته باشد. مجدود کردن با استفاده از Apache’s suEXEC یا mod_suPHP انجام میشود که در اینده این عملیات تحت یک پست جدا اموزش داده خواهد شد.
مرحله چهاردهم – محدود کردن دسترسی PHP به دیگر فایل های سیستم
متغییر open_basedir تعیین میکند کدام دایرکتوری از سمت توابع PHP قابل دسترس میباشد. زمانی که فایلی خارج از ادرس تعیین شده open_basedir باشد PHP ان فایل را باز نمی کند. برای ادرسی نمیتوانید از سمبل ها برای وارد کردن چند ادرس استفاده نمایید و تنها اجازه دارید یک ادرس برای ان تعیین نمایید. برای تعیین ادرس دستور زیر را در فایل کانفیگ وارد نمایید.
1
2
3
4
5
6
|
; Limits the PHP process from accessing files outside
; of specifically designated directories such as /var/www/html/
open_basedir=“/var/www/html/”
; ——————————————————
; Multiple dirs example
; open_basedir=“/home/httpd/vhost/cyberciti.biz/html/:/home/httpd/vhost/nixcraft.com/html/:/home/httpd/vhost/theos.in/html/”
|
مرحله پانزدهم – محافظت از بازنویسی فایل های کانفگ Mysql, PHP و Apache
برای محافظت میتوانید با استفاده از دستور chattr در لینوکس از باز نویسی فایل های کانفیگ جلوگیری نمایید. دستورات زیر را در ssh وارد نمایید. توجه داشته باشید ممکن است ادرس فایل تنظیمات شما متفاوت باشد که میتوانید ادرس مورد نظر را به ان بدهید.
1
2
3
4
5
|
# chattr +i /etc/php.ini
# chattr +i /etc/php.d/*
# chattr +i /etc/my.ini
# chattr +i /etc/httpd/conf/httpd.conf
# chattr +i /etc/
|
با استفاده از این دستور میتوانید فایل های php مهم را از بازنویسی محافظت نمایید.
امنیت قطعا به همین مراحل خلاصه نشده و روش های پیشرفته تری نیز دارد. هرچه سطح دسترسی ها محدود تر و امنیت افزایش یابد احتمال هک شدن کاهش میابد هرچند نمیتوان هیچگاه جلوی حملات را بصورت ۱۰۰% گرفت. به علاوه راهکار های بالا کانفیگ فایروال، نصب Mod_security، PHPIDS، PHPSecInfo و برسی لاگ نیز باعث افزایش امنیت خواهد. تهیه بکاپ برنامه ریزی شده فراموش نشود.