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

آشنایی با مفهوم 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 ارسال خواهد شد که حاوی اسکریپتی است که این فرم را هَندل خواهد کرد:

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

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


echo $_POST["comment"];

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

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

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

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

همان‌طور که در تصویر فوق مشخص است، یک پاپاپ حاوی عبارت hacked به معنی «شما هَک شده‌اید!» روی صفحهٔ مرورگر نمایش داده می‌شود. این مثال صرفاً یک کد سادهٔ alert در زبان جاوااسکریپت بود که یک پاپاپ را به نمایش در می‌آورد و جمله‌ای را به کاربر نمایش می‌دهد اما مطمئن باشیم که مجرمین سایبری می‌توانند از همین طریق، کدهای به مراتب مخرب‌تری را وارد وب اپلیکیشن ما سازند و امنیت آن را به مخاطره اندازند.

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

اعتبارسنجی داده‌ها 
برای این منظور، نیاز است تا با مفهومی تحت عنوان Data Validation آشنا شویم که به صورت تحت‌الفظی می‌توان آن را به «اعتبارسنجی داده‌ها» ترجمه کرد. اعتبارسنجی داده‌ها به فرایندی گفته می‌شود که در آن این اطمینان را حاصل می‌کنیم که اپلیکیشن ما بر اساس داده‌های درست، صحیح و قابل‌اعتماد کار می‌کند.

به طور مثال، اگر اسکریپت ما برای اجرای درست نیاز به یک عدد صحیح یا Integer دارد، پس هر نوع دادهٔ دیگری مثل اعداد اعشاری، استرینگ و ... می‌بایست اجازهٔ ورود پیدا نکنند. علاوه بر این، هر داده‌ای که کاربران از طریق فرم، یوآرال و ... وارد وب سایت می‌کنند، می‌بایست پس از دریافت اعتبارسنجی شوند تا مطمئن شویم که نوع داده ورودی همانی است که ما نیاز داریم و در غیر این صورت، جلوی کاربر گرفته خواهد شد.

برای مثال، اگر شما در یک فرم HTML از کاربر بخواهید تا شماره تلفن خود را وارد کند، می‌بایست اعتبارسنجی به این صورت انجام شود که کاربر فقط و فقط بتواند عدد صحیح وارد کند و می‌بایست جلوی هر گونه استرینگ که حاوی عدد باشد گرفته شود. علاوه بر این، شما می‌بایست تعداد کاراکترهای این عدد صحیح را هم شمارش کنید تا مطمئن شود به طور مثال برای تلفن همراه در کشور ایران، کاربر یک شمارهٔ 11 رقمی را وارد نموده است. برای روشن‌تر شدن این مسئله، کد زیر را در نظر می‌گیریم:

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

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

تمیز کردن داده‌ها 
در اینجا می‌بایست با مفهوم دیگری تحت عنوان Data Sanitization آشنا شویم. Data که به معنی «داده‌ها» است و واژهٔ Sanitization هم به معنی «بهداشتی کردن» است که در کل می‌توان معادلی همچون «تمیز کردن داد‌ه‌ها» برای این اصطلاح امنیتی در نظر گرفت.

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


<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 و جلوگیری از آن در زبان برنامه نویسی 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 به معنی «تهی کردن، لخت کردن و خالی کردن» است).

کاری که این متد انجام می دهد این است که هر پارامتری که برایش در نظر گرفته شود را از هر گونه تگی از تگ‌های HTML گرفته تا سایر تگ‌ها مثل جاوااسکریپت و ... تهی می‌سازد. در ادامه هم با استفاده از دستور echo قصد داریم تا مقادیر این دو متغیر را نمایش دهیم:


 آشنایی با مفهوم XSS و جلوگیری از آن در زبان برنامه نویسی 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 انجام می‌دهد این است که اگر کاربر هرگونه تگ HTML را وارد فیلد مربوطه کرد (مثل تگ <strong>)، این متد اثربخشی آن تگ را از بین می‌برد و فقط به همان شکلی که کاربر واردش کرده نمایش داده می‌شود:


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

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

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

نتیجه‌گیری 
زمانی که شما سایتی را در دسترس کاربران اینترنتی در سراسر دنیا قرار می‌دهید، این بدان معنا است که طیف گسترده‌ای از افراد را مخاطب خود قرار داده‌اید که در این میان ممکن است با مجرمین سایبری، هکرها و تخریب‌گران آنلاین هم مواجه شوید؛ لذا منطق حکم می‌کند تا در حد توان اپلیکیشن‌تان را از دست این گروه از مخاطبین محافظت نمایید.

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

این مقاله فقط اشارهٔ کوچکی به مفهوم XSS کرده و هکرها راه‌های به مراتب پیشرفته‌تری از موارد ذکر شده در این مقاله را برای تخریب سایت‌ها مورد استفاده قرار می‌دهند، اما این در حالی است که راه‌های به مراتب پیچیده‌تری از راه کارهای ذکر شده در این مقاله هم برای جلوگیری از حملات آنها وجود دارد.

آنچه مسلم است این که اکثر فریمورک‌های حرفه‌ای زبان PHP همچون لاراول، سیمفونی و غیره به صورت پیش‌فرض داده‌های ورودی فرم‌ها را اعتبارسنجی کرده و بار قابل‌توجهی را از دوش دولوپر برمی‌دارند اما باز با این حال می‌بایست خیلی به فریمورک هم اعتماد نکرده و شخصاً اقدام به تست وب اپلکیشن کرد.

اکنون نوبت به نظرات شما می‌رسد. شما چه راه‌کارهای دیگری برای جلوگیری از حملات XSS پیشنهاد می‌دهید؟ نظرات، دیدگاه‌ها و تجربیات خود را با ما و سایر کاربران سکان آکادمی به اشتراک بگذارید.