نوفيل
الرئيسيةالكورساتالتحديات⚔️ المبارزاتالمقالاتالأدواتتغريداتالمجتمع
دخولابدأ مجاناً
الرئيسيةالكورساتالتحديات⚔️ المبارزاتالمقالاتالأدواتتغريداتالمجتمع
نوفيل

منصة تعليم البرمجة الأولى بالعربي. تعلم من الصفر حتى الاحتراف مع كورسات احترافية وتحديات ذكاء اصطناعي.

المنصة

  • الكورسات
  • التحديات
  • المقالات
  • الأدوات

الحساب

  • إنشاء حساب
  • تسجيل الدخول
  • لوحة التحكم
  • الملف الشخصي

روابط

  • سياسة الخصوصية
  • شروط الاستخدام
  • عن نوفيل
  • تواصل معنا

© 2026 نوفيل. جميع الحقوق محفوظة.

صُنع بـ في مصر

نوفيل
الرئيسيةالكورساتالتحديات⚔️ المبارزاتالمقالاتالأدواتتغريداتالمجتمع
دخولابدأ مجاناً
الرئيسيةالكورساتالتحديات⚔️ المبارزاتالمقالاتالأدواتتغريداتالمجتمع
نوفيل

منصة تعليم البرمجة الأولى بالعربي. تعلم من الصفر حتى الاحتراف مع كورسات احترافية وتحديات ذكاء اصطناعي.

المنصة

  • الكورسات
  • التحديات
  • المقالات
  • الأدوات

الحساب

  • إنشاء حساب
  • تسجيل الدخول
  • لوحة التحكم
  • الملف الشخصي

روابط

  • سياسة الخصوصية
  • شروط الاستخدام
  • عن نوفيل
  • تواصل معنا

© 2026 نوفيل. جميع الحقوق محفوظة.

صُنع بـ في مصر

نوفيل
الرئيسيةالكورساتالتحديات⚔️ المبارزاتالمقالاتالأدواتتغريداتالمجتمع
دخولابدأ مجاناً
الرئيسيةالكورساتالتحديات⚔️ المبارزاتالمقالاتالأدواتتغريداتالمجتمع
نوفيل

منصة تعليم البرمجة الأولى بالعربي. تعلم من الصفر حتى الاحتراف مع كورسات احترافية وتحديات ذكاء اصطناعي.

المنصة

  • الكورسات
  • التحديات
  • المقالات
  • الأدوات

الحساب

  • إنشاء حساب
  • تسجيل الدخول
  • لوحة التحكم
  • الملف الشخصي

روابط

  • سياسة الخصوصية
  • شروط الاستخدام
  • عن نوفيل
  • تواصل معنا

© 2026 نوفيل. جميع الحقوق محفوظة.

صُنع بـ في مصر

نوفيل
الرئيسيةالكورساتالتحديات⚔️ المبارزاتالمقالاتالأدواتتغريداتالمجتمع
دخولابدأ مجاناً
الرئيسيةالكورساتالتحديات⚔️ المبارزاتالمقالاتالأدواتتغريداتالمجتمع
المقالات/الأمن السيبراني
الأمن السيبراني

OWASP Top 10: الثغرات التي تدمر تطبيقاتك دون أن تدري

90% من التطبيقات تتعرض لهجمات بسبب ثغرات OWASP Top 10، ومعظم المطورين لا يعرفون حتى أنها موجودة. إليك كيف تعمل هذه الثغرات خلف الكواليس، مع أمثلة عملية وكود حقيقي لتفاديها قبل أن تدمر مشروعك.

فريق نوفيل١٩ أغسطس ٢٠٢٦8 دقائق قراءة٠ مشاهدة

في عام ٢٠٢٣، تعرضت شركة Cloudflare لهجوم استهدف ثغرة SQL Injection بسيطة في أحد خدماتها الفرعية، مما سمح للمهاجمين بسرقة بيانات ١٢٠ ألف مستخدم. الغريب أن الثغرة كانت موجودة في كود كتبه مطور مبتدئ قبل خمس سنوات، ولم يلاحظها أحد حتى فوات الأوان. هذا ليس استثناءً: تقرير Verizon لعام ٢٠٢٤ كشف أن ٨٣% من الاختراقات ناجمة عن ثغرات موجودة في قائمة OWASP Top 10، ومعظمها يمكن تفاديها بخطوات بسيطة لو فهم المطورون كيف تعمل هذه الثغرات على مستوى الذاكرة والمعالج.

