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

لفهم السبب ، قمنا بتقسيم أحد الأمثلة غير الناجحة إلى أجزاء أبسط. مثل هذا:
function f(userInput: A): A { const firstCommand: A = ...; const secondCommand: A = ...; return firstCommand.concat(userInput.concat(secondCommand)); }
من الواضح أن
السبب الجذري للهجمات من خلال إدخال الرمز هو أنه لا يوجد فرق بين الأمر وإدخال المستخدم لجهاز الكمبيوتر! لذلك ، يمكن للمهاجم إدخال البيانات التي ستتم معالجتها بشكل إضافي كرمز.بطبيعة الحال ، كما قلت ، هناك دفاعات معروفة ضد مثل هذه الهجمات. بدلاً من ذلك:
"SELECT name FROM users WHERE login = \"" + login + "\""
من الأفضل كتابة شيء مثل هذا:
query("SELECT name FROM users WHERE login = :login", {login})
وبالتالي ، فإن
SELECT name FROM users WHERE login =:login
يتم فصل أمر
SELECT name FROM users WHERE login =:login
بوضوح عن بيانات
{login}
. في الوقت نفسه ، تضمن الآليات الداخلية تحضير البيانات للاستخدام في استعلام SQL. الهروب من الاقتباسات وحقن كود خبيث ستفشل.
ومع ذلك ، يزدهر تطوير تطبيقات الويب. ليس هذا فقط موجود بشكل متزايد:
{ paramA: "the value of the A parameter", paramB: "the value of the A parameter", }
ولكن هذا أيضًا:
{ paramA: "the value of the A parameter", paramB: {$in: [ "the value of the B parameter", "the value of the C parameter", ]}, }
الفرق الكبير بين الخيارين هو أن قيمة المعلمة هي كائن يحتوي على أمر!
لنفترض أن القيم تُقرأ من
userInput
:
{ paramA: userInput.paramA, paramB: {$in: [ userInput.paramB[0], userInput.paramB[1], ]}, }
لا داعي للقلق بشأن قيام المستخدم بتقديم سلسلة ضارة. سيتم التعامل مع كل شيء بطريقة آمنة.
تكمن المشكلة في أن قيم المعلمات لا يمكن أن تكون مجرد قيم بسيطة مثل
the value of the A parameter
، ولكنها أيضًا أوامر ، على سبيل المثال
{$in: ["B", "C"]}
. يمكن للمستخدم إرسال طلب بطرق مختلفة ، بعد فك التشفير الذي يتم الحصول على كائن (النموذج ، JSON أو XML) ، وبالتالي يمكن مهاجمة التعليمات البرمجية عن طريق الحقن.
افترض أن
userInput.paramA
هو
{$empty: false}
. ثم يكون الاستعلام كما يلي:
{ paramA: {$empty: false}, paramB: {$in: [ userInput.paramB[0], userInput.paramB[1], ]}, }
مرة أخرى ، اتضح أنه بالنسبة لجهاز الكمبيوتر ، لا يمكن تمييز الأوامر الموثوقة عن إدخال المستخدم غير الموثوق به.
الآن فقط لا يتعلق الأمر بسلاسل موثوقة وغير موثوقة ، ولكن حول أشياء موثوقة وغير موثوقة.لتجنب هذه المشكلة ، يجب عليك دائمًا كتابة أوامر بحيث لا يمكن تلقيها من المستخدم. يمكن تنفيذ ذلك ، من بين أمور أخرى ، باستخدام النهج المستخدم في
React و
Snabbdom-Signature (هذه مكتبة صغيرة للحماية من الحقن في DOM الافتراضي) ، أي وضع علامة على كل كائن من أمر
Symbol
بحيث لا يمكن إرساله عبر الشبكة.
أعترف ، لقد كنت أعتقد في كثير من الأحيان أنه نظرًا لعدم وجود قاعدة بيانات SQL أو إذا كنت أستخدم DOM الافتراضي ، فإن الهجمات عن طريق حقن الشفرة لا تهددني. كم كنت مخطئا!
LOOKING.HOUSE - جمع المشروع أكثر من 150 نقطة من الزجاج في 40 دولة. يمكنك تنفيذ أوامر المضيف و ping و traceroute و mtr بسرعة.
