أمان التطبيقات

مراجعة الكود الآمن

4 دقيقة للقراءة

مراجعة الكود الآمن هي مهارة AppSec أساسية يتم اختبارها في معظم مقابلات الأمن. يغطي هذا الدرس الأدوات والتقنيات والثغرات التي تحتاج لتحديدها.

SAST مقابل DAST مقابل SCA

نوع الأداةما تحللهمتى تعملأمثلة
SASTالكود المصدريوقت البناءSemgrep، CodeQL، SonarQube
DASTالتطبيق قيد التشغيلوقت التشغيلBurp Suite، OWASP ZAP، Nuclei
SCAالتبعياتوقت البناءSnyk، Dependabot، Trivy
IASTالتشغيل + المُجهزوقت التشغيلContrast Security

سؤال المقابلة

س: "ما هي قيود أدوات SAST؟"

الإجابة:

  • الإيجابيات الكاذبة: تعليم الكود الآمن كثغرة
  • لا سياق وقت التشغيل: لا يمكن اكتشاف مشاكل التكوين
  • خاصة باللغة: كل لغة تحتاج قواعد مختلفة
  • عمياء عن منطق العمل: لا تفهم السلوك المقصود

منهجية مراجعة الكود

نهج STRIDE لكل عنصر

عند مراجعة الكود، تحقق بشكل منهجي من:

1. معالجة المدخلات
   └── أين تدخل البيانات الخارجية؟
   └── هل يتم التحقق منها، تنظيفها، تهريبها؟

2. المصادقة
   └── كيف يتم التعامل مع بيانات الاعتماد؟
   └── هل تُدار الجلسات بأمان؟

3. التفويض
   └── هل يتم فرض ضوابط الوصول؟
   └── هل هناك فحص للأدوار/الصلاحيات؟

4. حماية البيانات
   └── هل البيانات الحساسة مشفرة؟
   └── هل الأسرار مكتوبة في الكود؟

5. معالجة الأخطاء
   └── هل الأخطاء تسرب معلومات؟
   └── هل يتم التعامل مع الفشل بأمان؟

اكتشاف الثغرات في الكود

حقن SQL

# ثغرة
def get_user(username):
    query = f"SELECT * FROM users WHERE username = '{username}'"
    return db.execute(query)

# آمن
def get_user(username):
    query = "SELECT * FROM users WHERE username = %s"
    return db.execute(query, (username,))

حقن الأوامر

# ثغرة
import os
def ping_host(host):
    os.system(f"ping -c 1 {host}")

# آمن
import subprocess
def ping_host(host):
    # التحقق من المدخلات
    if not re.match(r'^[\w.-]+$', host):
        raise ValueError("Invalid hostname")
    subprocess.run(["ping", "-c", "1", host], check=True)

اجتياز المسار

# ثغرة
def read_file(filename):
    with open(f"/uploads/{filename}") as f:
        return f.read()

# آمن
import os
def read_file(filename):
    base_dir = "/uploads"
    full_path = os.path.normpath(os.path.join(base_dir, filename))
    # ضمان بقاء المسار ضمن الدليل الأساسي
    if not full_path.startswith(base_dir):
        raise ValueError("Invalid path")
    with open(full_path) as f:
        return f.read()

إلغاء التسلسل غير الآمن

# ثغرة
import pickle
def load_session(data):
    return pickle.loads(base64.b64decode(data))

# آمن
import json
def load_session(data):
    return json.loads(base64.b64decode(data))

تمرين المقابلة: ابحث عن الأخطاء

// كم عدد الثغرات التي يمكنك اكتشافها؟
app.get('/user/:id', async (req, res) => {
    const userId = req.params.id;
    const query = `SELECT * FROM users WHERE id = ${userId}`;

    try {
        const user = await db.query(query);
        res.send(`<h1>Welcome ${user.name}</h1>`);
    } catch (err) {
        res.send(`Error: ${err.message}`);
    }
});

الإجابة:

  1. حقن SQL: إدراج مباشر لـ userId
  2. XSS: user.name غير مهرب في استجابة HTML
  3. كشف المعلومات: رسالة الخطأ الكاملة مكشوفة
  4. AuthZ مفقود: لا فحص إذا كان الطالب يمكنه الوصول لهذا المستخدم

نصيحة المقابلة: عند إعطائك كود للمراجعة، صِف عملية تفكيرك بصوت عالٍ. يريد المحاورون رؤية كيف تجد الثغرات، وليس فقط أنك تجدها.

في الدرس التالي، سنغطي منهجيات نمذجة التهديدات. :::

مراجعة سريعة: كيف تجد هذا الدرس؟

اختبار

الوحدة 3: أمان التطبيقات

خذ الاختبار
نشرة أسبوعية مجانية

ابقَ على مسار النيرد

بريد واحد أسبوعياً — دورات، مقالات معمّقة، أدوات، وتجارب ذكاء اصطناعي.

بدون إزعاج. إلغاء الاشتراك في أي وقت.