تطبيق : إنشاء صفحة للدّردشة

تصحيح : صفحة delete.php

آخر تحيين: 10-01-2015

دوال SQL تصحيح : صفحة edit.php


delete.php : حذف ردود الدّردشة

ظاهريا ، تبدو عملية حذف المواضيع من القاعدة ، جد سهلة .
مثلا لحذف رد من ردود الدّردشة ،

<?php 
//لا تنسى الإتصال بقاعدة البيانات ...
$id = isset($_GET['id']) ? (int)$_GET['id'] : exit('لا يمكنك القيام بهذه العملية');

$query=$db->prepare('DELETE  
                     FROM chat
                     WHERE id = :id
                   ');
$query->bindValue(':id', $id, PDO::PARAM_INT);
$query->execute();
$query->CloseCursor();
?>

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

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

تخيل أنك مدير الموقع ، وحدك لك الصلاحيات لحذف المواضيع ، و لا أحد ظاهريا ينازعك على هذا . هل أنت متأكّد ؟ ماذا لو قلت لك بأن من استطاعة أي عضو من موقعك أن يخدعك . و يجعلك تحذف أي موضوع يريده هو . كيف ذلك ؟
سيختار العضو مُعرّف id أي موضوع يريد حذفه . ثم سيرسله لك "في رابط الحذف" عبارة عن صورة إلى علبة رسائلك مثلا . صورة بريئة تحثك على نقرها . بمجرّد نقرها سيتم حذف الموضوع . <a href="delete.php?id=3"><img src="pretty.jpg" alt="أنقر هذه الوصلة الرّائعة"></a>
إذاً ، ليس العضو من حذف الموضوع فعليا ، لأنه لا يملك الصلاحيات . بل خدعك و جعلك أنت من قام بذلك دون أن تدري ، بنقرك على الصورة التي تتضمن رابط الحذف .

توجد عدة طرق للحماية من هذه الثغرة : كطلب التأكد من كلمة المرور مثلا للبيانات الحساسة جدّا . أو طلب الموافقة ، قبل البدأ في عملية الحذف ... سنرى هذه الأخيرة ، فهي الأقرب إلينا ، و ستُجنّبنا الكثير من الأسى .

الموافقة على عملية الحذف

بدل أن نحذف الرّد مباشرة ، لا بأس من إضافة استمارة من باب التأكد من هذه العملية . ستكون استمارة بسيطة تحتوي على حقل مخفي .

<h1>هل أنت متأكد من حذف الموضوع !!?  </h1>
<form action="delete.php?id=<?php echo $id;?>" method="post">
  <input type="hidden" name="check" value="">
  <input type="submit" value="نعم"> | <a href="chat.php"> لا </a>
</form>

قبل البدأ في تنفيذ شيفرة الحذف ، يجب أن نتأكد من أن المستخدم قام بالموافقة

if(isset($_POST['check']))
{
  // حذف الرّد
}

صفحة delete.php : الشيفرة كاملة

<?php
try 
{
  $db = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
} 
catch(PDOException $e)
{
  die('خطأ : ' . $e->getMessage());
}

$id = isset($_GET['id']) ? (int)$_GET['id'] : exit('لا يمكنك القيام بهذه العملية');
?>
<!DOCTYPE html>
<html dir="rtl">
<head>
<style>
  body{width:500px;margin:auto;}
  label {display:inline-block;width:60px;font-weight:bold;vertical-align:top;}
  h1 {color:red;}
  h3 {color:blue;}
</style>
</head>
<body>
<h1>هل أنت متأكد من حذف الموضوع !!؟  </h1>
<form action="delete.php?id=<?php echo $id;?>" method="post">
  <input type="hidden" name="check" value="ok">
  <input type="submit" name="submit" value="نعم"> | <a href="chat.php">لا</a>
</form>
</body>
</html>
<?php 
if(isset($_POST['check']))
{
 $query=$db->prepare('DELETE  
                      FROM chat
                      WHERE id = :id
                    ');
 $query->bindValue(':id', $id, PDO::PARAM_INT);
 $query->execute();
 $query->CloseCursor();
 
 echo '<hr><h3> تم حذف الموضوع بنجاح </h3>
        <p>سيتم تحويلك تلقائيا إلى صفحة الدّردشة ...</p>';
 header ('Refresh:4;URL= chat.php');
}

سنتعرف على طرق أخرى داعمة لهذه لاحقا ، تزيد قوة الحماية من هذه الثغرة .

تأكدوا دائما قبل حذف البيانات ، حتى تعلموا بأنكم أنتم من سيقوم بذلك عن سبق الإصرار