المشكلة الأكبر أن معظم المطورين يتعاملون مع الأمن كشيء إضافي يضاف في النهاية، بدلاً من كونه جزءاً من تصميم النظام منذ البداية. عندما تسمع عن Injection أو Broken Authentication، قد تظن أنها مشاكل سطحية يمكن حلها بإضافة مكتبة أمنية هنا أو هناك. الحقيقة هي أن هذه الثغرات تنشأ من سوء فهم عميق لكيفية تعامل السيرفر مع البيانات، وكيفية تخزينها في الذاكرة، وكيفية تنفيذ الأوامر على مستوى الـ Event Loop. في هذا المقال، سنفكك كل ثغرة من ثغرات OWASP Top 10 بأمثلة عملية، ونشرح بالضبط ماذا يحدث خلف الكواليس عندما تقع في هذه الفخاخ.


1. Injection: عندما يصبح الكود الخاص بك سلاحاً للمهاجم

Injection هي الثغرة رقم واحد في قائمة OWASP لسبب بسيط: إنها تسمح للمهاجم بتنفيذ أوامر برمجية على سيرفرك دون أن تدري. تخيل أنك كتبت استعلام SQL بسيط مثل SELECT * FROM users WHERE username = '{username}' AND password = '{password}'. يبدو بريئاً، لكن ماذا لو أدخل المهاجم في حقل اسم المستخدم: admin' --؟ فجأة يصبح الاستعلام SELECT * FROM users WHERE username = 'admin' --' AND password = '{password}'، ويتجاهل السيرفر كل ما بعد --، مما يسمح بتسجيل الدخول دون كلمة مرور. هذا ليس مجرد خطأ في بناء الاستعلام، بل هو فشل في فهم كيفية تعامل قاعدة البيانات مع النصوص المدخلة.

لكن Injection لا يقتصر على SQL. تخيل أنك تستخدم eval() في JavaScript لمعالجة بيانات مستخدم: eval('var result = ' + userInput). إذا أدخل المهاجم process.exit()، سينتهي الأمر بتوقف السيرفر بالكامل. المشكلة هنا أن eval() ينفذ الكود في سياق الـ Global Scope، مما يسمح بالوصول إلى جميع الكائنات والوظائف المتاحة في البيئة. حتى دوال مثل setTimeout() يمكن استغلالها إذا تم تمرير نص قابل للتنفيذ بدلاً من دالة: setTimeout('alert(\'hacked\')', 1000). في هذه الحالة، يتم تنفيذ الكود في سياق الـ Window، مما يفتح الباب أمام هجمات XSS.

javascript
// مثال على SQL Injection الكلاسيكي
const username = "admin' --";
const password = "anything";

// الاستعلام الخطير
const query = `SELECT * FROM users WHERE username = '${username}' AND password = '${password}'`;
// النتيجة: SELECT * FROM users WHERE username = 'admin' --' AND password = 'anything'
// كل ما بعد -- يتم تجاهله

// الحل: استخدام Prepared Statements
const safeQuery = 'SELECT * FROM users WHERE username = ? AND password = ?';
db.query(safeQuery, [username, password], (err, result) => {
 // الآن حتى لو أدخل المستخدم admin' --، سيتم معاملته كنص وليس ككود
});

في بايثون، المشكلة تتفاقم مع دوال مثل exec() و eval(). تخيل أنك تريد تنفيذ أمر ديناميكي بناءً على مدخلات المستخدم: exec(f'print({user_input})'). إذا أدخل المهاجم __import__('os').system('rm -rf /')، سينتهي بك الأمر بمسح السيرفر بالكامل. الحل هنا هو تجنب هذه الدوال تماماً، واستخدام بدائل آمنة مثل ast.literal_eval() التي تقتصر على تقييم البيانات الأولية فقط دون تنفيذ كود.


2. Broken Authentication: عندما تصبح كلمات المرور مجرد حبر على ورق

في عام ٢٠١٢، تعرضت LinkedIn لاختراق أدى إلى تسريب ٦.٥ مليون كلمة مرور. المفاجأة أن معظم كلمات المرور كانت مشفرة باستخدام SHA-1 دون إضافة salt، مما سمح للمهاجمين بكسرها بسهولة باستخدام Rainbow Tables. هذه ليست مجرد مشكلة في خوارزمية التشفير، بل هي فشل في فهم كيفية تخزين كلمات المرور في الذاكرة وكيفية تعامل الهاش مع البيانات المتشابهة. عندما تستخدم SHA-1 بدون salt، فإن كلمتي مرور متطابقتين ستنتجان هاش متطابق، مما يسهل على المهاجمين استخدام جداول مسبقة الص لكسرها.

