Security
سجل تدقيق في PostgreSQL لا يستطيع مدير قاعدة البيانات تعديله بصمت
يسجّل pgAudit ما يفعله الـ DBA، لكن superuser يستطيع إيقافه أو تعديل ملفاته. كيف تسد هذه الثغرات وفق الضابط 2-12 من ECC، وأين يأتي دور PGEE.

سؤال "هل لديكم سجل تدقيق؟" سهل، فأغلب الفرق تُري المدقق أن pgaudit مفعّلة. الصعوبة في السؤال التالي: يختار المدقق حساب DBA وتاريخًا محددًا، ويطلب كل ما نفّذه هذا الحساب في ذلك اليوم، ثم يسأل: كيف تثبتون أن صاحب الحساب لم يعدّل هذا السجل لاحقًا؟
PostgreSQL المجتمعي يجيب عن السؤال الأول جيدًا. أما الثاني فالمشكلة فيه بنيوية: سجل التدقيق يُكتب افتراضيًا في ملفات يملكها حساب نظام التشغيل نفسه الذي يشغّل الخادم، والمستخدم ذو الصلاحيات العليا (superuser) داخل قاعدة البيانات يستطيع التصرف بصلاحيات ذلك الحساب. نعرض هنا أين يمكن إيقاف السجل أو تعديله، وما يمكن إحكامه بـ PostgreSQL وpgAudit كما هما، وما يغيّره التدقيق في CYBERTEC PostgreSQL Enterprise Edition (PGEE).
ما الذي تطلبه الضوابط فعلًا
بالنسبة للجهات الخاضعة للضوابط الأساسية للأمن السيبراني من الهيئة الوطنية للأمن السيبراني، يطلب الضابط 2-12-3 في إصدار ECC-2:2024 تفعيل سجلات الأحداث على الأصول الحساسة وعلى الحسابات ذات الصلاحيات الهامة، وجمعها عبر نظام SIEM، ومراقبتها باستمرار، والاحتفاظ بها مدة لا تقل عن 12 شهرًا. ونموذج معيار إدارة سجلات الأحداث والمراقبة الصادر عن الهيئة أكثر تفصيلًا: فهو يذكر صراحةً نشاط الحسابات ذات الصلاحيات، والتغييرات على إعدادات الأنظمة، والتغييرات على إعدادات سجلات التدقيق نفسها، ضمن الأحداث الواجب تسجيلها، ويعدّ أحداث قواعد البيانات مصدرًا إلزاميًا.
ضع البندين الأخيرين معًا تجد أن إيقاف سجل التدقيق حدث يجب تسجيله هو أيضًا. فإذا استطاع DBA تعطيل pgAudit ساعة واحدة دون أن يترك أثرًا، فالإعداد لا يحقق الضابط حتى لو عمل pgAudit بلا خلل بقية السنة.
ماذا يسجّل pgAudit
يكتب pgAudit أسطرًا منظَّمة عبر آلية السجلات المعتادة في PostgreSQL. كل سطر يحمل نوع التدقيق (SESSION أو OBJECT)، ورقم العبارة ورقم العبارة الفرعية، والفئة، والأمر، ونوع الكائن واسمه الكامل، ونص العبارة. أما من نفّذ ومن أين ومتى، فيضيفها log_line_prefix.
تدقيق الجلسة يعمل بالفئات: READ وWRITE وFUNCTION وROLE وDDL وMISC وMISC_SET، ويمكن استثناء فئة كما في 'all, -misc'. أما تدقيق الكائنات فيعمل عبر دور: تضبط pgaudit.role = 'auditor' ثم تمنح هذا الدور الصلاحيات التي تريد تسجيلها على جداول بعينها. عندها يُسجَّل SELECT على payments.card لأن auditor يملك SELECT عليه، ولا يُسجَّل على جدول مرجعي عادي.
وبهذا الفصل يبقى حجم السجلات تحت السيطرة. تسجيل فئة READ لكل الجلسات على نظام معاملات مزدحم ينتج كمية كبيرة جدًا من الأسطر، بينما يتيح تدقيق الكائنات تسجيل القراءة على الجداول التي تحوي بيانات شخصية أو بيانات دفع فقط.
نقطة بداية معقولة:
# postgresql.confshared_preload_libraries = 'pgaudit'pgaudit.log = 'ddl, role, misc_set' # every sessionpgaudit.log_catalog = off # skip psql/driver catalog noisepgaudit.log_relation = on # one line per table touchedpgaudit.log_parameter = off # see the PDPL note belowpgaudit.role = 'auditor' # object auditing for sensitive tableslog_line_prefix = '%m [%p] %q%u@%d %r app=%a sess=%c 'log_connections = 'authentication,authorization' # PostgreSQL 18; use 'on' on 17 and olderlog_disconnections = on
CREATE EXTENSION pgaudit;CREATE ROLE auditor NOLOGIN;GRANT SELECT, INSERT, UPDATE, DELETE ON payments.card TO auditor;-- Privileged roles get full session auditingALTER ROLE dba_ops SET pgaudit.log = 'all, -misc';
في PostgreSQL 18 أصبح log_connections قائمة بمراحل الاتصال بدل قيمة on/off، وتُسجَّل محاولات المصادقة الفاشلة دائمًا بغض النظر عن قيمته.
تنبيه بخصوص pgaudit.log_parameter: عند تفعيله تُكتب قيم المعاملات في السجل كنص صريح. على جدول يحوي أرقام الهوية الوطنية مثلًا، يصبح سجل التدقيق نسخة ثانية من البيانات الشخصية، وهذه النسخة تحتاج بموجب نظام حماية البيانات الشخصية الحماية نفسها التي يحتاجها الجدول. اتركه معطّلًا إلا عند الحاجة لتحقيق محدد، وتعامل مع مخزن السجلات كبيانات حساسة في كل الأحوال.
خمس طرق يصمت بها السجل
لا شيء مما يلي خلل برمجي، فكله سلوك موثّق في PostgreSQL. جرّبها في بيئة الاختبار وانظر ماذا يسجّل إعدادك الحالي.
1. أمر SET على مستوى الجلسة. إعدادات pgAudit لا يغيّرها إلا superuser، وهذا يمنع المستخدمين العاديين. لكن superuser يستطيع تنفيذ SET pgaudit.log = 'none' والعمل دون تسجيل حتى نهاية الجلسة. أضف MISC_SET إلى الفئات العامة ليترك أمر SET نفسه سطرًا في السجل، وتحقق من ذلك على نسخة pgAudit لديك.
2. التجاوز على مستوى الدور. الأمر ALTER ROLE dba_ops SET pgaudit.log = 'none' يعطّل التدقيق في كل الجلسات القادمة لهذا الدور، ولا يظهر في postgresql.conf، فلن تكشفه مراجعة ملفات الإعداد. ابحث عنه في الكتالوج:
SELECT coalesce(r.rolname, '(all roles)') AS role, coalesce(d.datname, '(all databases)') AS db, s.setconfigFROM pg_db_role_setting sLEFT JOIN pg_roles r ON r.oid = s.setroleLEFT JOIN pg_database d ON d.oid = s.setdatabaseWHERE array_to_string(s.setconfig, ',') LIKE '%pgaudit%';
3. ALTER SYSTEM ثم إعادة تحميل الإعدادات. يستطيع superuser كتابة pgaudit.log = 'none' في postgresql.auto.conf ثم استدعاء pg_reload_conf(). عند إعادة التحميل يكتب الخادم السطر parameter "pgaudit.log" changed to "none". هذا السطر هو دليلك، بشرط أن يصل إلى مكان لا يصل إليه الـ DBA.
4. التصرف بصلاحيات حساب نظام التشغيل. الأمر COPY ... TO PROGRAM ينفّذ أمر shell بصلاحيات مستخدم نظام التشغيل الذي يشغّل PostgreSQL، ويتطلب superuser أو عضوية pg_execute_server_program. ولغات الإجراءات غير الموثوقة مثل plpython3u تنفّذ الكود بصلاحيات المستخدم نفسه. بأي منهما يستطيع superuser حذف ملفات السجل في log_directory أو تعديلها، لأن ذلك المستخدم هو مالكها. اعرف من يملك هذه القدرات:
SELECT rolname, 'superuser' AS why FROM pg_roles WHERE rolsuperUNION ALLSELECT r.rolname, g.rolnameFROM pg_roles rJOIN pg_auth_members m ON m.member = r.oidJOIN pg_roles g ON g.oid = m.roleidWHERE g.rolname IN ('pg_execute_server_program', 'pg_write_server_files', 'pg_read_server_files');SELECT lanname FROM pg_languageWHERE NOT lanpltrusted AND lanname NOT IN ('c', 'internal');
استعلام العضوية يُظهر المنح المباشرة فقط، والأدوار المتداخلة تحتاج فحصًا تكراريًا.
5. تغيير وجهة السجل. تغيير log_destination أو log_directory يرسل الأسطر القادمة إلى مكان آخر. إعادة التحميل تسجّل تغيير الإعداد، لكن قد يكون التغيير قد طُبّق على الوجهة الجديدة في تلك اللحظة.
في الحالات الخمس يتحكم superuser في PostgreSQL المجتمعي بما يُسجَّل وبالملفات التي تحفظه معًا. لا يوجد إعداد يسد هذا. الحل أن تنقل السجل خارج متناوله فور كتابته، وأن يترك أي تخفيض لمستوى التدقيق أثرًا خاصًا به.
إحكام الإعداد في PostgreSQL المجتمعي
قلّل عدد حسابات superuser. العمل اليومي للـ DBA لا يحتاجها. الأدوار المعرّفة مسبقًا مثل pg_monitor وpg_signal_backend وpg_read_all_data (من الإصدار 14) وpg_checkpoint (من الإصدار 15) تغطي أغلب المهام الروتينية. احتفظ بحساب superuser للطوارئ فقط، بمالك معروف بالاسم، ودقّقه بإعداد 'all, -misc'. وإرشادات الهيئة لإدارة الصلاحيات الهامة تطلب أصلًا ألا تُستخدم هذه الحسابات في المهام اليومية، فخطوة واحدة تغطي ضابطين.
أرسل السجلات خارج الخادم لحظة كتابتها. هناك نمطان عمليان:
log_destination = 'syslog'مع rsyslog يعيد توجيه الأسطر عبر TCP وTLS إلى نظام SIEM باستخدام طابور محفوظ على القرص. توثيق PostgreSQL ينبّه إلى أن syslog قد يُسقط رسائل تحت الضغط العالي، بينما صُمّم logging collector بحيث لا يفقد أي رسالة.إبقاء
logging_collector = onبصيغةjsonlogأوcsvlog، معlog_file_mode = 0640، وتشغيل أداة شحن سجلات بحساب نظام تشغيل مستقل له صلاحية القراءة عبر المجموعة دون الكتابة. تبقى الملفات المحلية كاملة، وتُرسل الأداة نسخة منها خلال ثوانٍ.
لا يغلق أي من النمطين النافذة تمامًا. من يعدّل الملف المحلي قبل أن تقرأه أداة الشحن يستطيع تغيير تلك النسخة. المكسب أن النسخة التي يراجعها المدقق تكون في نظام لا يملك الـ DBA صلاحية الكتابة عليه.
نبّه على لحظات الصمت. في SIEM، أنشئ تنبيهات على أي سطر يبدأ بـ parameter "pgaudit.، وعلى عبارات ALTER ROLE ... SET pgaudit وALTER SYSTEM، وعلى COPY ... TO PROGRAM، وعلى جلسة ذات صلاحيات نفّذت استعلامات دون أن تنتج أي سطر تدقيق. وشغّل استعلامي الكتالوج أعلاه بشكل دوري ونبّه على أي تغيير في نتيجتهما.
احسب مساحة الاحتفاظ قبل التشغيل. اثنا عشر شهرًا من تدقيق 'all' على الحسابات ذات الصلاحيات، إضافة إلى تدقيق الكائنات على الجداول الحساسة، بند تخزين حقيقي في الميزانية. قِس أسبوعًا من الحركة الفعلية في بيئة الاختبار واضرب الناتج. لا تخمّن.
أين يأتي دور التدقيق في PGEE
تذكر CYBERTEC التدقيق المؤسسي (Enterprise-class auditing) ضمن الميزات الأساسية في PGEE، وتصفه بأنه دعم متقدم للتدقيق مع ضمانات تمنع التعديل. والنقطة التصميمية المحددة، بحسب مواد CYBERTEC الأمنية عن PGEE، أن سجل التدقيق لا يُحفظ تحت مستخدم PostgreSQL، بل يُرسل إلى سياق مستخدم UNIX مختلف، فلا يستطيع الـ DBA تعديل سجلات تدقيقه.
هذا يعالج الطريقة الرابعة مباشرة. في الإعداد المجتمعي يستطيع الشخص الخاضع للتدقيق الوصول إلى ملفات السجل عبر حساب نظام التشغيل الذي يشغّل الخادم، أما في PGEE فيُكتب السجل تحت هوية نظام تشغيل منفصلة. وتبقى بقية الضوابط المذكورة أعلاه لازمة: تقليل حسابات superuser، والإرسال إلى SIEM، والتنبيه على تغيير الإعدادات، والاحتفاظ 12 شهرًا. PGEE لا يحل محل SIEM، ولا توجد ميزة في قاعدة بيانات تحقق الامتثال وحدها.
وبجانب التدقيق هناك مكوّنان آخران في PGEE. أداة pg_permissions تعرض الصلاحيات الموجودة فعليًا، وتقارنها بحالة مستهدفة معرّفة، وتُظهر الفرق، وهذا مفيد حين يسأل المدقق: من يستطيع قراءة هذا الجدول؟ وتشفير TDE في PGEE يغطي الجداول والفهارس وملفات WAL والملفات المؤقتة والنسخ الاحتياطية. ملفات سجل الخادم ليست ضمن هذه القائمة لدى CYBERTEC، لذا خطّط لحماية مخزن سجلات التدقيق بشكل مستقل.
عند تقييم PGEE، اطلب عرض فصل سجل التدقيق على إصدار PostgreSQL الذي تستخدمه خلال مرحلة إثبات المفهوم (PoC). اجعل حساب superuser يجرّب الطرق الخمس أعلاه، وتحقق مما يصل إلى السجل المنفصل وإلى SIEM. وبهذا يحصل فريق الأمن على دليل موثّق يحفظه في ملف الامتثال.
اختبار يمكنك تنفيذه هذا الأسبوع
فعّل الإعداد أعلاه في بيئة الاختبار مع إرسال السجلات إلى SIEM أو إلى جامع سجلات تجريبي.
نفّذ الطرق الخمس واحدة تلو الأخرى بحساب superuser.
تحقق في كل مرة: هل وصل إلى SIEM سجل يذكر الحساب والوقت والتغيير؟
عالج كل طريقة لم تترك أثرًا، ثم أعد الاختبار.
إذا كان فريقك ينتقل من Oracle أو SQL Server، فنفّذ هذا الاختبار قبل التشغيل الفعلي، ما دام تصميم الأدوار سهل التعديل.
تواصل مع Worlber
Worlber هي الموزّع المعتمد لـ CYBERTEC في المملكة العربية السعودية. نطبّق PGEE وندعمه من الرياض، بما في ذلك تصميم التدقيق، والربط مع SIEM، واختبار إثبات المفهوم الموضح أعلاه.
اطلب عرض سعر PGEE: https://worlber.sa/contact?subject=pgee-quote&utm_source=blog&utm_medium=cta&utm_campaign=postgresql-audit-logging-tamper-resistant-pgee
احصل على تقييم ترحيل مجاني: https://worlber.sa/contact?subject=migration&utm_source=blog&utm_medium=cta&utm_campaign=postgresql-audit-logging-tamper-resistant-pgee&utm_content=assessment
أو راسلنا على contactus@worlber.com
المصادر
صفحة PGEE لدى CYBERTEC: https://www.cybertec-postgresql.com/en/products/cybertec-postgresql-enterprise-edition/
CYBERTEC، Enterprise PostgreSQL Security (PDF): https://www.cybertec-postgresql.com/wp-content/uploads/2025/02/Enterprise-PostgreSQL-Security.pdf
توثيق pgAudit: https://github.com/pgaudit/pgaudit
توثيق PostgreSQL 18 للسجلات: https://www.postgresql.org/docs/18/runtime-config-logging.html
توثيق PostgreSQL 18 لأمر COPY: https://www.postgresql.org/docs/18/sql-copy.html
الضوابط الأساسية للأمن السيبراني ECC-2:2024: https://cdn.nca.gov.sa/api/files/public/upload/86e09090-44e4-481f-bc28-355673607654_ECC--2024-EN.pdf
الخطوة التالية
تحدث مع مهندسي Worlber
أرسل لنا بيئتك وهدفك. سنوضح لك ما يصلح، وما لا يصلح، والخطوة الآمنة التالية.