اسکریپت بین سایتی (XSS)

برنامه نویسی متقابل  یک نوع حمله وب مخرب است که در آن یک اسکریپت خارجی به کد یا خروجی وب سایت تزریق می شود. مهاجم می تواند کد آلوده را به کاربر نهایی ارسال کند در حالی که مرورگر نمی تواند آن را به عنوان یک اسکریپت قابل اعتماد شناسایی کند. این حمله بیشتر در مکان هایی رخ می دهد که کاربر توانایی وارد کردن و ارسال داده ها را دارد. این حمله می تواند به کوکی ها، جلسات و سایر اطلاعات حساس در مورد مرورگر دسترسی داشته باشد. بیایید به مثال درخواست GET نگاه کنیم که برخی از داده ها را از طریق URL ارسال می کند:

URL: http://example.com/search.php?search=<script>alert(‘test’)</script>

$search = $_GET[‘search’] ?? null;

echo ‘Search results for ‘.$search;

شما می توانید با استفاده از htmlspecialchars متوجه این حمله شوید. همچنین با استفاده از ENT_QUOTES، می توانید از نقل قول های تکی و دوگانه فرار کنید.

$search = htmlspecialchars($search, ENT_QUOTES, ‘UTF-8’);

echo ‘Search results for ‘.$search;

در همین حال، حملات XSS می‌توانند از طریق ویژگی‌ها، طرح‌های URI رمزگذاری‌شده و کدگذاری کد نیز اجرا شوند.

حملات تزریق SQL (SQL injection )

تزریق SQL رایج ترین حمله در برنامه نویسی PHP است. یک پرس و جو می تواند کل برنامه را در معرض خطر قرار دهد. در حمله تزریق SQL، مهاجم سعی می‌کند داده‌هایی را که از طریق کوئری‌ها ارسال می‌کنید، تغییر دهد. فرض کنید شما مستقیماً در حال پردازش داده های کاربر در کوئری های SQL هستید و ناگهان یک مهاجم ناشناس مخفیانه از کاراکترهای مختلف برای دور زدن آن استفاده می کند. پرس و جوی SQL زیر را ببینید:

$sql = “SELECT * FROM users WHERE username = ‘” . $username . “‘;

 

نام کاربری $ می تواند حاوی داده های تغییر یافته باشد که می تواند به پایگاه داده آسیب برساند، از جمله حذف کل پایگاه داده در یک چشم به هم زدن. بنابراین، راه حل چیست؟ PDO. توصیه می کنم همیشه از عبارات آماده استفاده کنید. PDO به شما در ایمن سازی پرس و جوهای SQL کمک می کند.

$id = $_GET[‘id’] ?? null;

ارتباط بین پایگاه داده و برنامه با عبارت زیر ایجاد می شود:

$dbh = new PDO(‘mysql:dbname=testdb;host=127.0.0.1’, ‘dbusername’, ‘dbpassword’);

 

می توانید نام کاربری را بر اساس شناسه بالا انتخاب کنید اما صبر کنید! در اینجا کد SQL “GET data” به درخواست شما تزریق می شود. مراقب باشید از چنین کدنویسی اجتناب کنید و به جای آن از عبارات آماده شده استفاده کنید:

$sql = “SELECT username, email FROM users WHERE id = “.$id.” ;

