Kodax

SQL Injection — الجزء 1: الفهم — الأمن المتقدم

SQL Injection

ما هو SQL Injection؟

هجوم يحقن أوامر SQL ضارة عبر مدخلات المستخدم.

أنواع SQL Injection

Classic SQLi

' OR 1=1 --

Union-based

استخراج بيانات من جداول أخرى.

Blind SQLi

لا يظهر الخطأ، لكن يمكن استنتاجه.

Time-based

استخدام SLEEP() لاستنتاج المعلومات.

الوقاية

- ✅ Prepared Statements

- ✅ Parameterized Queries

- ✅ Input Validation

- ✅ Least Privilege

- ❌ String Concatenation

import sqlite3
import re

class SQLInjectionDemo:
    """
    عرض توضيحي لـ SQL Injection وكيفية الوقاية
    """
    
    def __init__(self):
        # إنشاء قاعدة بيانات للاختبار
        self.conn = sqlite3.connect(':memory:')
        self.cursor = self.conn.cursor()
        self._setup_db()
    
    def _setup_db(self):
        """إعداد جداول الاختبار"""
        self.cursor.execute('''
            CREATE TABLE users (
                id INTEGER PRIMARY KEY,
                username TEXT,
                password TEXT,
                email TEXT,
                is_admin INTEGER
            )
        ''')
        
        # بيانات تجريبية
        users = [
            (1, 'admin', 'admin123', 'admin@example.com', 1),
            (2, 'user1', 'pass123', 'user1@example.com', 0),
            (3, 'user2', 'pass456', 'user2@example.com', 0),
        ]
        self.cursor.executemany(
            'INSERT INTO users VALUES (?, ?, ?, ?, ?)', 
            users
        )
        self.conn.commit()
    
    # ❌ طريقة خاطئة - معرضة للـ SQLi
    def vulnerable_login(self, username, password):
        """
        ⚠️ هذا كود ضعيف! للتوضيح فقط
        """
        query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
        print(f"Query: {query}")
        
        try:
            self.cursor.execute(query)
            result = self.cursor.fetchone()
            return result
        except Exception as e:
            return f"Error: {e}"
    
    # ✅ طريقة صحيحة - محمية
    def secure_login(self, username, password):
        """
        ✅ استخدام Parameterized Queries
        """
        query = "SELECT * FROM users WHERE username=? AND password=?"
        print(f"Query: {query}")
        print(f"Params: ({username}, {password})")
        
        self.cursor.execute(query, (username, password))
        return self.cursor.fetchone()
    
    # التحقق من المدخلات
    @staticmethod
    def validate_input(user_input):
        """
        فحص المدخلات للأنماط المشبوهة
        """
        suspicious_patterns = [
            r"('\s*OR\s*')",
            r"(--)",
            r"(;)",
            r"(UNION\s+SELECT)",
            r"(DROP\s+TABLE)",
            r"(INSERT\s+INTO)",
            r"(DELETE\s+FROM)",
        ]
        
        for pattern in suspicious_patterns:
            if re.search(pattern, user_input, re.IGNORECASE):
                return False, f"نمط مشبوه: {pattern}"
        
        return True, "OK"

# ===== عرض توضيحي =====
demo = SQLInjectionDemo()

print("=== محاولة تسجيل دخول عادية ===")
result = demo.vulnerable_login("admin", "admin123")
print(f"النتيجة: {result}\n")

print("=== هجوم SQL Injection ===")
# ' OR '1'='1 يجعل الشرط دائماً صحيح
malicious_input = "' OR '1'='1"
result = demo.vulnerable_login(malicious_input, malicious_input)
print(f"النتيجة: {result}")
print("⚠️ تم الدخول بدون كلمة مرور صحيحة!\n")

print("=== نفس الهجوم على الكود الآمن ===")
result = demo.secure_login(malicious_input, malicious_input)
print(f"النتيجة: {result}")
print("✅ الهجوم فشل!\n")

print("=== فحص المدخلات ===")
test_inputs = [
    "normaluser",
    "' OR 1=1 --",
    "admin'; DROP TABLE users; --"
]

for test in test_inputs:
    valid, msg = SQLInjectionDemo.validate_input(test)
    status = "✅" if valid else "❌"
    print(f"{status} '{test}' - {msg}")
اختبر فهمك