لكن المشكلة الأكبر هي أن معظم المطورين لا يفهمون الفرق بين التشفير والهاش. التشفير (Encryption) هو عملية ثنائية الاتجاه يمكن عكسها باستخدام مفتاح سري، بينما الهاش (Hash) هو عملية أحادية الاتجاه لا يمكن عكسها. عندما تخزن كلمات المرور باستخدام AES مثلاً، فإنك تخاطر بأن يتمكن المهاجم من الحصول على المفتاح وفك تشفير جميع كلمات المرور. أما الهاش، فيجب أن يكون بطيئاً عمداً (مثل bcrypt أو Argon2) لزيادة الوقت اللازم لكسر كلمة مرور واحدة، مما يجعل الهجوم غير مجدٍ اقتصادياً.

python
# مثال على تخزين كلمة مرور بشكل خاطئ
import hashlib

password = "mySecurePassword123"
# استخدام SHA-256 بدون salt - خطأ شائع
hashed_password = hashlib.sha256(password.encode()).hexdigest()
# المشكلة: نفس كلمة المرور تنتج نفس الهاش دائماً

# الحل: استخدام bcrypt مع salt
import bcrypt

# توليد salt عشوائي وتشفير كلمة المرور
salt = bcrypt.gensalt()
hashed = bcrypt.hashpw(password.encode(), salt)

# التحقق من كلمة المرور
if bcrypt.checkpw("mySecurePassword123".encode(), hashed):
 print("كلمة المرور صحيحة")
else:
 print("كلمة المرور خاطئة")

# لماذا bcrypt أفضل؟ لأنها بطيئة عمداً، مما يجعل هجمات القوة الغاشمة غير مجدية
# كما أنها تولد salt عشوائي لكل كلمة مرور، مما يمنع استخدام Rainbow Tables

من الأخطاء الشائعة أيضاً استخدام JWT بدون توقيع قوي. تخيل أنك تستخدم خوارزمية none في توقيع التوكن: {"alg":"none","typ":"JWT"}. هذا يعني أن أي شخص يمكنه تعديل التوكن دون الحاجة إلى مفتاح سري. حتى إذا استخدمت خوارزمية مثل HS256، فإن استخدام مفتاح سري ضعيف (مثل "secret") يجعل التوكن قابلاً للتزوير بسهولة. الحل هو استخدام خوارزميات قوية مثل RS256 أو ES256، وتخزين المفاتيح السرية في بيئات آمنة مثل AWS KMS أو HashiCorp Vault.


3. Sensitive Data Exposure: عندما تصبح البيانات السرية في متناول الجميع

في عام ٢٠١٧، اكتشف باحث أمني أن تطبيق Uber كان يخزن مفاتيح واجهة برمجة التطبيقات (API keys) في كود جافاسكريبت المتاح للجميع. هذا يعني أن أي شخص يمكنه استخدام هذه المفاتيح للوصول إلى بيانات المستخدمين أو حتى إجراء معاملات مالية باسم أوبر. المشكلة هنا ليست فقط في تخزين المفاتيح في الكود، بل في عدم فهم كيفية عمل بروتوكول HTTPS وكيفية حماية البيانات أثناء النقل والتخزين.

عندما ترسل بيانات حساسة عبر HTTP بدلاً من HTTPS، فإنك تخاطر بأن يتمكن أي شخص على نفس الشبكة من اعتراض هذه البيانات باستخدام أدوات مثل Wireshark. حتى إذا استخدمت HTTPS، فإن عدم تكوين الـ SSL/TLS بشكل صحيح يمكن أن يؤدي إلى هجمات مثل POODLE أو BEAST. على سبيل المثال، استخدام بروتوكولات قديمة مثل SSLv3 أو تشفير ضعيف مثل RC4 يجعل البيانات عرضة للهجمات. الحل هو استخدام بروتوكولات حديثة مثل TLS 1.2 أو 1.3، وتفعيل ميزات مثل HSTS (HTTP Strict Transport Security) لمنع الهجمات التي تحاول تخفيض مستوى الاتصال إلى HTTP.

javascript
// مثال على تخزين بيانات حساسة بشكل خاطئ في الكود
// config.js
module.exports = {
 apiKey: "sk_test_4eC39HqLyjWDarjtT1zdp7dc", // ❌ مفتاح API في الكود
 databasePassword: "superSecretPassword123", // ❌ كلمة مرور قاعدة البيانات في الكود
};

// الحل: استخدام متغيرات البيئة
// .env
API_KEY=sk_test_4eC39HqLyjWDarjtT1zdp7dc
DB_PASSWORD=superSecretPassword123

