آشنایی با مفهوم XSS و به کارگیری آن در زبان برنامه نویسی PHP

Cross-site Scripting یا XSS یکی از مهم ترین انواع حملات سایبری است که هکرها به کمک آنها به سادگی خواهند توانست اقدام به دست کاری در وب اپلیکیشن ها کنند. در واقع، XSS یکی از حملات سایبری است که در آن اساساً تزریق کد (Code Injection) صورت می گیرد به این شکل که با دور زدن اپلیکیشن، به راحتی از طریق فرم های اینترنتی و یا URL وارد اپلیکیشن مد نظر می شوند. این کد می تواند انواع تخریب ها را شامل شود، از ذخیره کردن اطلاعات نامربوط گرفته تا حذف کامل دیتابیس و حتی موارد به مراتب خطرناک تر.

با توجه به اینکه بسیاری از برنامه نویسان تحت وب مسائل امنیتی را رعایت نمی کنند، حملات سایبری از نوع XSS بسیار شایع شده اند. شما به عنوان یک برنامه نویس PHP نیاز دارید تا با این نوع حملات آشنا بوده و راه های مقابله با آنها را نیز فرا بگیرید. امید است با مثال هایی که در این مقاله زده می شود، مفهوم حملات XSS به خوبی روشن گردد:

<form action="post.php" method="post">
    <input name="comment" type="text" />
    <input name="submit" type="submit" value="Submit" />
</form>

در کد فوق یک فرم ساده HTML می بینیم که در آن فیلدی وجود دارد که با استفاده از آن کاربر می تواند نظرات خود را وارد نماید و دکمه ای هم وجود دارد تحت عنوان Submit به معنی "ارسال کردن" که با کلیک بر روی آن، اطلاعات وارد شده در فیلد مربوط به comment برای فایلی تحت عنوان post.php که حاوی اسکریپت PHP است ارسال خواهد شد:

xss in php

تنها کاری که اسکریپت قرار گرفته در فایل post.php انجام می دهد، این است که محتوای وارد شده داخل فیلد مربوط به نظرات را به نمایش در آورد. برای این منظور، کدهای زیر را داخل این فایل می نویسیم:


echo $_POST["comment"];

همانطور که در کد فوق می بینیم، دستور echo را نوشته سپس با استفاده از متدی یا بهتر بگوییم آرایه ای از پیش تعریف شده در زبان برنامه نویسی PHP تحت عنوان POST، مقدار قرار گرفته در فیلد comment را به نمایش در می آوریم. با در نظر گرفتن، این شرایط، هکری پیدا می شود که کد زیر را وارد تنها فیلد این فرم می کند:

<script>
    alert("hacked")
</script>

پس از کلیک روی دکمه Submit با تصویر زیر مواجه خواهیم شد:

xss in php

همانطور که در تصویر فوق مشخص است، یک Popup حاوی عبارت hacked به معنی "شما هَک شده اید!" روی صفحه مرورگر نمایش داده می شود. این مثال صرفاً یک کد ساده alert در زبان جاوا اسکریپت بود که یک Popup را به نمایش در می آورد و جمله ای را به کاربر نمایش می دهد اما مطمئن باشیم که مجرمین سایبری می توانند از همین طریق، کدهای به مراتب مخرب تری را وارد وب اپلیکیشن ما سازند و امنیت آن را به مخاطره اندازند. پیش از این گفتیم یکی دیگر از راه هایی که از آن طریق می توان حملات XSS انجام داد، ارسال کدهای مخرب از طریق URL است. برای روشن شدن این مسئله، کدهای زیر را مد نظر می گیریم:

echo "You searched for: " . $_GET["query"];

کد فوق مربوط به اسکریپتی است که مسئول نمایش نتایج جستجوی کاربر در یک سایت می باشد. این اسکریپت کاملاً ناامن است چرا که اولاً خود Query از لحاظ امنیتی تست نشده است ثانیاً خود Query در معرض دید کاربر قرار می گیرد و یک هکر به سادگی با ارسال URL زیر می تواند به سایت حمله کند:


http://example.com/search.php?query=<script>alert("hacked")</script>

که در نهایت خروجی کد فوق به صورت زیر خواهد بود:

 
You searched for: <script>alert("hacked")</script>

و این در حالی است که اگر وب اپلیکیشن ما از بُعد XSSیی ایمن شده باشد، به هیچ وجه خروجی فوق نشان داده نخواهد شد.

راه های جلوگیری از حملات Cross-site Scripting 
اگرچه هکرها خیلی راحت با یکسری تکنیک های XSSیی می تواند به سایت ما حمله کنند اما این در حالی است که راه های مقابله با Cross-site Scripting نیز بسیار راحت می باشند. ما به عنوان برنامه نویس وب همواره می بایست یک قانون کلی را در طراحی وب اپلیکیشن ها مد نظر داشته باشیم و آن هم اینکه "به هیچ وجه به ورودی هایی که از سمت کاربران و یا سایر منابع به سمت وب سایت ما می رسد اعتماد نکنیم". این یک قانون طلایی برای مقابله با حملات XSSیی است به این صورت که تک تک داده هایی ورودی را تست کرده سپس اجازه ورود به اپلیکیشن یا دیتابیس را به آنها بدهیم.

