معرفی چند باگ معروف و پچ آن ها در php

آموزش وب ، PHP ، هک و امنیت ،
2825 بازدید
معرفی چند باگ معروف و پچ آن ها در php
معرفی باگ های xss ، csrf و sql injection به همراه مثال های مناسب و آموزش چگونگی پچ این باگ ها

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

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

چند اصطلاح و کلمه در php:

  • باگ (bug): به خطا های برنامه نویسی گفته می شود که در php هم منظور همان خطا هایی است که می تواند به نفوذ مخرب ها کمک کند.
  • پَچ (patch): به رفع باگ ها در php ، پچ باگ گفته می شود. من در این مطلب بیشتر از کلمه ی "رفع باگ" استفاده می کنم.
  • کوکی (cookie): کوکی ها مقادیری هستند که به طور موقت در مرورگر ها ذخیره می شوند و سرور می تواند با استفاده از آن ها عملیاتی را انجام دهد. برای مثال هنگامی که شما به پنل کاربری خود وارد می شوید ، یوزرنیم و پسوردتان در کوکی ها ذخیره می شوند.
  • نشست (session): مقادیری که به صورت رمزگذاری شده در کوکی مروگر کاربر ذخیره می شوند و با هر بار بسته شدن پنجره ی مروگر ، حذف می شوند.

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

  • باگ xss که مخفف Cross Site Scripting است
  • باگ csrf که مخفف Cross Site Recuest Forgery است.
  • باگ sql injection یا تزریق sql

فکر می کنم تا همین حد کافی باشد. اما چند نکته که اگر آن ها را رعایت کنید ، خیلی از مشکلات امنیتی از بین خواهند رفت:

  • تا حدی که می توانید مقادیر و موارد مختلف را محدود کنید. به گونه ای که هکر ها نتوانند اطلاعاتی را که مورد نظر شما نیست به سایتتان بفرستند.
  • تمام موارد را در نظر بگیرید. یعنی این که فکر نکنید همه چیز همان طور که در ذهن شما وجود دارد پیش خواهد رفت.
  • از یک نرم افزار اسکن سایت (مثل Acunetix Web Vulnerability Scanner) بعد از اتمام کار خود استفاده کنید تا ببینید که چه باگ هایی در اسکریپت شما وجود دارد. (البته بعد از این که با باگ های امنیتی آشنا شدید ، دیگر نیازی به این کار نخواهد بود)

باگ xss ( مخفف Cross Site Scripting )

این مشکل امنیتی موقعی به وجود می آید که اطلاعات دریافتی از طرف کاربر ، بدون هیچ گونه فیلتر یا بررسی ای مورد استفاده قرار می گیرند. ما در مثال زیر یک نمونه از این باگ را داریم:

<<<code>>>

<?php

   $v = $_GET['value'];

   echo $v;

?>

<<</code>>>

در مثال بسیار ساده ی بالا شما می توانید به چگونگی به وجود آمدن این باگ پی ببرید. در این کد ، ما فرض می کنیم که یک فرم html اطلاعات را به این صفحه ی php با متد get فرستاده است. مقدار name یکی از موارد فرم ما value است و ما با استفاده از کد قسمت قرمز رنگ آن را در متغیری به نام v ذخیره کرده ایم. تا اینجا هیچ مشکلی نیست. اما همان طور که می بینید ، این مقدار به صورت مستقیم در صفحه چاپ می شود (قسمت آبی رنگ). در این حالت ممکن است هکر به جای این که مقدار مورد نظر ما (فرض می کنیم کلمه ای برای جستجو در سایت) ، که یک مقدار رشته ای بدون علامت است ، را وارد کند ، چیز دیگری را استفاده کند. مثلا ممکن است کد اچ تی ام الی را وارد کند یا از دستورات جاوا اسکریپت استفاده کند. در هر صورت هکر آزاد است هر کاری که دلش می خواهد بکند. اما مشخص است که ما این را نمی خواهیم. علت روشن است. اگر هکر بتواند با استفاده از یک دستور جاوا اسکریپت ، کوکی های مرورگر یکی از کاربران شما را دریافت کند ، می تواند نام کاربری و رمز عبور او را به دست آورد. برای مثال ممکن است هکر کاربر را به آدرس زیر بکشاند و اطلاعات کوکی مروگر او را به روشی به دست آورد:

<<<code>>>

http://localhost/search.php?value=<script>alert( document.cookie );</script>

<<</code>>>

برای حل این مشکل امنیتی در php تابعی وجود دارد. این تابع تمام علامت هایی مثل < ، > و ... را به کد نمایشی آن ها تبدیل می کند و به این ترتیب به جای این که کد وارد شده در آدرس ، در صفحه به عنوان یک تگ وارد شود ، به صورت یک نوشته ی معمولی در می آید:

<<<code>>>

<?php

   $v = $_GET['value'];

   echo htmlspecialchars( $v );

?>

<<</code>>>

این تابع به غیر از مقدار رشته ای که من وارد کرده ام ، می تواند آرگومان های دگیری نیز دریافت کند. برای مطالعه ی کامل در این باره به این مطلب مراجعه کنید.

همچنین می توانید در کنار این تابع از روش های دیگری نیز استفاده کنید. برای مثال می توانید از عبارات باقاعده (Regular Expressions) برای تشخیص صحت مقدار وارد شده کمک بگیرید:

<<<code>>>

