السلام عليكم ..

بالطبع لا يخفى على أي مبرمج صفحات ويب تفاعلية (مواقع ديناميكية) كمبرمجين (asp - php - jsp - asp.net) أهمية الكوكيز، لأنها العنصر الرئيسي في سكربتات الأعضاء والمنتديات إلخ ..!!!
ونحن نتكلم عنها في php لأنها اللغة التي نبرمج بها، وتعتبر لغة بي اتش بي من أسهل اللغات تعاملا مع الكوكيز، فعند إدخال الكوكيز نستخدم الدالة

setcookie('name',val,time);

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

$_COOKIE['name'];

وطبعاً هذا معروف للمبرمجين.

بعد أن تكلمنا عن إدخال الكوكيز واستخراجها سنتكلم عن مخاطرها وأسرارها..

فما مخاطر الكوكيز ؟

الكوكيز طبعاً هي عبارة عن ملفات تحفظ في جهاز المتصفح للموقع، وطبعاً يجب استخدام أحد المتصفحات لأنها تكون مبرمجة لاستقبال الكوكيز بالشكل الصحيح، وطبعاً لأنها ملفات يمكن تعديلها، ويوجد برامج كثيرة لتعديل الكوكيز مثل Cookie Editor، وأداة التعديل المصاحبة للموزيلا والفايرفوكس ..
وعندما يكون الكوكيز قيمة واحدة ويتم التحقق منها مباشرة، يمكن استغلالها للدخول بمعلومات المسئولين..

مثال:
إذا كانت قيم الكوكيز الموجودة لدينا

user id
user password(md5)

وطبعاً لنفترض أن السكربت محمي ولم يقم بمعرفة الباسوورد، وكان أمر التحقق من الكوكيز كالتالي:

$userid=$_COOKIE['userid'];
$userpwd=$_COOKIE['userpwd'];
$query=mysql_query("select * from users where userid=$userid and userpwd=$userpwd");

أليست هذه هي الطريقة التي يقوم الأغلب بالتحقق بها ؟
طبعاً هنا على اعتقاد المبرمج أنه لا يمكن استغلالها، ولكن هل هذا صحيح؟

جرب أن تضع قيمة الكوكيز

1/*

وانظر ماذا حدث هنا !!
لقد قام بالتحقق من الـ userid فقط وتجاهل الباسوورد باستخدام العلامة /* والتي تنهي الاستعلام.

ثغرة أخرى ..
ضع كوكيز ال userpwd بقيمة

1 or 1=1/*

وانظر ماذا حدث هنا !!

أرأيتم الخطأ البسيط، مالذي قام بعمله؟ لقد حدثت ثغرة خطيرة وهي الدخول حتى بدون كلمة مرور أو اسم مستخدم !

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

أسرار الأمن في الكوكيز

عند القيام باستخراج الكوكيز يجب التحقق من قيمتها، مثلاً لدينا الـ userid قيمة رقمية، أي أنها لا يمكن أن تكون حرفية.
نستخرجها كالتالي:

$userid=intval($_COOKIE['userid']);

وجرب السابق..
أرأيت؟ هنا لا يستطيع استخدام غير الأرقام في الكوكيز.
لكن أيضا userpwd غير محمية.

طبعاً إذا كنت لا تريد ان تقوم بعمل دوال للحماية من هذه الثغرات، فما عليك إلا وضع التحقق من الباسوورد بين علامات التنصيص وثم عمل addslashes عن استخراجه:

$userpwd=addslashes($_COOKIE['userpwd']);

وعند كتابة الاستعلام، أفضل طريقة هي أن يكون الاستعلام كالتالي:

$userid=intval($_COOKIE['userid']);
$userpwd=addslashes($_COOKIE['userpwd']);
$query=mysql_query("select * from users where userid='$userid' and userpwd='$userpwd'");

تلميحة: لدينا هنا كعكة ولها قيمتها

setcookie('PHP',$_POST['username']);

التحقق مثل:

if (!empty($PHP)) {
echo 'مرحباً بك في لوحة التحكم !';
}

الكود السابق يتحقق من أن المتغير $PHP ليس فارغاً. ادخله لوحة التحكم..
هذا خطأ ؟ إذاً ماذا لو طلب هذا الرابط من خلال العنوان كالتالي :

http://localhost/example.php?PHP=Admin

سوف يكون المتغير له قيمة وبالتالي تحقق الشرط السابق فيدخله إلى لوحة التحكم مثلاً.

الذي أريد الوصول له أن نستخدم المصفوفة HTTP_COOKIE_VARS التي تحتوي على قيم الكعكات و يمكننا استخدام المصفوفة _COOKIE اختصاراً للسابقة، إذاً شفرتنا سوف تكون هكذا

if (!empty($_COOKIE['PHP'])) {
echo 'مرحباً بك في لوحة التحكم !';
}

هنا نفس الكود السابق لكن أضاف عليه مصفوفة $_COOKIE

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

setcookie('PHP_username',$_POST['username']);
setcookie('PHP_password',$_POST['username']);

الآن نتحقق بالطريقة الصحيحة و الآمنة، حيث نقوم بتمرير محتوى الكعكات على استعلام و ننظر إلى النتائج كالتالي:

$per = 0; //لا يوجد صلاحيات، قيمه افتراضية لكي لا نسبب ثغرة أمنية

//الاستعلام
$query = mysql_query("SELECT * FROM user WHERE username='" . $_COOKIE['PHP_username'] . "' AND password='" . $_COOKIE['PHP_password'] . "'");
// التأكد من عدد الحقول
$num = mysql_num_rows($query);// إذا كانت عدد الحقول اكبر من الصفر
if ($num> 0) {
$per = 1; // أعطه الصلاحية
}
// و إلا
else {
$per = 0; // لا تعطه الصلاحية
}

أريد أن انوه أن هذا الاستعلام كتب على فرض أن Magic Quotes في حالة التشغيل الذي سوف نقوم بعمله هو التحقق من قيمة المتغير $per كالتالي :

//لديه الصلاحية
if ($per == 1) {
echo 'مرحباً بك في لوحة التحكم'; // يمكنه الدخول
}
// لا يوجد صلاحية
else {
die('المعذرة لا يمكنك الدخول'); // لا يمكنه الدخول
}

تم .