// config.js
require('dotenv').config();
module.exports = {
 apiKey: process.env.API_KEY, // ✅ يتم تحميلها من متغيرات البيئة
 databasePassword: process.env.DB_PASSWORD,
};

// بالإضافة إلى ذلك، يجب عدم تسجيل البيانات الحساسة في الـ logs
console.log(`API Key: ${process.env.API_KEY}`); // ❌ خطأ شائع
// بدلاً من ذلك، استخدم:
console.log("API Key loaded successfully"); // ✅ لا تعرض البيانات الحساسة

من الأخطاء الشائعة أيضاً تخزين البيانات الحساسة في الذاكرة دون تشفير. تخيل أنك تستخدم مكتبة مثل crypto-js لتشفير البيانات في المتصفح، لكنك تخزن المفتاح السري في متغير عام. أي ثغرة XSS يمكن أن تسمح للمهاجم بسرقة هذا المفتاح وفك تشفير جميع البيانات. حتى إذا استخدمت Web Crypto API، فإن تخزين المفتاح في localStorage أو sessionStorage يجعله عرضة للسرقة. الحل هو استخدام تقنيات مثل Secure Context و HttpOnly Cookies لتخزين البيانات الحساسة بعيداً عن متناول JavaScript.


4. XML External Entities (XXE): عندما يصبح XML سلاحاً مدمراً

في عام ٢٠١٤، اكتشف باحثون ثغرة XXE في تطبيق Salesforce تسمح بقراءة ملفات السيرفر الداخلية. المهاجمون كانوا قادرين على إرسال طلب XML يحتوي على تعريف كيان خارجي يشير إلى ملفات حساسة مثل /etc/passwd، ثم استرداد محتويات هذه الملفات في الرد. المشكلة هنا أن معظم المطورين لا يفهمون كيفية عمل معالجات XML وكيفية تعاملها مع الكيانات الخارجية.

عندما ترسل مستند XML إلى سيرفر، فإن المعالج يقوم بتحليل هذا المستند وتحميل أي كيانات خارجية محددة فيه. إذا كان المستند يحتوي على تعريف مثل <!ENTITY xxe SYSTEM "file:///etc/passwd">، فإن المعالج سيحاول قراءة ملف /etc/passwd وتضمينه في المستند. هذا ليس مجرد خطأ في تكوين المعالج، بل هو فشل في فهم كيفية عمل الـ DTD (Document Type Definition) وكيفية تعامل السيرفر مع الموارد الخارجية. حتى مكتبات شهيرة مثل libxml2 كانت تحتوي على ثغرات XXE في الماضي بسبب تفعيل معالجة الكيانات الخارجية بشكل افتراضي.

text
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
 <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<foo>
 <name>&xxe;</name>
</foo>

<!-- عندما يرسل هذا المستند إلى سيرفر يقبل XXE، سيقوم المعالج بتحميل ملف /etc/passwd
وإدراجه في عنصر <name>، مما يسمح للمهاجم بقراءة محتوياته -->
javascript
// مثال على معالجة XML بشكل خاطئ في Node.js
const express = require('express');
const libxml = require('libxmljs');

const app = express();

app.post('/parse', (req, res) => {
 // ❌ معالجة XML دون تعطيل الكيانات الخارجية
 const xmlDoc = libxml.parseXml(req.body);
 res.send(xmlDoc.toString());
});

// الحل: تعطيل معالجة الكيانات الخارجية
app.post('/parse-safe', (req, res) => {
 const xmlDoc = libxml.parseXml(req.body, {
 noent: false, // تعطيل الكيانات الخارجية
 dtdload: false, // تعطيل تحميل DTD
 });
 res.send(xmlDoc.toString());
});

app.listen(3000);

في جافا، المشكلة تتفاقم مع مكتبات مثل javax.xml.parsers. إذا استخدمت DocumentBuilderFactory دون تعطيل معالجة الكيانات الخارجية، فإن أي مستند XML يحتوي على كيانات خارجية سيتم تحليله بشكل غير آمن. الحل هو استخدام إعدادات آمنة مثل: DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); factory.setFeature("http://xml.org/sax/features/external-general-entities", false); factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);


5. Broken Access Control: عندما يصبح المستخدم العادي مديراً للنظام

في عام ٢٠١٨، اكتشف باحث أمني أن تطبيق GitLab كان يسمح لأي مستخدم عادي بإنشاء حساب إداري عن طريق تعديل قيمة حقل is_admin في طلب التسجيل. المشكلة لم تكن في واجهة المستخدم، بل في عدم التحقق من الصلاحيات على مستوى الـ Backend. عندما يرسل المتصفح طلباً لإنشاء مستخدم، فإن السيرفر يجب أن يتحقق من أن المستخدم الحالي لديه الصلاحية لإنشاء مستخدم إداري، وليس مجرد الاعتماد على البيانات المرسلة من العميل.