<?php

   $v = $_GET['value'];

   if( preg_match( "/^[a-zA-Z0-9 ]+$/" , $v ) ) // فاصله ی بعد از 9 مربوط به فاصله ی بین کلمات است

      echo htmlspecialchars( $v );

?>

<<</code>>>

قسمت قرمز رنگ: مربوط به عبارات باقاعده است. عبارات باقاعده ، نیاز به آموزش بسیار زیادی دارد و در این مطلب جایی برای این بحث نیست. شما می توانید با جتسجو در اینترنت ، آموزشاتی در این باره پیدا کنید. اما فقط این را بدانید که در این عبارت ما مشخص کرده ایم که تنها حروف a تا z (کوچک) ، A تا Z (بزرگ) و 0 تا 9 (عدد) به تعداد نامحدود و بیشتر از صفر امکان چاپ شدن در صفحه را دارند. اگر می خواهید حروف فارسی هم امکان وارد شدن را داشته باشند ، این عبارت را استفاده کنید:

قسمت آبی رنگ: این تابع بر اساس عبارت باقاعده ای که با آن داده می شود ، مقدار رشته ای آرگومان دوم را می سنجد. اگر این مقدار با عبارت همخوانی داشت ، مقدار صحیح (true) و اگر نداشت مقدار غلط (false) را بر می گرداند. این تابع آرگومان های اختیاری دیگری هم دارد.

<<<code>>>

/^[a-zA-Z0-9 اآبپتثجچهخدذرزژسشصضطظعغفقکگلمنوهی]+$/

<<</code>>>

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

باگ csrf ( مخفف Cross Site Recuest Forgery )

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

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

احتمالا تا به حال با فرم هایی در وب برخورد کرده اید که دارای یک input با type="hidden" هستند. این گونه input ها ، اطلاعاتی را در خود نگه می دارند که نیازی به وارد کردن آن ها توسط کاربر نیست. اگر این گونه فرم ها را بعد از هر بار بارگذاری دوباره ی صفحه بررسی کنید ، متوجه خواهید شد که مقدار این input تغییر می کند. حال علت چیست؟

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

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

یک فرم با باگ csrf:

<<<code>>>

<form action="index.php" method="get">

<input type="password" name="password" placeholder="your new password">

<input type="submit">

</form>

<<</code>>>

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

<<<code>>>

http://localhost/index.php?password=123456789

<<</code>>>

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

<<<code>>>

<?php

   session_start();

   $random = rand();

   $_SESSION['random'] = $random;

?>

<form action="index.php" method="get">

<input type="hidden" value="<?= $random ?>" name="rand" />

<input type="password" name="password" placeholder="your new password" />

<input type="submit">

</form>

<<</code>>>

قسمتی که زیر آن خط کشیده شده: در این قسمت مقدار تصادفی نمایش داده می شود. در اصل این قسمت معادل دستور زیر است:

<<<code>>>

<?php echo $random; ?>

<<</code>>>

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

<<<code>>>

<?php

   if( $_SESSION['rand'] == $_GET['rand'] )

   {

         ... // change password

   }

?>

<<</code>>>

حال دیگر هکر هیچ کاری نمی تواند در این باره انجام دهد!

باگ  sql injection یا تزریق sql

این باگ هنگامی در یک فرم یا صفحه به وجود می آید که اطلاعات وارد شده از طرف کاربر بدون هیچ گونه بررسی ای در دستورات sql پایگاه داده مورد استفاده قرار گیرد. این یک مثال از این باگ است:

<<<code>>>

<?php

   $page = $_GET['page'];

   $connect = mysqli_connect( SQL_HOST , SQL_USERNAME , SQL_PASSWORD , SQL_DBNAME );

      $result = mysqli_query( $connect , 'SELECT * FROM pages WHERE id='.$page );

      print_r( mysqli_fetch_array( $result ) );

   mysqli_close( $connect );

?>

<<</code>>>

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

در این مطلب امکان توضیح چگونگی تزریق کد ها توسط هکر نیست اما راه پچ این باگ را در مثال زیر مشاهده کنید:

<<<code>>>

<?php

   $page = $_GET['page'];

   $connect = mysqli_connect( SQL_HOST , SQL_USERNAME , SQL_PASSWORD , SQL_DBNAME );

      $page = mysqli_real_escape_string( $connect , $page );

      $result = mysqli_query( $connect , 'SELECT * FROM pages WHERE id='.$page );

      print_r( mysqli_fetch_array( $result ) );

   mysqli_close( $connect );

?>

<<</code>>>

در قسمت قرمز رنگ شما یک تابع جدید را می بیند. این تابع می تواند دستورات Sql را از بین ببرد و این موضوع باعث می شود که حتی اگر هکر بخواهد دستوراتی را تزریق کند ، هیچ فایده ای نداشته باشد.

 همان طور که در قسمت باگ xss هم گفته شد ، در اینجا هم شما می توانید با استفاده از عبارات باقاعده ، مقدار وارد شده توسط کاربر را بررسی کنید و در صورت ورود مقدار صحیح ، اجازه ی اجرای ادامه ی دستورات را بدهید.

 

این مطلب به پایان رسید. اما هنوز مسائل زیادی هستند که نیاز به مطالب طولانی زیادی دارند. منتظر این گونه مطالب باشید.

رمز تمام فایل های فشرده
رمز فایل فشرده است.