الخميس، 28 فبراير 2013

شرح الحماية من ثغرات XSS في PHP

بسم الله الرحمن الرحيم،
فى هذه التدوينة الجديدة سأكتب لكم عن ثغرات XSS وكيفية الحماية منها فى لغة PHP، وسينقسم الدرس إلى ثلاثة أجزاء أساسية وهي كالتالي: خطوات قبل العمل، توضيح الثغرة، ترقيع الثغرة.
- خطوات قبل العمل.
بداية سنعمل على ملف سجل للزوار Guest Book ، سنقوم بإنشاء ملف guestbook.php ، وبجواره مجلد core وسيكون بداخله ملف init.inc.php، وبجواره مجلد بإسم inc وبداخله ملف guestbook.inc.php.
والآن سنقوم بتصميم قاعدة بيانات جديدة، حيث نقوم بإنشاء جدول بإسم posts ويحتوى على عمودين فقط، الأول هو post_id والآخر هو post_body.
أما بداخل ملف guestbook.inc.php سنقوم بكتابة الدوال التى سنقوم بإستخدامها فى برنامجنا البسيط، وهذا هو محتوى الملف:
<?php

//adds a new post to the questbook.
function add_post($message){
$message = mysql_real_escape_string($message);
mysql_query("INSERT INTO `posts` {`post_body`} VALUES {'{$message}'}");
}
//fetches all posts from the databse.
function fetch_posts(){
$result = mysql_query("SELECT `post_body` FROM `posts`");
$posts = array();
while(($row = mysql_fetch_assoc()) !== false){
$posts[] = $row['post_body'];
}
return $posts;
}
?>
وكما موضح فى الشيفرة السابقة، هذا الملف يقوم بتعريف دالتين هما add_post و fetch_posts ، وهما دالتين ستسهلان المهام أثناء العمل.
أما بداخل ملف init.inc.php فسنقوم بالإتصال بقاعدة البيانات بالطريقة المعروفة والمنشورة فى كل مكان على الإنترنت، أما بداخل الملف الرئيسي وهو ملف guestbook.php فسنقوم فى أوله بإدراج ملف init.inc.php عبر هذا السطر:
<?php
include "core/init.inc.php";
?>
ومن ثم إضافة تلك السطور تمهيدًا لإنشاء نموذج الإدخال إلى قاعدة البيانات:
if(isset($_POST['message'])){
add_post($_POST['message']);
}
$posts = fetch_posts();
أما بعد عنصر body فى الصفحة نقوم بإضافة تلك السطور لعرض الرسائل التى يتم تسجيلها فى قاعدة البيانات:
foreach($posts as $message){
echo $message;
echo "<hr />";
}
ثم نقوم بإضافة شيفرة النموذج HTML Form الذي سنقوم عن طريقه بإدخال الرسائل:
<form action="" method="post">
<p>
<textarea name="message" rows="10"
cols="80"></textarea>
</p>
<p>
<input type="submit" value="Post">
</p>
</form>
والآن نكون قد إنتهينا من الجزء الأول من الدرس، والآن تستطيع الدخول إلى guestbook.php وإدخال ما تريد ومن ثم الضغط على زر post وسيقوم بدوره على إدخال ما قمت بكتابته إلى قاعدة البيانات ثم عرضه فى الصفحة ، والآن تعال لنفهم ثغرة XSS سويًا !
- توضيح الثغرة.
سنتعرف الآن على كيفية إستغلال ثغرة XSS أو ثغرة Cross-Site Scripting أو بمعني أصح سنتعرف على كيفية عملها ؛ لكي نفهمها ونوضحها.
تلك الثغرة ببساطة هي إمكانية كتابة بعض شيفرات HTML او JavaScript فى النموذج وإدخالها إلى قاعدة البيانات، حيث أن المستخدم من الممكن ألا يقوم بإدخال نصوص عادية فقط، بل يمكنه إدخال شيفرات HTML أو JavaScript والتي بعضها تقوم بدورها فى عمل بعض الأشياء الغير مطلوبة، قد تكون تلك الشيفرة تقوم بالتحويل إلى موقع آخر، أو تقوم بعرض نافذة تزعج المستخدمين، فمثلاً يمكنك كتابة تلك الشيفرة فى النموذج ثم إدخاله، وسترى أنه يتم إدخاله إلى قاعدة البيانات بشكل طبيعي ثم سيتم عمل تحديث للصفحة بشكل طبيعي لكنك سترى أن مدونة مدرسة البي اتش بي هي التي يتم عرضها وليست الصفحة التى قمت ببرمجتها وهذا عبر شيفرة HTML بسيطة وهي كالتالي:
<iframe style="position:fixed; top:0px; left:0px; width:100%; height:100%; border:none; z-index:99;" border="0" src="http://phpitc.blogspot.com/" />
كما سترى، ستقوم تلك الشيفرة بالدخول إلى قاعدة البيانات بشكل طبيعي جدًا، ولكن عند طباعتها فى الصفحة ستدخل تلك الشيفرة إلى رابط المدونة وعرضها بدلًا من عرض محتوى صفحتك وهي سجل الزوار.
- ترقيع الثغرة.
يتمثّل ترقيع الثغرة فى القيام بعملية Encoding للنص الذي يتم إدخاله حيث يتم إستبدال علامة < مثلاً برمز &lt; أثناء التسجيل فى قاعدة البيانات ، لكن عند العرض فى الصفحة ستظهر بالشكل الأصلي < ببساطة، ونستطيع القيام بتلك العلمية عبر دالة htmlentities، ولعمل ذلك سنقوم بالدخول إلى ملف guestbook.inc.php وبداخل دالة add_post نقوم بإضافة هذا السطر فى أول الدالة:
$message = htmlentities($message, ENT_COMPAT, 'UTF-8');
وبهذا ببساطة تكون قد قمت بحماية البيانات المُدخلة من المستخدم من التلاعب بموقعك، وبذلك أنت قمت بحماية موقعك من ثغرات XSS بشكل أساسي، حيث يمكنك بعد ذلك تطوير تلك الشيفرة كما تود لاحقًا.
المزيد من المواضيع:

2 التعليقات:

  1. الاخ احمد
    بعد ادراج كافة الملفات وفي اماكنها كما ذكرت اجد هذا الخطأ
    Fatal error: Call to undefined function fetch_posts() in C:\AppServ\www\project\guestbook\guestbook.php on line 25
    وهو عدم التعرف على fetch_posts()
    وعند إدراج الملف هكذا
    include "inc/guestbook.inc.php";

    بملف guestbook.php
    يظهر الخطأ التالي
    Warning: Wrong parameter count for mysql_fetch_assoc() in C:\AppServ\www\project\guestbook\inc\guestbook.inc.php on line 12

    وهذا هو السطر 12
    while(($row = mysql_fetch_assoc()) !== false){
    تحياتي

    ردحذف
    الردود
    1. استبدله بهذا السطر وجرب
      while(($row = mysql_fetch_assoc($result)) !== false){

      حذف