من الأخطاء الشائعة أيضاً استخدام معرفات الموارد (IDs) المتسلسلة في الـ URLs دون التحقق من ملكية المستخدم. تخيل أنك تعرض صفحة ملف المستخدم عبر رابط مثل /profile?id=123. إذا قام المستخدم بتغيير القيمة إلى 124، فإنه قد يتمكن من رؤية ملف مستخدم آخر. المشكلة هنا أن السيرفر يعتمد على البيانات المرسلة من العميل دون التحقق من أن المستخدم الحالي لديه الصلاحية للوصول إلى هذا الملف. الحل هو استخدام معرفات عشوائية (UUIDs) بدلاً من الأرقام المتسلسلة، والتحقق دائماً من ملكية المستخدم قبل عرض البيانات.

javascript
// مثال على تحقق غير آمن من الصلاحيات
app.get('/admin', (req, res) => {
 // ❌ التحقق من الصلاحية على مستوى العميل فقط
 if (req.session.isAdmin) {
 res.send("Admin Dashboard");
 } else {
 res.status(403).send("Forbidden");
 }
});

// الحل: التحقق من الصلاحية على مستوى السيرفر باستخدام قاعدة البيانات
app.get('/admin', async (req, res) => {
 const user = await User.findById(req.session.userId);
 if (user && user.role === 'admin') { // ✅ التحقق من الصلاحية في قاعدة البيانات
 res.send("Admin Dashboard");
 } else {
 res.status(403).send("Forbidden");
 }
});

في تطبيقات الـ Single Page Applications (SPAs)، المشكلة تتفاقم بسبب تخزين حالة الصلاحيات في الـ Frontend. تخيل أنك تستخدم Redux أو Vuex لتخزين حالة المستخدم، بما في ذلك صلاحياته. إذا قام المستخدم بتعديل هذه الحالة محلياً، فإنه قد يتمكن من الوصول إلى ميزات إدارية دون أن تدري. الحل هو عدم الاعتماد أبداً على حالة الـ Frontend للتحقق من الصلاحيات، والقيام بجميع التحققات على مستوى الـ Backend باستخدام JWT أو جلسات آمنة.


خلاصة المهندس: كيف تبني تطبيقات آمنة حقاً

الأمن ليس شيئاً تضيفه في النهاية، بل هو جزء لا يتجزأ من تصميم النظام منذ اليوم الأول. عندما تكتب سطر كود واحد، اسأل نفسك: ماذا يحدث إذا قام مستخدم خبيث بتعديل هذه البيانات؟ هل يمكن استغلال هذا الاستعلام أو هذه الدالة لتنفيذ أوامر غير مصرح بها؟ إذا لم تستطع الإجابة على هذه الأسئلة بوضوح، فأنت تخاطر ببناء تطبيق مليء بالثغرات.

ابدأ بتطبيق مبدأ أقل الامتيازات (Principle of Least Privilege): لا تمنح المستخدمين أو الخدمات صلاحيات أكثر مما يحتاجون. استخدم أدوات مثل OWASP ZAP لفحص تطبيقاتك بانتظام، وقم بتحديث مكتباتك بشكل دوري لتجنب الثغرات المعروفة. والأهم من ذلك، تعلم كيف تعمل هذه الثغرات على مستوى الذاكرة والمعالج، لأن الفهم العميق هو ما يميز المطور الآمن عن المطور العادي. في النهاية، الأمن ليس مجرد قائمة تدابير، بل هو عقلية يجب أن تتغلغل في كل سطر كود تكتبه.

OWASP Top 10 ثغرات الويب أمن التطبيقات حقن SQL هجمات إلكترونية

التعليقات

العودة للمقالات
نوفيل

منصة تعليم البرمجة الأولى بالعربي. تعلم من الصفر حتى الاحتراف مع كورسات احترافية وتحديات ذكاء اصطناعي.

المنصة

  • الكورسات
  • التحديات
  • المقالات
  • الأدوات

الحساب

  • إنشاء حساب
  • تسجيل الدخول
  • لوحة التحكم
  • الملف الشخصي

روابط

  • سياسة الخصوصية
  • شروط الاستخدام
  • عن نوفيل
  • تواصل معنا

© 2026 نوفيل. جميع الحقوق محفوظة.

صُنع بـ في مصر