اعتبارسنجی داده ها 
برای این منظور، نیاز است تا با مفهومی تحت عنوان Data Validation آشنا شویم که به صورت تحت الفظی می توان آنرا به "اعتبارسنجی داده ها" ترجمه کرد. اعتبارسنجی داده ها به فرایندی گفته می شود که در آن این اطمینان را حاصل می کنیم که اپلیکیشن ما بر اساس داده های درست، صحیح و قابل اعتماد کار می کند. به طور مثال اگر اسکریپت ما برای اجرای درست نیاز به یک عدد صحیح یا Integer دارد، پس هر نوع داده دیگری مثل اعداد اعشاری، رشته و ... می بایست اجازه ورود پیدا نکنند. علاوه بر این، هر داده ای که کاربران از طریق فرم، URL و ... وارد وب سایت می کنند می بایست پس از دریافت اعتبارسنجی شوند تا مطمئن شویم که نوع داده آن همانی است که ما نیاز داریم و در غیر این صورت، جلوی کاربر گرفته خواهد شد. برای مثال، اگر شما در یک فرم HTML از کاربر بخواهید تا شماره تلفن خود را وارد کند، می بایست اعتبارسنجی به این صورت انجام شود که کاربر فقط و فقط بتواند عدد صحیح وارد کند و می بایست جلوی هر گونه string یا رشته ای که حاوی عدد باشد گرفته شود. علاوه بر این، شما می بایست تعداد کاراکترهای این عدد صحیح را هم شمارش کنید تا مطمئن شود به طور مثال برای تلفن همراه در کشور ایران، کاربر یک شماره 11 رقمی را وارد نموده است. برای مثال کد زیر را در نظر می گیریم:

  
if (preg_match('/^((1-)?d{3}-)d{3}-d{4}$/', $phone)) {
    echo $phone . " is valid format.";
}

این اسکریپت شماره تلفن را ورودی از سمت کاربر را اعتبار سنجی می کند و اگر کاربر چیزی به غیر از اعداد، یکسری علائم خاص مثل – که برای مجزا سازی بخش های یک شماره تلفن مثلاً جدا سازی کد شهر از شماره تلفن و ... وارد کند، این داده معتبر نخواهد بود.

تمیز کردن داده ها 
در اینجا می بایست با مفهومی تحت عنوان Data Sanitization آشنا شویم. Data که به معنی "داده ها" است و واژه Sanitization هم به معنی "بهداشتی کردن" است که در کل می توان معادلی همچون "تمیز کردن داده ها" برای این اصطلاح امنیتی در نظر گرفت. در کل Data Sanitization به فرایندی اشاره دارد که در آن برنامه نویس به پالایش داده ها می پردازد تا مطمئن شود که داده های ورودی دارای هیچ گونه کدهای ضمیمه شده اضافی نمی باشند. برای مثال، در یک فرم ثبت نام در سایت، در فیلد مربوط به وارد کردن نام و نام خانوادگی، ما این انتظار را از کاربر داریم تا یک string ساده را وارد کنند. حال اگر کاربری پیدا شد (یا بهتر بگوییم هکری پیدا شد) و خواست تا علاوه بر وارد کردن نام و نام خانوادگی خود، یکسری تگ های HTML هم ضمیمه کند، ما می بایست این تگ های اضافی را از string حذف کنیم. برای روشن شدن این مسئله، کدهای زیر را در نظر می گیریم:


<form action="post.php" method="post">
    <input name="first_name" type="text" />
    <input name="last_name" type="text" />
    <input name="submit" type="submit" value="Submit" />
</form>

همانطور که در بالا مشاهده می شود، فرم ساده ای طراحی کرده ایم که حاوی دو فیلد است که یکی مخصوص وارد کردن نام و دیگری مخصوص وارد کردن نام خانوادگی است. پس از کلیک کردن روی دکمه Submit هم داده های فرم برای فایل post.php ارسال می شوند:

xss in php

همانطور که در تصویر فوق مشخص است، در فیلد اول نام را داخل تگ های strong قرار داده ایم که مسئول Bold کردن محتوای داخلش می باشند. در ادامه، با استفاده از متد خاصی در زبان PHP قصد داریم تا داده های فرم را گرفته اما در صورتی که هر گونه تگی به همراه داده ها برای اسکریپت PHP ارسال شد آنها را حذف نماییم. برای این منظور، فایل post.php را به صورت زیر تکمیل می کنیم:


$first_name = strip_tags($_POST["first_name"]);
$last_name = strip_tags($_POST["last_name"]);
echo $first_name;
echo $last_name;

