أمان التطبيقات
درس 2 من 4
2أمان التطبيقات
الصورة الكبيرةأغلب الاختراقات لا تحتاج عبقرية. تحتاج مدخلًا لم يُتحقق منه، أو رابطًا يغيّر فيه المهاجم رقمًا فيرى بيانات غيره، أو مكتبة قديمة بثغرة معروفة.
ماذا تشاهد في الرسم: خط الدفاع لكل طلب: التحقق من المدخل، ثم الصلاحية، ثم الاستعلام الآمن، ثم الهروب عند العرض.
خارطة هذا الجزء
المفاهيم بالترتيب، اضغط أيًّا منها للقفز إليه:
طريقان إلى نفس الفكرة
بيتك آمن ليس بقفل واحد قوي، بل بعادات: تقفل كل باب، لا تعطي المفتاح لأي أحد، تسأل من يطرق قبل أن تفتح، وتصلح النافذة المكسورة فورًا. الأمان في الكود عادات مشابهة تتكرر في كل طلب.
OWASP Top 10: (1) كسر التحكم بالوصول، مثل IDOR حين يغيّر المستخدم /invoices/7 إلى 8، والحل فحص الملكية في الخادم لكل مورد. (2) فشل التشفير: كلمات المرور بـ bcrypt أو argon2 أو scrypt بملح، لا MD5 أو SHA256 مجردة. (3) الحقن: استعلامات بمعاملات دائمًا، ولا eval أو shell بمدخلات. XSS: الهروب عند العرض وCSP. CSRF: رموز CSRF وملفات تعريف SameSite. أيضًا: الإعدادات الخاطئة (DEBUG في الإنتاج)، المكونات الضعيفة (pip-audit، npm audit، Dependabot)، والتسجيل والمراقبة لاكتشاف الهجوم. وحدّد المعدّل على تسجيل الدخول.
قبل أن تبدأ
🗄️SQL
تكتب استعلامات بمعاملات.
🔐HTTPS والتشفير
درس DNS والتشفير في مسار الإنترنت.
الفكرة الجوهرية
1الحقن: هاجم كودك
نفس الاستعلام مرتين: مرة بدمج النص، ومرة بمعاملات. المدخل الخبيث يكسر الأول ويفشل في الثاني:
import sqlite3
db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE users (name TEXT, is_admin INTEGER)")
db.executemany("INSERT INTO users VALUES (?, ?)", [("sara", 0), ("admin", 1)])
attack = "nobody' OR '1'='1"
unsafe = f"SELECT name FROM users WHERE name = '{attack}'"
print("string-built :", db.execute(unsafe).fetchall())
safe = "SELECT name FROM users WHERE name = ?"
print("parameterised:", db.execute(safe, (attack,)).fetchall())2كلمات المرور
لا تخزن كلمة المرور ولا تجزئة سريعة لها. استخدم دالة بطيئة عمدًا بملح عشوائي لكل مستخدم، فلو سُرقت القاعدة يصبح التخمين مكلفًا جدًا:
import hashlib
import hmac
import os
def hash_password(password, salt=None):
salt = salt or os.urandom(16)
digest = hashlib.scrypt(password.encode(), salt=salt, n=2**14, r=8, p=1)
return salt, digest
def verify(password, salt, digest):
_, candidate = hash_password(password, salt)
return hmac.compare_digest(candidate, digest)
salt, stored = hash_password("correct horse battery")
print("right password:", verify("correct horse battery", salt, stored))
print("wrong password:", verify("123456", salt, stored))
_, other = hash_password("correct horse battery")
print("same password, same hash for two users?", other == stored)hashlib.sha256(password) لأنه «تشفير». SHA256 سريع جدًا، فالمهاجم يجرّب مليارات الكلمات بالثانية. التجزئة البطيئة المملحة هي المعيار.3التحكم بالوصول
أخطر ثغرة وأسهلها: الواجهة تخفي زر الحذف عن غير المالك، لكن الخادم لا يفحص. المهاجم يرسل الطلب مباشرة. افحص في الخادم دائمًا:
@app.get("/invoices/{invoice_id}")
def get_invoice(invoice_id: int, user = Depends(current_user), db = Depends(get_db)):
invoice = db.get(Invoice, invoice_id)
if invoice is None or invoice.owner_id != user.id:
raise HTTPException(status_code=404) # 404, not 403: do not confirm it exists
return invoiceمثال محلول
المسألة: تطبيق حجوزات يعرض /bookings/1043. مختبر أمان غيّر الرقم إلى 1042 فرأى اسم مريض آخر ورقم جواله. السبب: المسار يجلب الحجز بالمعرّف فقط. الإصلاح: WHERE id = ? AND patient_id = ? ورد 404 لغير المالك، واختبار آلي يطلب حجز مستخدم آخر. درس إضافي: سجّل محاولات الوصول المرفوضة لتكتشف من يجرّب الأرقام.
خرافة مقابل حقيقة
| الخرافة | الحقيقة |
|---|---|
| HTTPS يجعل التطبيق آمنًا. | يحمي الطريق فقط. الحقن وIDOR يمران عبر HTTPS بسلام. |
| إخفاء الزر في الواجهة يكفي. | المهاجم لا يستخدم واجهتك، يرسل الطلبات مباشرة. |
اختبر فهمك
أي طريقة تمنع حقن SQL؟
المعاملات تجعل المدخل بيانات لا كودًا.
كيف تخزن كلمات المرور؟
البطء والملح يجعلان التخمين مكلفًا.
مستخدم غيّر رقم الفاتورة في الرابط ورأى فاتورة غيره. ما الثغرة؟
الخادم لم يفحص ملكية المورد.
بطاقات مراجعة سريعة
تحقق من فهمك
لماذا 404 بدل 403 لمورد لا يملكه المستخدم؟
حتى لا تؤكد للمهاجم أن المورد موجود.
ما خطر DEBUG في الإنتاج؟
صفحات الخطأ تكشف الكود والإعدادات وأحيانًا الأسرار.
كيف تعرف أن مكتبة عندك فيها ثغرة؟
pip-audit أو npm audit أو Dependabot يقارنون إصداراتك بقواعد الثغرات.
مصادر هذا الدرس
مرتّبة بالنوع. ابدأ بالتوثيق الرسمي إذا تبي المرجع الدقيق، وبالمقال أو الفيديو إذا تبي الشرح أولًا.
توثيق رسمي2
خلّصت الدرس؟
سجّل الدخول ليُحفظ تقدّمك.