بوابة موظفين صغيرة نموذج الدخول يأخذ اسم المستخدم وكلمة المرور ويضعهما مباشرة داخل استعلام SQL. لا توجد أي حماية والصفحة تعرض لك الاستعلام الذي نفذه الخادم حتى ترى أثر ما تكتبه
أمامك بوابة موظفي الغربان تطبيق صغير من صفحتين صفحة دخول ولوحة طاقم خلف الدخول صفحة الدخول ترسل اسم المستخدم وكلمة المرور إلى /login والخادم يطبع لك الاستعلام الذي بناه بالضبط فتشوف أثر كل حرف تكتبه حساب admin موجود لكن كلمة مروره عشوائية تتغير كل مرة
يرد الخادم بأنك دخلت بحساب دوره admin.
لماذا نجح الحل
الخادم بنى الاستعلام بلصق ما كتبته داخل نص SQL. علامة الاقتباس التي كتبتها أنهت القيمة النصية فقرأت قاعدة البيانات بقية مدخلك على أنه كود وليس بيانات بالتعليق -- حذفت شرط كلمة المرور فبقي الاستعلام يطلب المستخدم admin فقط القاعدة نفذت بالضبط ما وصلها الخطأ في الكود الذي خلط البيانات بالأوامر
السبب الجذري
السطر الذي يبني الاستعلام بدمج النصوص فيلصق قيمة username داخل نص SQL بين علامتي اقتباس عند قاعدة البيانات لا يوجد حد فاصل بين ما كتبه المبرمج وما كتبه المستخدم فالكل نص واحد يفسر كأوامر
كيف يصلح الكود
الإصلاح هو الاستعلامات ذات المعاملات (parameterized queries): نص الاستعلام ثابت والقيم ترسل منفصلة عنه فلا تستطيع أي علامة في المدخل أن تتحول إلى كود فلترة علامات الاقتباس ليست حلا وكلمات المرور تخزن كـ hash ولا تقارن داخل الاستعلام
الكود المصاب
app.post('/login', (req, res) => {
const { username, password } = req.body;
// Input is pasted into the SQL text: a quote in the input changes the query itself.
const sql = "SELECT id, username, role FROM users " +
"WHERE username = '" + username + "' AND password = '" + password + "'";
const user = db.get(sql);
if (user) startSession(res, user);
});
الكود الآمن
app.post('/login', async (req, res) => {
const { username, password } = req.body;
// Placeholders: the query text is fixed, and the values travel separately as data.
const user = db.get('SELECT id, username, role, password_hash FROM users WHERE username = ?', [username]);
// Passwords are stored as hashes and compared with a password-hashing function.
if (user && (await verifyPassword(password, user.password_hash))) startSession(res, user);
});
الأثر في الواقع
تجاوز الدخول هو أبسط صور حقن SQL وأشهرها في الواقع أدى الحقن إلى تسريب قواعد بيانات كاملة وسرقة بيانات ملايين المستخدمين وهو سنوات طويلة على رأس قائمة OWASP لأخطر ثغرات الويب
كيف يكتشفها المدافعون
المدافع يرصد في سجلات الخادم علامات الاقتباس والتعليقات -- و or 1=1 في حقول الدخول وارتفاع أخطاء SQL كما تكشف أدوات WAF وقواعد الرصد هذه الأنماط لكن الاعتماد عليها وحدها لا يغني عن الإصلاح الجذري