مقدّمة
من الممكن أن ننخدع بفكرة أنّ الخوادم لن تُهاجَم ما دام الخادوم جديدا، زواره قلائل أو أنّ المخترقين لن يستفيدوا شيئا من اختراقه. لكنّ العديد من الهجمات تكون مُؤتمتة وتُصمَّمُ خصيصا للبحث عن الأخطاء الشّائعة التي تُرتَكب عند ضبط الخادوم. تقوم هذه البرمجيات بفحص الشبكات لاكتشاف الخوادم فقط، ولا تكثرت بمحتواها.
تمكين الاتصالات الخارجيّة من أكثر الحالات الشّائعة التي قد تُؤدي إلى وصول غير مُصرّح إلى قاعدة بيانات PostgreSQL. يُمكن أن يحدث هذا لأنّ الإعدادات تسمح للبرمجيات باستكشاف الخوادم الضعيفة بسهولة.
في هذا الدّرس، سنلقي نظرة على كيفيّة تقليل خطر الوصول غير المُصرّح الذي يطرحه تفعيل الاتّصالات البعيدة (remote connections). ورغم أنّ هذه خطوة أولى بغاية الأهميّة، وبما أنّ الخوادم قد تتعرّض للاختراق بطرق أخرى، فإنّنا ننصح باتّخاذ إجراءات إضافيّة لحماية بياناتك، والتي يُمكنك أن تجدها في جزء "إجراءات إضافيّة لمزيد من الحماية” من هذا الدّرس.
الوضعيّة
لفهم الخطر الذي نحاول تخفيفه، تخيّل الخادوم على أنّه متجر صغير. إن كان المتجر يُنصت (listening) على أي منفذ (port)، فهذا يُكافئ قلب لافتة تُشير إلى أنّ المتجر "مفتوح”. أي أنّ الخادوم يكون مرئيّا على الشّبكة، ما يُمكّن البرمجيات المؤتمتة من إيجاده.
يُمكننا أن نتخيّل بأنّ كلّ منفذ عبارة عن طريقة للدّخول إلى المتجر، مثل باب أو نافذة مثلا. يُمكن لهذه المداخل أن تكون مفتوحة، مُغلقة، مُقفلة أو مُعطّلة حسب حالة البرمجيّة التي تقوم بالإنصات، لكنّ الإنصات على واجهة عامّة يعني بأنّ البرمجيات الخبيثة تستطيع مُحاولة الدّخول. فمثلا، يُمكن أن تُحاول البرمجيّة استعمال كلمة مرور افتراضيّة على أمل أنّها لم تتغيّر. يُمكن لها كذلك استغلال ثغرات أمنيّة موجودة في البرنامج الذي يُنصِتُ على أمل أنّها لم تُصلَح بعد. يُمكن مُحاولة العديد من الأساليب، إن تمكّنت البرمجيّة الخبيثة من إيجاد نقطة ضعف وقامت باستغلالها، فهذا يعني بأنّ الوصول إلى الخادوم سيتمّ بنجاح وسيتمكّن الهجوم من تخليف خسائر كبيرة.
إن قُمنا بتقييد عفريت (daemon) معيّن مثل postgresql
ليُنصت محليّا فقط، فهذا مُشابه لمحو الباب الذي يوصل إلى الخارج. ولن يُمكن مُحاولة أي شيء آخر للوصول إلى Postgres. تحمي الجدران النّاريّة (Firewalls) وشبكات VPN بطريقة مُشابهة. في هذا الدّرس، سنُركّز على حذف الباب العمومي الذي يوصل إلى PostgreSQL. لحماية العفريت أو البيانات أثناء نقلها أو تخزينها، انظر فقرة "إجراءات إضافيّة لمزيد من الحماية” من هذا الدّرس.
المُتطلّبات
سنستعمل في هذا الدّرس خادومي Ubuntu، الأول لمُضيف قاعدة البيانات والآخر ليعمل كعميل يتّصل بالمُضيف عن بُعد. يجب على كلّ خادوم أن يُجهَّز بمُستخدم sudo
وجدار ناري مُفعّل. يُمكنك الاستعانة بدرس الإعداد البدئي لخادوم Ubuntu.
مُضيف قاعدة البيانات PostgreSQL (Ubuntu 16.04)
إن لم تقم بتنصيب PostgreSQL بعد، يُمكنك القيام بذلك باستخدام الأوامر التّاليّة:
sudo apt-get update sudo apt-get install postgresql postgresql-contrib
آلة العميل (Ubuntu 16.04)
لاختبار تمكين الاتصالات البعيدة، سنستعمل عميل PostgreSQL psql
. لتنصيبها، استعمل الأوامر التّاليّة:
sudo apt-get update
sudo apt-get install postgresql-client
عند استيفاء هذه المُتطلبات، ستكون جاهزا لاتّباع هذا الدّرس.
فهم الإعداد الافتراضيّ
عند تنصيب PostgreSQL من مستودع حزم Ubuntu، فالخيار الافتراضيّ هو الانصات على المُضيف المحليّ (localhost). يُمكن تغيير هذا الخيار الافتراضي عبر تعديل مقطع listen_addresses
على ملفّ postgresql.conf
، لكنّ هذا الإعداد الافتراضي يمنع الخادوم من الانصات آليّا على واجهة عموميّة (public interface).
علاوة على ما سبق، فالملفّ pg_hba.conf
لا يسمح سوى لاتّصالات من مقابس أسماء نطاقات Unix/Linux (Unix/Linux domain sockets)، وعنوان الاسترجاع (loopback address) الخاصّ بالخادوم المحلي، ما يعني بأنّ الاتّصالات من مُضيفات خارجيّة لن تُقبَل:
# Put your actual configuration here
# ----------------------------------
#
# If you want to allow non-local connections, you need to add more
# "host" records. In that case you will also need to make PostgreSQL
# listen on a non-local interface via the listen_addresses
# configuration parameter, or via the -i or -h command line switches.
# DO NOT DISABLE!
# If you change this first entry you will need to make sure that the
# database superuser can access the database using some other method.
# Noninteractive access to all databases is required during automatic
# maintenance (custom daily cronjobs, replication, and similar tasks).
#
# Database administrative login by Unix domain socket
local all postgres peer
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
local all all peer
# IPv4 local connections:
host all all 127.0.0.1/32 md5
# IPv6 local connections:
host all all ::1/128 md5
هذه الإعدادات الافتراضيّة تُحقّق هدف منع الانصات على واجهة عموميّة. إن تركناها على حالها وأبقينا الجدار النّاري مُفعّلا، فهذا كلّ ما في الأمر! يُمكننا الآن الانتقال إلى قسم "إجراءات إضافيّة لمزيد من الحماية” للتّعرف على كيفيّة حماية البيانات أثناء نقلها.
إن أردت الاتصال من مُضيف بعيد، فسنتطرّق إلى كيفيّة تعديل الإعدادات الافتراضيّة إضافة إلى الخطوات التي يجب اتّخاذها فورا لحماية الخادوم في الفقرة التّاليّة.
إعداد الاتّصالات البعيدة (Remote Connections)
لإعداد بيئة إنتاج قويّة، وقبل بدء العمل مع بيانات حسّاسة، من المُفضّل تشفير مرور (traffic) PostgreSQL باستخدام SSL، إضافة إلى حماية باستخدام جدار ناري خارجي أو شبكة افتراضيّة خاصّة (VPN). قبل القيام بالأمور السابقة ذكرها، يُمكننا اتّخاذ طريق أقل تعقيدا عبر تفعيل جدار ناريّ على خادوم قاعدة البيانات الخاص بنا وتقييد الوصول لتقبل فقط المُضيفات التي تحتاج إلى الوصول إلى الخادوم.
الخطوة الأولى – إضافة مُستخدم وقاعدة بيانات
سنبدأ بإضافة مُستخدم وقاعدة بيانات لأغراض تجريبيّة. للقيام بذلك، سنستعمل عميل PostgreSQL psql
للاتصال بصفة المُستخدم الإداري postgres
. عبر تمرير الخيار -i
للأمر sudo
سيتمّ تشغيل صدفة تسجيل الدّخول (login shell) الخاصّة بالمُستخدم postgres
، ما يضمن بأنّ الخيارات في ملفّ .profile
أو في موارد أخرى مُتعلّقة بتسجيل الدّخول ستُحمَّل. يقوم الخيار -u
بتحديد المُستخدم postgres
:
sudo -i -u postgres psql
بعدها، سنقوم بإنشاء مُستخدم بكلمة مرور. تأكّد من استعمال كلمة مرور جيّدة عوضا عن المقطع mypassword
في المثال أسفله:
CREATE USER sammy WITH PASSWORD 'mypassword';
إن تمّ إنشاء المُستخدم بنجاح، فسنستقبل المُخرج التّالي:
CREATE ROLE
مُلاحظة: منذ الإصدار 8.1 من PostgreSQL، فالأدوار (ROLES) والمُستخدمون (USERS) يشتركون في المعنى.لكنّ هناك اتّفاقا يقول بأنّه إن كان لدور كلمة مرور فإنّنا نُسمّيه مُستخدما، ونُسمّي الدّور عديم كلمة المرور دورا، لذا أحيانا ستحصل على ROLE
في المُخرج رغم أنّك تتوقّع أن ترى USER
.
تاليّاََ، سنُنشئ قاعدة بيانات وسنمنح كامل صلاحيّات الوصول لمُستخدمنا الجديد. تقول أفضل الممارسات بمنح المُستخدمين صلاحيّات الوصول التي يجتاجونها فقط، وعلى الموارد التي يجب أن يحصلوا عليها فقط، لذا فاعتمادا على حالة الاستخدام ( use case)، قد يُفضّل تقييد أحقيّة الوصول للمُستخدم. .
CREATE DATABASE sammydb OWNER sammy;
عند إنشاء قاعدة البيانات بنجاح، سنستقبل التّأكيد التّالي:
CREATE DATABASE
بعد إنشاء المُستخدم وقاعدة البيانات، سنقوم بالخروج من سطر أوامر PostgreSQL:
\q
بعد الضغط على مفتاح ENTER، سنرجع إلى سطر الأوامر وسنكون جاهزين للمُتابعة.
الخطورة الثّانيّة – إعداد UFW
في درس الإعداد البدئي لخادوم Ubuntu ، قمنا بتفعيل UFW وسمحنا لاتّصالات SSH فقط. قبل بدء الإعداد، لنتحقّق من حالة UFW:
sudo ufw status
مُلاحظة: إن كان المخرج يدُلّ على أنّ الجدار النّاري غير مُفعّل (inactive)، يُمكننا تفعيله بالأمر التّالي:
sudo ufw enable
بعد التّفعيل، فإنّ إعادة تنفيذ الأمر sudo ufw status
سيستعرض القواعد الحاليّة. فعّل SSH إن كان ذلك مطلوبا:
sudo ufw allow OpenSSH
في حالة لم تُغيِّر من المُتطلّبات، فمُخرج الأمر sudo ufw status
سيُشير إلى أنّ OpenSSH هي الخدمة الوحيدة المُفعّلة:
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
بعد التّحقّق من حالة الجدار النّاري، سنقوم بالسماح بالوصول إلى منفذ PostgreSQL وسنُقيّد الوصول لنسمح فقط للمُضيف أو المُضيفات المرغوبة.
سيُضيف الأمر أسفله قاعدة للمنفذ الافتراضيّ لـPostgreSQL، أي المنفذ رقم 5432. إن غيّرت هذا المنفذ، فتأكّد من تعديل الأمر أسفله. تأكّد من استعمال عنوان IP الخاص بالخادوم الذي يحتاج إلى الوصول. أعد تنفيذ الأمر لإضافة كلّ عميل من العملاء الذين ترغب بإعطائهم أحقيّة الوصول إن كان ذلك لازما:
sudo ufw allow from client_ip_address to any port 5432
استبدل client_ip_address
بعنوان IP الخاصّ بالعميل.
للتّحقّق من أنّ القاعدة قد طُبِّقت، يُمكنك تنفيذ الأمر ufw status
مُجدّدا:
sudo ufw status
المُخرج:
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
5432 ALLOW client_ip_address
OpenSSH (v6) ALLOW Anywhere (v6)
مُلاحظة: إن لم تكن لديك دراية مُسبقة بأساسيّات UFW، يُمكنك تعلّم المزيد في درس أساسيات UFW: قواعد وأوامر شائعة للجدار الناري .
بعد تجهيز قاعدة الجدار النّاريّ هذه، سنقوم الآن بإعداد PostgreSQL لتُنصت على عنوان IP العمومي. سنقوم بهذا عبر تعديل إعدادَيْن، خانة للمُضيف المُتصل في pg_hba.conf
وإعداد listen_addresses
في postgresql.conf
.
الخطوة الثّالثة – إعداد المُضيفات المسموح لها (Allowed Hosts)
سنبدأ عبر إضافة خانة المُضيف في ملفّ pg_hba.conf
. إن كنت تستعمل نسخة أخرى غيْرَ النُّسخةِ 9.5 من PostgreSQL فتأكّد من تعديل الأمر أسفله قبل تنفيذه:
sudo nano /etc/postgresql/9.5/main/pg_hba.conf
سنضع أسطر host
تحت مقطع التّعليقات الذي يصف كيفيّة السّماح للاتصالات غير المحليّة. سنُضيف سطرا يحمل العنوان العمومي الخاص بخادوم قاعدة البيانات لاختبار ما إذا كان الجدار النّاري مُعدّا بشكل صحيح. استبدل المقطع client_ip_address
بعنوان IP الخاص بآلة العميل الخاصّ بك:
# If you want to allow non-local connections, you need to add more
# "host" records. In that case you will also need to make PostgreSQL
# listen on a non-local interface via the listen_addresses
# configuration parameter, or via the -i or -h command line switches.
host sammydb sammy client_ip_address/32 md5
قبل حفظ التغييرات، لننظر إلى كل قيمة من قيم السّطر الذي أضفناه في حالة كنت ترغب تعديل أي منها:
-
المُضيف، المُعامل
host
يُحدّد بأنّ اتّصال TCP/IP سيُستَعمَل. -
قاعدة البيانات، العمود الثّاني،
sammydb
، يُحدّد أي قاعدة بيانات يُمكن للمُضيف أن يتّصل بها، يُمكنك تعيين أكثر من قاعدة بيانات واحدة عبر تفرقة أسمائها بالفاصلة,
. -
المُستخدم،
sammy
، يُحدّد المُستخدم المسموح له بالاتّصال. وكما مع عمود قاعدة البيانات، فتستطيع تحديد أكثر من مستخدم واحد باستعمال علامة الفاصلة. - العنوان، يُحدّد عنوان آلة العميل ويُمكن أن يكون عبارة عن اسم مُضيف (hostname)، مجال عناوين IP (IP address range) أو كلمات مفتاحيّة خاصّة. في المثال أعلاه، قمنا بالسماح لعنوان IP الخاصّ بالعميل فقط.
-
طريقة الاستيثاق (auth-method)، في الأخير، يُمكن تحديد طريقة استيثاق، يُشير
md5
إلى كلمة مرور مزدوجة التّشفير بـMD5 ( double-MD5-hashed password ) لن تحتاج سوى كلمة المرور التي تم إنشاؤها للمُستخدم الذي سيقوم بالاتّصال.
للمزيد من المعلومات وإعدادات إضافيّة راجع التوثيق الرّسمي لـPostgreSQL حول ملفّ pg_hba.conf.
بعد الانتهاء من التّعديلات، احفظ وأغلق الملف.
الخطوة الرّابعة – إعداد عنوان الإنصات (Listening Address)
سنقوم الآن بضبط عنوان الإنصات في ملفّ postgresql.conf
(تأكّد من تصحيح رقم النّسخة):
sudo nano /etc/postgresql/9.5/main/postgresql.conf
أضف عناوين الإنصات تحت سطر listen_addresses
، تأكّد من استبدال server_ip_address
بعنوان IP أو اسم مُضيف قاعدة البيانات الخاصّة بك وليس عنوان العميل الذي سيقوم بالاتصال:
#listen_addresses = 'localhost' # what IP address(es) to listen on;
listen_addresses = 'localhost,server_ip_address'
احفظ وأغلق الملفّ عند الانتهاء من إجراء التّعديلات.
الخطوة الخامسة – إعادة تشغيل PostgreSQL
لن تُطبَّق التعديلات حتى نُعيد تشغيل عفريت (daemon) PostgreSQL، لذا سنقوم بهذا قبل أن نبدأ بالتجربة:
sudo systemctl restart postgresql
وبما أنّ systemctl
لا يوفّر تغذيّة راجعة (feedback)، فسنتحقّق من نجاح إعادة تشغيل العفريت:
sudo systemctl status postgresql
إن احتوى المُخرج على Active: active
وانتهى بمقطع مُشابه لما يلي، فهذا يعني بأنّ عفريتPostgreSQL مُفعّل.
...
Jan 10 23:02:20 PostgreSQL systemd[1]: Started PostgreSQL RDBMS.
بعد إعادة تشغيل العفريت، يُمكننا الآن التّجربة.
الخطوة السّادسة – تجربة الاتّصال
لنتحقّق من أنّنا نستطيع الاتّصال من جهاز العميل الخاص بنا. للقيام بهذا، سنستعمل الأمر psql
مع الخيّار -U
لتحديد المُستخدم، الخيار -h
لتحديد عنوان IP الخاصّ بالعميل و -d
لتحديد قاعدة البيانات، وذلك لأنّنا ضيّقنا الحماية لكي يتمكّن sammy
فقط من الاتّصال بقاعدة بيانات واحدة فقط.
psql -U sammy -h postgres_host_ip -d sammydb
استبدل postgres_host_ip
بعنوان IP الخاصّ بمُضيف PostgreSQL.
إن تمّ إعداد كل شيء بشكل صحيح، فيجب أن تستقبل المحثَّ (prompt) التّالي:
Password for user sammy:
أدخل كلمة المرور التّي حدّدتها مسبقا عندما أضفت المُستخدم sammy
في مرقاب (monitor) PostgreSQL.
إن حصلت على المحثّ التّالي، فهذا يعني بأنّ الاتصال قد تمّ بنجاح:
sammydb=>
هذا يُؤكّد على أنّنا نستطيع تجاوز الجدار النّاري وأن نتّصل بقاعدة البيانات. سنقوم الآن بالخروج من المحثّ:
\q
بعد التّحقّق من أنّ الإعدادات قد ضُبِطت بنجاح، سنقوم بتنظيف مُخلّفات التّجربة.
الخطوة السّابعة – حذف قاعدة البيانات والمُستخدم التّجريبيّين
بعد اختبار الاتّصال، يُمكننا الآن العودة إلى المُضيف واستخدام الأمر التّالي لحذف قاعدة البيانات والمُستخدم.
sudo -i -u postgres psql
لحذف قاعدة البيانات:
DROP DATABASE sammydb;
عند نجاح العمليّة، ستستقبل المُخرج التّالي:
DROP DATABASE
لحذف المُستخدم:
DROP USER sammy;
المُخرج عند نجاح العمليّة:
DROP ROLE
سنقوم بإنهاء عمليّة التّنظيف بحذف خانة المُضيف الخاصّة بقاعدة البيانات sammydb
من ملفّ pg_hba.conf
لأنّنا لم نعد نحتاج إليها:
sudo nano /etc/postgresql/9.5/main/pg_hba.conf
استبدل 9.5
برقم النّسخة الخاصّة بك.
السّطر الذي يجب عليك حذفه:
host sammydb sammy client_ip_address/32 md5
ليُطبَّقَ التّعديل، سنقوم بحفظ وإغلاق الملفّ ومن ثمّ نُعيد تشغيل خادوم قاعدة البيانات:
sudo systemctl restart postgresl
للتحقّق من أنّ إعادة التّشغيل قد تمّت بنجاح، سنطّلع على الحالة:
sudo systemctl status postgres
إن كان المُخرج يحتوي على Active: active
فهذا يعني بأنّ إعادة التّشغيل قد تمّت بنجاح.
يُمكنك الآن ضبط التّطبيق أو الخدمة على العميل التي تحتاج إلى إمكانيّة الاتصال عن بعد.
خاتمة
اتّخذنا في هذا الدّرس الخطوات الأساسيّة لحماية PostgreSQL عبر إعداد الجدار النّاريّ الخاصّ بالخادوم ليسمح فقط للاتصالات من المُضيفات التي تحتاج إلى صلاحيّات الوصول وعبر ضبط PostgreSQL لتقبل الاتصالات من هذه المُضيفات فقط. هذا يُخفّف من خطر بعض من أنواع الهجمات. تعتبر هذه الإجراءات الخطوة الأولى فقط لحماية البيانات، وننصح بمراجعة واتّخاذ الإجراءات الأمنية الإضافيّة المذكورة أعلاه.
ترجمة -بتصرّف- للمقال How To Secure PostgreSQL Against Automated Attacks لصاحبته Melissa Anderson.
تم التعديل في بواسطة zahershullar
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.