همانطور که در کد فوق می بینیم، دو متغیر داریم تحت عناوین first_name و last_name که به ترتیب به معنای "نام" و "نام خانوادگی" می باشند که از طریق آرایه POST فیلدهایی با همین نام ها را به عنوان Value این دو متغیر در نظر گرفته ایم. در زبان برنامه نویسی PHP متدی داریم تحت عنوان strip_tags که وظیفه تمیز سازی داده ها را بر عهده دارد (واژه strip به معنی "تهی کردن، لخت کردن، خالی کردن و ... " است و tags هم که به معنی "تگ ها" است.) کاری که این متد انجام می دهد این است که هر پارامتری که برایش در نظر گرفته شود را از هر گونه تگی از تگ های HTML گرفته تا سایر تگ ها مثل جاوا اسکریپت و ... تهی می سازد. در ادامه هم با استفاده از دستور echo قصد داریم تا مقادیر این دو متغیر را نمایش دهیم:


xss in php

می بینیم که تگ های strong حذف شده اند و فقط نام و نام خانوادگی نمایش داده شده است.

پالایش خروجی
  علاوه بر موارد فوق الذکر، مفهوم دیگری وجود دارد تحت عنوان Data Escaping که منظور از این اصطلاح این است که در جهت محافظت از یکپارچکی اطلاعاتی که در معرض دید کاربران قرار می گیرد، ما به عنوان برنامه نویس یا توسعه دهنده می بایست داده های خروجی را پالایش کنیم که با اینکار مطمئن خواهیم شد مرورگر مورد استفاده کاربر داده ها را با هیچ گونه معنی و مفهوم خاصی به غیر از آنچه مد نظر ما است را در معرض دید کاربر قرار نخواهد داد. برای روشن شدن این مسئله، فرم بالا را در نظر می گیریم اما یک تغییر کوچک در اسکریپت موجود در فایل post.php خواهیم داد:


$first_name = htmlspecialchars($_POST["first_name"]);
$last_name = strip_tags($_POST["last_name"]);
echo $first_name;
echo $last_name;

همانطور که در کد فوق مشاهده می شود، متد در نظر گرفته شده برای متغیر first_name متدی است تحت عنوان htmlspecialchars و کاری که این متد PHP انجام می دهد این است که اگر کاربر هر گونه تگ اچ تی ام الی را وارد فیلد مربوطه کرد (مثل تگ strong)، این متد اثربخشی آن تگ را از بین می برد و فقط به همان شکلی که کاربر واردش کرده نمایش داده می شود:


xss in php

می بینیم که واژه Behzad نمایش داده شده و این در حالی است که تگ های آغازین و پایانی strong در دو طرف آن قرار دارند بدون آنکه این واژه را Bold کرده باشند. حال اگر متد htmlspecialchars را از داخل اسکریپت خود حذف کنیم، خروجی کدهای فوق به صورت زیر خواهد بود:

xss in php

نتیجه گیری: 
زمانی که شما سایتی را در دسترس کاربران اینترنتی در سراسر دنیا قرار می دهید، این بدان معنا است که طیف گسترده ای از افراد را مخاطب خود قرار داده اید که در این میان ممکن است با مجرمین سایبری، هکرها و تخریب گران آنلاین مواجه شوید. لذا منطق حکم می کند تا در حد توان اپلیکیشن خود را از دست این گروه از مخاطبین محافظت نماییم. برای این منظور، می بایست هر گونه داده ورودی از سمت کاربران را مورد سنجش و ارزیابی قرار داده و در صورتی که جنس داده های ورودی با آنچه مد نظر ما است تفاوت داشت، جلوی کاربر گرفته شده و این موضوع به اطلاع وی برسد تا اصلاح اش کند. علاوه بر این، اگر ورودی کاربران از آزمون اعتبارسنجی داده ها سربلند بیرون نیامدند، می بایست جلوی ورود آنها به اپلیکیشن و دیتابیس گرفته شود و در نهایت هم برای آنکه مطمئن شویم کاربران همان خروجی که مد نظر ما است را مشاهده خواهند کرد، می بایست نتیجه اسکریپت خود را پالایش نموده تا اطمینان حاصل کنیم مرورگرها همان چیزی که مد نظر ما است را در معرض دید کاربران سایتمان قرار می دهند. این مقاله فقط اشاره کوچکی به مفهوم XSS کرده و هکرها راه های به مراتب پیشرفته تری از موارد ذکر شده در این مقاله را برای تخریب سایت ها مورد استفاده قرار می دهند، اما این در حالی است که راه ها به مراتب پیچیده تری از راه کارهای ذکر شده در این مقاله هم برای جلوگیری از حملات آنها وجود دارد.

0


بهزاد مرادی

از جمله علائقم می‌شه به نشر علم،‌ سرمایه‌گذاری روی نسل آینده، برنامه‌نویسی به خصوص زبان PHP و جامعهٔ اپن‌سورس و همچنین راه‌اندازی استارتاپ و کارآفرینی اشاره کرد و اعتقاد دارم که سکان آکادمی می‌تونه بستری باشه که از اون طریق به علائقم جامهٔ عمل بپوشونم!






از طریق این فرم، می توانید بدون ثبت نام نظر دهید و یا اگر قبلا ثبت نام کرده اید، با ورود ناحیه ی کاربری می توانید علاوه بر ثبت نظر، به مدیریت نظرات خود نیز بپردازید.
(فیلد اجباری)
(فیلد اجباری)
(فیلد اجباری)
(فیلد اجباری)