foreach ($dbh->query($sql) as $row) {

printf (“%s (%s)\n”, $row[‘username’], $row[’email’]);

اکنون می توانید با استفاده از امکان تزریق SQL فوق اجتناب کنید

$sql = “SELECT username, email FROM users WHERE id = :id”;

$sth = $dbh->prepare($sql, [PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY]);

$sth->execute([‘:id’ => $id]);

$users = $sth->fetchAll();

همچنین، یک روش خوب استفاده از ORM مانند doctrine یا eloquent است، زیرا کمترین امکان تزریق پرس و جوهای SQL در آنها وجود دارد.

جعل درخواست متقابل سایت XSRF/CSRF

حمله CSRF با حملات XSS کاملا متفاوت است. در حمله CSRF، کاربر نهایی می تواند اقدامات ناخواسته ای را در وب سایت های احراز هویت شده انجام دهد و می تواند دستورات مخرب را برای اجرای هر عمل نامطلوب به سایت منتقل کند. CSRF نمی تواند داده های درخواست را بخواند و بیشتر با ارسال هر پیوند یا داده های تغییر یافته در تگ های HTML، درخواست تغییر حالت را هدف قرار می دهد. می‌تواند کاربر را مجبور به انجام درخواست‌های تغییر حالت مانند انتقال وجه، تغییر آدرس ایمیل و غیره کند. بیایید این URL را ببینیم که در آن درخواست‌های GET پول را به حساب دیگری ارسال می‌کند:

GET http://bank.com/transfer.do?acct=TIM&amount=100 HTTP/1.1

حالا اگر کسی بخواهد از برنامه وب سوء استفاده کند، URL را با نام و مقداری مانند این تغییر می دهد

http://bank.com/transfer.do?acct=Sandy&amount=100000

اکنون این URL می تواند از طریق ایمیل در هر فایل، تصویر و غیره ارسال شود و مهاجم ممکن است از شما بخواهد که آن را دانلود کنید

فایل یا روی تصویر کلیک کنید. و به محض انجام این کار، بلافاصله با ارسال مقدار زیادی پول مواجه می شوید که هرگز از آن خبر ندارید.

ربودن session

Session hijacking نوع خاصی از حملات مخرب وب است که در آن مهاجمان به طور مخفیانه شناسه session کاربر را می دزدند. شناسه session به سروری ارسال می‌شود که آرایه $_SESSION مربوطه، فضای ذخیره‌سازی آن را در پشته تأیید می‌کند و به برنامه دسترسی می‌دهد. ربودن session از طریق یک حمله XSS یا زمانی که شخصی به پوشه روی سروری که داده های session در آن ذخیره می شود دسترسی پیدا کند امکان پذیر است.

برای جلوگیری از ربودن session ، همیشه session را به آدرس IP خود متصل کنید:

$IP = getenv ( “REMOTE_ADDR” );

هنگام کار بر روی لوکال هاست مراقب آن باشید زیرا IP دقیقی را در اختیار شما قرار نمی دهد اما مقادیر نوع :::1 یا :::127 را در اختیار شما قرار می دهد. هر زمان که تخلفی رخ داد، باید سریعاً session (کوکی تنظیم نشده، ذخیره‌سازی session تنظیم نشده، حذف ردپاها) را باطل کنید و همیشه سعی کنید شناسه‌ها را تحت هیچ شرایطی فاش نکنید.

برای کوکی ها، بهترین روش این است که هرگز از داده های سریالی ذخیره شده در یک کوکی استفاده نکنید. هکرها می توانند کوکی ها را به راحتی دستکاری کنند و در نتیجه متغیرهایی را به محدوده شما اضافه کنند. با خیال راحت کوکی ها را مانند زیر حذف کنید:

setcookie ($name, “”, 1);

setcookie ($name, false);

unset($_COOKIE[$name]);

خط اول کد تضمین می کند که کوکی در مرورگر منقضی می شود، خط دوم روش استاندارد حذف یک کوکی را نشان می دهد (بنابراین شما نمی توانید false را در یک کوکی ذخیره کنید). خط سوم کوکی را از اسکریپت شما حذف می کند.

مخفی کردن فایل ها از مرورگر

اگر از micro-framework های PHP استفاده کرده اید، پس باید ساختار دایرکتوری خاصی را دیده باشید که قرار دادن فایل ها را به درستی تضمین می کند. فریم‌ورک‌ها اجازه می‌دهند فایل‌های مختلفی مانند کنترل‌کننده‌ها، مدل‌ها، فایل پیکربندی (.yaml) و غیره را در آن دایرکتوری داشته باشید، اما اغلب اوقات مرورگر همه فایل‌ها را پردازش نمی‌کند، اما برای دیدن در مرورگر در دسترس هستند. برای حل این مشکل، نباید فایل های خود را در پوشه اصلی قرار دهید تا همیشه در مرورگر در دسترس نباشند. به ساختار دایرکتوری چارچوب Slim در زیر نگاه کنید:

به طور ایمن فایل ها را آپلود کنید

آپلود فایل بخشی ضروری از هر برنامه پردازش داده های کاربر است. اما به یاد داشته باشید که در برخی موارد، همانطور که قبلاً در مقاله توضیح داده‌ام، از فایل‌ها برای حملات XSS نیز استفاده می‌شود. برای بازگشت به اصول، همیشه از درخواست POST در فرم استفاده کنید و ویژگی enctype=”multipart/form-data” را در تگ <form> اعلام کنید. سپس نوع فایل را با استفاده از کلاس finfo مانند زیر اعتبار سنجی کنید:

$finfo = new finfo(FILEINFO_MIME_TYPE);

$fileContents = file_get_contents($_FILES[‘some_name’][‘tmp_name’]);

$mimeType = $finfo->buffer($fileContents);

 

توسعه‌دهندگان می‌توانند قوانین اعتبارسنجی فایل سفارشی و فوق‌ایمن خود را ایجاد کنند، اما برخی از فریم‌ورک‌ها مانند Laravel، Symfony و codeigniter از قبل روش‌های از پیش تعریف‌شده‌ای برای اعتبارسنجی انواع فایل‌ها دارند.

بیایید به مثال دیگری نگاه کنیم. HTML فرم باید به صورت زیر باشد:

<form method=”post” enctype=”multipart/form-data” action=”upload.php”>

File: <input type=”file” name=”pictures[]” multiple=”true”>

<input type=”submit”>

</form>

و upload.php حاوی کد زیر است:

foreach ($_FILES[‘pictures’][‘error’] as $key => $error) {

if ($error == UPLOAD_ERR_OK) {

$tmpName = $_FILES[‘pictures’][‘tmp_name’][$key];

$name = basename($_FILES[‘pictures’][‘name’][$key]);

move_uploaded_file($tmpName, “/var/www/project/uploads/$name”);

}

}

 

اعلان صحیح UPLOAD_ERR و basename() ممکن است از حملات پیمایش دایرکتوری جلوگیری کند، اما تعداد کمی اعتبارسنجی دیگر – مانند اندازه فایل، تغییر نام فایل و ذخیره فایل های آپلود شده در مکان خصوصی – نیز برای تقویت امنیت برنامه ها مورد نیاز است.

از گواهینامه های SSL برای HTTPS استفاده کنید

همه مرورگرهای مدرن مانند گوگل کروم، اپرا، فایرفاکس و دیگران، استفاده از پروتکل HTTPS را برای برنامه های تحت وب توصیه می کنند. HTTPs یک کانال دسترسی ایمن و رمزگذاری شده برای سایت های غیرقابل اعتماد فراهم می کند. شما باید HTTPS را با نصب گواهی SSL در وب سایت خود وارد کنید. همچنین برنامه های کاربردی وب شما را در برابر حملات XSS تقویت می کند و از خواندن داده های منتقل شده توسط هکرها با استفاده از کدها جلوگیری می کند.

استقرار برنامه های PHP روی ابرها

میزبانی مرحله نهایی و مهم برای هر برنامه وب است، زیرا شما همیشه پروژه را بر روی سرورهای محلی PHP ایجاد کرده و آنها را بر روی سرورهای زنده که میزبانی اشتراکی، ابری یا اختصاصی ارائه می دهند، مستقر می کنید.

تنظیم پوشه root

ریشه سند برای برنامه های PHP در هر سرور باید روی var/www/html تنظیم شود تا کاربران بتوانند از طریق مرورگر به وب سایت شما دسترسی داشته باشند. اما در برخی موارد، زمانی که در حال توسعه API با فریمورک هایی مانند Laravel، Symfony و Slim هستید، باید webroot را به پوشه `/public به روز کنید.

/public خروجی برنامه مشابه وب سایت PHP ساده را با فایل index.php ارائه می دهد. هدف از تنظیم webroot به var/www/html/public مخفی کردن فایل‌های حساسی مانند .htaccess و .env است که حاوی متغیرهای محیطی و اعتبارنامه‌های پایگاه داده، نامه‌ها، APIهای پرداخت هستند.

همچنین، فریم‌ورک‌هایی مانند Laravel، Symfony توصیه می‌کنند که همه فایل‌های خود را به پوشه ریشه منتقل نکنید، در عوض ایجاد یک ساختار دایرکتوری خوب برای ذخیره فایل‌های مرتبط مانند view، مدل‌ها و کنترل‌کننده‌ها رویکرد معقول‌تری است.

همه خطاها را ثبت کنید و نمایش آنها را غیرفعال کنید

هنگامی که وب سایت را توسعه دادید و روی سرور زنده مستقر کردید. اولین کاری که باید انجام دهید این است که نمایش خطاها را غیرفعال کنید، زیرا هکرها ممکن است همان اطلاعات ارزشمند را از خطاها دریافت کنند. این پارامتر را در فایل php.ini خود تنظیم کنید

display_errors=Off

اکنون، پس از خاموش کردن نمایش، خطاهای PHP را برای نیازهای بعدی در یک فایل خاص ثبت کنید:

log_errors=On

error_log=/var/log/httpd/php_scripts_error.log

بدیهی است که شما می توانید نام فایل را به دلخواه تغییر دهید.

آی پی های عمومی برای Mysql را در وایت لیست قرار دهید.

هنگام کار با برنامه های PHP، اغلب باید پایگاه داده mysql را در اسکریپت های داخلی و همچنین در کلاینت های mysql تنظیم کنید. اکثر کلاینت‌ها برای راه‌اندازی اتصال راه دور MySQL استفاده می‌شوند که برای ایجاد اتصال به آدرس IP یا نام میزبان دیگری که توسط سرور میزبان ارائه می‌شود، نیاز دارد.

IP عمومی برای اتصال از راه دور Mysql باید در لیست سفید سرور میزبان شما قرار گیرد تا کاربر ناشناس نتواند به پایگاه داده دسترسی پیدا کند.

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

 

آخرین به روز رسانی: 5 شهریور 1403