زنگ

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

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

قبل از اقدام به به آرایه جهانی $_SERVER در PHPمن فقط یک اشاره کوچک به شما می کنم. یک ویژگی فوق العاده تعبیه شده است PHP، که نامیده می شود phpinfo(). بیایید فوراً مثالی از کاربرد آن بیاوریم:

phpinfo();
?>

در نتیجه اجرای این اسکریپت ساده، یک جدول بزرگ با انواع مختلف مشاهده خواهید کرد تنظیمات مترجم PHP، از جمله، در نزدیکی پایان جدولی از مقادیر وجود خواهد داشت آرایه جهانی $_SERVER. تمام کلیدها و تمام مقادیر مربوط به آنها را فهرست می کند. این چگونه می تواند به شما کمک کند؟ و این واقعیت است که اگر به این یا آن مقدار نیاز دارید و فراموش کردید که کلید چه نامیده می شود، سپس از تابع استفاده کنید phpinfo()شما همیشه می توانید نام آن را به خاطر بسپارید. به طور کلی، شما این اسکریپت را اجرا خواهید کرد و بلافاصله من را درک خواهید کرد.

حالا بیایید به محبوب ترین ها برویم کلیدهای آرایه $_SERVER:

  • HTTP_USER_AGENT- این کلید به شما امکان می دهد ویژگی های مشتری را دریابید. در بیشتر موارد، این قطعاً مرورگر است، اما نه همیشه. و دوباره، اگر مرورگر، پس کدام یک، شما می توانید در مورد این در این متغیر پیدا کنید.
  • HTTP_REFERER- حاوی مسیر مطلق آن فایل ( اسکریپت PHP, صفحه HTML) که از آن به این اسکریپت تغییر داده اید. به طور کلی، مشتری از کجا آمده است.
  • SERVER_ADDR - آدرس آی پیسرور
  • REMOTE_ADDR - آدرس آی پیمشتری.
  • DOCUMENT_ROOT- مسیر فیزیکی به دایرکتوری ریشه سایت. این گزینه از طریق تنظیم شده است فایل پیکربندی سرور آپاچی.
  • SCRIPT_FILENAME- مسیر فیزیکی به اسکریپت فراخوانی شده
  • QUERY_STRING- یک مقدار بسیار مفید که به شما امکان می دهد یک رشته را با یک پرس و جو دریافت کنید و سپس می توانید این رشته را تجزیه کنید.
  • REQUEST_URI- یک مقدار حتی مفیدتر که نه تنها خود درخواست، بلکه مسیر نسبی به اسکریپت فراخوانی شده را از ریشه به همراه آن در بر می گیرد. این اغلب برای حذف موارد تکراری استفاده می شود index.php، یعنی وقتی چنین داریم URL: "http://mysite.ru/index.php"و" http://mysite.ru/"به یک صفحه منجر شود، و URL هامتفاوت است، بنابراین، تکرار، که تاثیر بدی در بهینه سازی موتورهای جستجو خواهد داشت. و اینجا با کمک REQUEST_URIمی توانیم تعریف کنیم: index.phpیا نه اسکریپت فراخوانی شد. و ما می توانیم با تغییر مسیر index.php(اگر حضور داشت REQUEST_URI) بدون index.php. در نتیجه، هنگام ارسال چنین درخواستی: " http://mysite.ru/index.php?id=5"، ما یک تغییر مسیر به URL: "http://mysite.ru/?id=5«.یعنی با حذف از شر تکثیر خلاص شدیم URLاین index.php.
  • SCRIPT_NAME- مسیر نسبی به اسکریپت فراخوانی شده

شاید همه اینها عناصر باشند آرایه جهانی $_SERVER در PHPکه به طور منظم استفاده می شوند. آنها باید بدانند و بتوانند در مواقع لزوم استفاده کنند.

آرایه ابرجهانی $_SERVER

یکی از مهمترین آرایه های از پیش تعریف شده آرایه $_SERVER است - مفسر PHP متغیرهای دریافتی از سرور را در آن قرار می دهد. بدون این متغیرها، سازماندهی پشتیبانی کامل برای برنامه های کاربردی وب دشوار است. مهمترین عناصر آرایه ابرجهانی $_SERVER در زیر توضیح داده شده است.

اظهار نظر

شما می توانید لیست کامل عناصر در آرایه $_SERVER را با تابع print_r() که یک dump از آرایه را چاپ می کند یا با تابع phpinfo() که اطلاعات مربوط به مفسر PHP را نمایش می دهد، مشاهده کنید.

عنصر $_SERVER["DOCUMENT_ROOT"]

عنصر $_SERVER["DOCUMENT_ROOT"] حاوی مسیر دایرکتوری ریشه سرور است؛ اگر اسکریپت در یک میزبان مجازی اجرا شود، این عنصر مسیر دایرکتوری ریشه میزبان مجازی را مشخص می کند. آن ها در فایل پیکربندی httpd.conf، میزبان مجازی دارای یک دستورالعمل DocumentRoot است که روی "D:/main" تنظیم شده است، عنصر $_SERVER["DOCUMENT_ROOT"] حاوی مقدار "D:main" خواهد بود.

عنصر $_SERVER["HTTP_ACCEPT"]

عنصر $_SERVER["HTTP_ACCEPT"] ترجیح مشتری را در مورد نوع سند توصیف می کند. محتوای این عنصر از هدر Accept HTTP که از مشتری به سرور ارسال شده است، بازیابی می شود. محتوای این هدر ممکن است به این شکل باشد

image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/msword, */*

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

نماد * برای گروه بندی انواع در یک ردیف رسانه استفاده می شود. به عنوان مثال، نماد */* استفاده از همه انواع را مشخص می کند، و نوع علامت گذاری/* استفاده از تمام زیرگونه های نوع انتخاب شده را مشخص می کند.

اظهار نظر

انواع رسانه ها با کاما از یکدیگر جدا می شوند.

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

اظهار نظر

پارامتر q به طور پیش فرض 1 است. همچنین با یک نقطه ویرگول از نوع رسانه جدا می شود.

قبول مثال سرصفحه:

پذیرش: صوتی/*; q=0.2، صوتی/پایه

در این هدر نوع اول صدا/* است که شامل تمامی اسناد موسیقایی می شود و با ضریب ترجیح 0.2 مشخص می شود. یک نوع صوتی/پایه جدا شده با کاما مشخص شده است که ضریب ترجیحی برای آن مشخص نشده است و مقدار پیش فرض یک را در نظر می گیرد. به نقل از RFC2616، این عنوان را می توان به صورت زیر تفسیر کرد: "من نوع صوتی/پایه را ترجیح می دهم، اما می توانم اسنادی از هر نوع صوتی دیگری را نیز در صورت وجود، پس از کاهش ضریب ترجیحی بیش از 80٪ ارسال کنم."

مثال می تواند پیچیده تر باشد.

پذیرش: متن/ساده؛ q=0.5، متن/html،
text/x-dvi; q=0.8، متن/x-c

اظهار نظر

توجه داشته باشید که عنصر $_SERVER["HTTP_ACCEPT"] دقیقاً حاوی همان اطلاعات است، اما بدون هدر اولیه Accept.

این هدر به صورت زیر تفسیر می‌شود: نوع سند text/html و text/xc ترجیح داده می‌شوند، اما اگر در دسترس نباشند، مشتری که این درخواست را انجام می‌دهد text/x-dvi را ترجیح می‌دهد و در غیر این صورت ممکن است نوع آن را بپذیرد. متن / ساده

عنصر $_SERVER["HTTP_ACCEPT_LANGUAGE"]

عنصر $_SERVER["HTTP_ACCEPT_LANGUAGE"] تنظیمات زبانی مشتری را توصیف می کند. این اطلاعات از هدر Accept-Language HTTP که توسط مشتری به سرور ارسال شده است، بازیابی می شود. مثال زیر را می توان بیان کرد:

Accept-Language: ru, en; q=0.7

که می توان آن را به صورت زیر تفسیر کرد: مشتری زبان روسی را ترجیح می دهد، اما اگر در دسترس نباشد، با پذیرش اسناد به زبان انگلیسی موافقت می کند. عنصر $_SERVER["HTTP_ACCEPT_LANGUAGE"] دقیقاً حاوی همان اطلاعات است، اما بدون سرصفحه Accept-Language:

ru, en; q=0.7

محتویات عنصر $_SERVER["HTTP_ACCEPT_LANGUAGE"] را می توان برای تعیین ملیت بازدیدکنندگان استفاده کرد. با این حال، نتایج تقریبی خواهد بود، زیرا بسیاری از کاربران از مرورگرهای انگلیسی استفاده می کنند، که به سرور اطلاع می دهد که بازدید کننده تنها یک زبان - انگلیسی را ترجیح می دهد.

عنصر $_SERVER["HTTP_HOST"]

عنصر $_SERVER["HTTP_HOST"] حاوی نام سرور است که معمولاً با نام دامنه سایت میزبانی شده در سرور یکسان است. معمولاً، نامی که در این پارامتر مشخص شده است، همان نام $_SERVER["SERVER_NAME"] است. پارامتر فقط شامل نام دامنه بدون نام پروتکل (http://)، یعنی.

www.sofftime.ru

عنصر $_SERVER["HTTP_REFERER"]

عنصر $_SERVER["HTTP_REFERER"] حاوی آدرس صفحه ای است که بازدیدکننده از آن به این صفحه آمده است. انتقال باید از طریق پیوند باشد. بیایید دو صفحه index.php و page.php ایجاد کنیم.

صفحه index.php

اکو "پیوند به صفحه PHP
"
;
پژواک .
$_SERVER["HTTP_REFERER"]
?>

صفحه page.php محتوای مشابهی خواهد داشت، اما پیوند به صفحه index.php اشاره می کند.

صفحه page.php

اکو "پیوند به صفحه PHP
"
;
اکو "محتوای $_SERVER["HTTP_REFERER"] است ".
$_SERVER["HTTP_REFERER"]
?>

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

عنصر $_SERVER["HTTP_USER_AGENT"]

عنصر $_SERVER["HTTP_USER_AGENT"] حاوی اطلاعاتی درباره نوع و نسخه مرورگر و سیستم عامل بازدیدکننده است.

در اینجا محتوای معمولی این خط است: "Mozilla/4.0 (سازگار؛ MSIE 6.0؛ Windows NT 5.1)". وجود رشته فرعی "MSIE 6.0" نشان می دهد که بازدید کننده صفحه را با استفاده از Internet Explorer نسخه 6.0 مشاهده می کند. رشته "Windows NT 5.1" نشان می دهد که سیستم عامل ویندوز XP است.

اظهار نظر

برای Windows 2000، عنصر $_SERVER["HTTP_USER_AGENT"] به این صورت است: "Mozilla/4.0 (سازگار؛ MSIE 5.01؛ Windows NT 5.0)")"، در حالی که برای Windows XP شبیه "Mozilla/4.0 (سازگار؛ MSIE) است. 6.0)؛ Windows NT 5.1)".

اگر بازدیدکننده از مرورگر Opera استفاده می‌کند، محتویات $_SERVER["HTTP_USER_AGENT"] ممکن است به این شکل باشد: "Mozilla/4.0 (سازگار؛ MSIE 5.0؛ Windows 98) Opera 6.04". زیر رشته "MSIE 6.0" نیز در اینجا وجود دارد که نشان می دهد مرورگر Opera با مرورگر اینترنت اکسپلورر سازگار است و از همان DLL های ویندوز استفاده می کند. بنابراین، هنگام تجزیه رشته بازگردانده شده توسط مرورگر، به خاطر داشته باشید که اینترنت اکسپلورر به رشته ای اطلاق می شود که شامل رشته فرعی "MSIE 6.0" است و حاوی زیررشته "Opera" نیست. علاوه بر این، از این خط می توان نتیجه گرفت که کاربر از سیستم عامل ویندوز 98 استفاده می کند.

اظهار نظر

عامل کاربر مرورگر فایرفاکس ممکن است شبیه Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8) Gecko/20051111 Firefox/1.5 باشد.

هنگام استفاده از مرورگر Netscape، محتوای عنصر $_SERVER["HTTP_USER_AGENT"] ممکن است به این شکل باشد: "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624 Netscape/7.1" . این مرورگر را می توان با وجود زیر رشته "Netscape" شناسایی کرد. علاوه بر این، می توانید متوجه شوید که بازدیدکننده با استفاده از یک سیستم عامل لینوکس با هسته بهینه سازی شده Pentium IV در حالی که در رابط کاربری گرافیکی X-Window است به اینترنت دسترسی دارد. این مکانیسم برای جمع آوری اطلاعات آماری مفید است که به طراحان اجازه می دهد صفحات را برای رایج ترین مرورگرها بهینه کنند.

عنصر $_SERVER["REMOTE_ADDR"]

عنصر $_SERVER["REMOTE_ADDR"] حاوی آدرس IP مشتری است. هنگام آزمایش بر روی یک ماشین محلی، این آدرس 127.0.0.1 خواهد بود. با این حال، هنگام آزمایش در شبکه، متغیر آدرس IP مشتری یا آخرین سرور پراکسی را که مشتری از طریق آن به سرور رسیده است، برمی گرداند. اگر کلاینت از یک سرور پراکسی استفاده می کند، می توانید آدرس IP آن را با استفاده از متغیر محیطی HTTP_X_FORWARDED_FOR، که مقدار آن را با استفاده از تابع getenv() بدست آورید، پیدا کنید.

اظهار نظر

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

در حال بازیابی متغیر محیطی HTTP_X_FORWARDED_FOR

echo getenv(HTTP_X_FORWARDED_FOR)؛
?>

عنصر $_SERVER["SCRIPT_FILENAME"]

عنصر $_SERVER["SCRIPT_FILENAME"] حاوی مسیر مطلق فایل از ریشه درایو است. بنابراین، اگر سرور تحت سیستم عامل ویندوز در حال اجرا است، چنین مسیری ممکن است شبیه به این باشد: "d:main estindex.php"، i.e. مسیر از روی دیسک مشخص می شود، در یک سیستم عامل یونیکس مانند مسیر از دایرکتوری ریشه /، برای مثال "/var/share/www/test/index.php" مشخص می شود.

عنصر $_SERVER["SERVER_NAME"]

عنصر $_SERVER["SERVER_NAME"] حاوی نام سرور است که معمولاً با نام دامنه سایت میزبانی شده در آن مطابقت دارد. مثلا،

www.softtime.ru

محتوای عنصر $_SERVER["SERVER_NAME"] اغلب با محتوای عنصر $_SERVER["HTTP_HOST"] یکسان است. علاوه بر نام سرور، آرایه superglobal $_SERVER به شما امکان می دهد تعدادی از پارامترهای سرور مانند آدرس IP سرور، پورت گوش دادن که وب سرور نصب شده است و نسخه پروتکل HTTP را بیابید. این اطلاعات به ترتیب در عناصر $_SERVER["SERVER_ADDR"]، $_SERVER["SERVER_PORT"]، $_SERVER["SERVER_SOFTWARE"] و $_SERVER["SERVER_PROTOCOL"] قرار می گیرند. در زیر مثالی با استفاده از این عناصر آورده شده است.

با استفاده از عناصر آرایه $_SERVER

echo "نام سرور -". $_SERVER["SERVER_NAME"]. "
" ;
اکو "آدرس آی پی سرور - ". $_SERVER["SERVER_ADDR"]. "
" ;
echo "درگاه سرور -". $_SERVER["SERVER_PORT"]. "
" ;
echo "وب سرور - ". $_SERVER["SERVER_SOFTWARE"]. "
" ;
اکو "نسخه پروتکل HTTP - ". $_SERVER["SERVER_PROTOCOL"]. "
" ;
?>

عنصر $_SERVER["REQUEST_METHOD"]

عنصر $_SERVER["REQUEST_METHOD"] حاوی روش درخواستی است که برای فراخوانی اسکریپت استفاده می شود: GET یا POST.

مؤلفه برای نمایش فرم مجوز استفاده می شود. معمولا در قالب طراحی سایت استفاده می شود. جزء استاندارد است و در کیت توزیع ماژول گنجانده شده است. در ویرایشگر بصری، مؤلفه در امتداد مسیر قرار دارد: سرویس > کاربر.

در ویرایشگر بصری، مؤلفه در امتداد مسیر قرار دارد: ابزارهای سیستم > کاربر > فرم مجوز.

مثال فراخوانی کامپوننت system.auth.form

شرح پارامترها

مکانیسم بازیابی رمز عبور (برای مرجع)

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

  1. کاربر روی آن کلیک می کند رمز عبور خود را فراموش کرده اید؟در فرم مجوز
  2. یک رشته تصادفی از 32 کاراکتر تولید می شود که یک راز فقط برای سرور شناخته شده است.
  3. نتیجه در پایگاه داده نوشته شده و به ایمیل ارسال می شود. مشاهده لینک: http://site.ru/bitrix/admin/index.php?change_password=yes&lang=ru&USER_CHECKWORD=3farde09fay52547f11c68bf17d95760&USER_LOGIN=market، جایی که:
    • http://site.ru/bitrix/admin/index.php - مسیر دسترسی به صفحه مجوز یا تغییر رمز عبور؛
    • change_password=yes - عمل تغییر رمز عبور.
    • lang=ru شناسه زبان;
    • USER_CHECKWORD=- رشته تغییر رمز عبور را بررسی کنید، 32 کاراکتر. رشته از کاراکترها استفاده می کند. موجود برای md5: .

      هنگام تغییر رمز عبور در خط چک، فقط رشته چک را بدون USER_CHECKWORD= وارد کنید!

    • &USER_LOGIN=بازار - نشانی است که رمز عبور برای کدام کاربری در حال تغییر است.
  4. هنگام مقایسه رشته کنترل از فرم با آنچه در پایگاه داده نوشته شده است، زمان انقضا مشخص شده در خط مشی امنیتی گروه در نظر گرفته می شود.

توجه داشته باشید. استفاده از CAPTCHA در قسمت فرم بازیابی رمز عبور توصیه می شود هنگام بازیابی رمز عبور از CAPTCHA استفاده کنیددر تنظیمات ماژول اصلی


Bitrix، 2001-2019، 1C-Bitrix، 2019

Reg.ru: دامنه و هاست

بزرگترین ثبت کننده و ارائه دهنده میزبانی در روسیه.

بیش از 2 میلیون نام دامنه در حال خدمت است.

تبلیغات، پست برای دامنه، راه حل هایی برای تجارت.

بیش از 700 هزار مشتری در سراسر جهان قبلاً انتخاب خود را انجام داده اند.

* ماوس را برای توقف پیمایش.

عقب به جلو

ایجاد یک سیستم ثبت نام کاربری ساده در PHP و MySQL

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

و حتی پس از نوشتن همه اینها، کاربران تمایلی به ثبت نام ندارند، زیرا. نیاز به تلاشی از جانب آنها دارد.

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



در اینجا نحوه عملکرد سیستم فوق العاده ساده ما آمده است:

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

پس از آن، یک مجموعه تصادفی منحصر به فرد از کاراکترها (ژتون) ایجاد می شود که به ایمیل مشخص شده توسط کاربر در قالب پیوندی که به مدت 10 دقیقه مرتبط خواهد بود، ارسال می شود.
- با کلیک بر روی لینک، کاربر به وب سایت ما می رود. سیستم حضور توکن را تعیین می کند و به کاربر اجازه می دهد.

مزایای این رویکرد:

بدون نیاز به ذخیره رمزهای عبور و تأیید فیلدها.
- بدون نیاز به بازیابی رمز عبور، سوالات مخفی و غیره؛
- از لحظه ای که یک کاربر ثبت نام / وارد شده است، همیشه می توانید مطمئن باشید که این کاربر در منطقه دسترسی شما خواهد بود (آدرس ایمیل درست است).
- فرآیند ثبت نام بسیار ساده

معایب:

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

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

بنابراین پیشنهاد می شود از آن برای ثبت نام در انجمن ها و خدماتی که با اطلاعات مهم کار نمی کنند استفاده کنید.

نحوه استفاده از این سیستم

در مواردی که فقط نیاز به استفاده از سیستم برای مجوز دادن به کاربران در سایت خود دارید، و نمی خواهید این درس را جدا کنید، در اینجا کاری که باید انجام دهید:

شما باید فایل های منبع ضمیمه درس را دانلود کنید
- فایل را در آرشیو پیدا کنید tables.sqlبا استفاده از گزینه import در phpMyAdmin آن را به پایگاه داده خود وارد کنید. راه جایگزین: این فایل را با یک ویرایشگر متن باز کنید، پرس و جوی SQL را کپی کنید و آن را اجرا کنید.
- باز کن شامل/main.phpو تنظیمات اتصال به دیتابیس خود را پر کنید ( یوزر و پسورد اتصال به دیتابیس و همچنین هاست و نام دیتابیس را مشخص کنید). در همین فایل باید یک آدرس ایمیل نیز مشخص کنید که به عنوان آدرس اصلی پیام های ارسالی سیستم مورد استفاده قرار گیرد. برخی از هاست‌ها ایمیل‌های خروجی را مسدود می‌کنند تا زمانی که فرم یک آدرس ایمیل واقعی را که از کنترل پنل میزبان ایجاد شده است نشان دهد، بنابراین آدرس واقعی را وارد کنید.
- دانلود تمامی فایل ها index.php, محافظت شده.phpو دارایی ها و شامل پوشه ها از طریق FTP به هاست شما.
- کد زیر را به هر صفحه PHP که می خواهید فرم مجوز نمایش داده شود اضافه کنید.

Require_once "Includes/main.php"; $user = کاربر جدید(); if(!$user->loggedIn())(redirect("index.php"); )
- آماده!

برای کسانی که علاقه مند به نحوه عملکرد آن هستند، در زیر بخوانید!

اولین قدم نوشتن کد HTM برای فرم مجوز است. این کد در فایل قرار دارد index.php. این فایل همچنین حاوی کد PHP است که داده های فرم و سایر ویژگی های مفید سیستم مجوز را مدیریت می کند. می توانید در بخش بررسی کد PHP در زیر اطلاعات بیشتری در مورد این موضوع کسب کنید.

index.php

آموزش: سیستم ثبت فوق العاده ساده با PHP و MySQL

ورود یا ثبت نام

آدرس ایمیل خود را در بالا وارد کنید و ما ارسال خواهیم کرد
لینک ورود شما

در قسمت head (بین تگ ها و) استایل های اصلی را قرار دادم (در این آموزش آنالیز نمی شوند، بنابراین خودتان می توانید آنها را ببینید. پوشه assets/css/style.css). قبل از تگ بسته شدنمن کتابخانه jQuery و فایل script.js را قرار دادم که در زیر می نویسیم و تجزیه و تحلیل می کنیم.


جاوا اسکریپت

jQuery وضعیت دکمه "ثبت نام/ورود" را با یک تابع پیگیری می کند e.preventDefault()و درخواست های AJAX را ارسال می کند. بسته به پاسخ سرور، یک پیام خاص را نمایش می دهد و اقدامات بعدی را تعیین می کند /

assets/js/script.js

$(function()( var form = $("#login-register"); form.on("submit"، function(e)( if(form.is(".loading, .loggedIn"))( return false ; ) var email = form.find("input").val()، messageHolder = form.find("span"); e.preventDefault();$.post(this.action, (ایمیل: ایمیل)، تابع (m)( if(m.error)( form.addClass("خطا")؛ messageHolder.text(m.message)؛ ) else( form.removeClass("خطا").addClass("loggedIn")؛ messageHolder. text(m.message); ))); ))؛ $(document).ajaxStart(function()(form.addClass("بارگیری"); ))؛ $(document).ajaxComplete(function()(فرم. removeClass("بارگیری")؛ )));

برای نمایش وضعیت فعلی درخواست AJAX به فرم اضافه شد (این به لطف روش ها امکان پذیر شد ajaxStart()) و ajaxComplete()، که می توانید در انتهای فایل پیدا کنید).

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

طرحواره پایگاه داده

سیستم ثبت فوق العاده ساده ما از 2 جدول MySQL استفاده می کند (کد SQL در فایل موجود است tables.sql). اولی اطلاعات مربوط به حساب های کاربری را ذخیره می کند. دومی اطلاعات مربوط به تعداد تلاش برای ورود را ذخیره می کند.


طرح جدول کاربر.

سیستم از رمز عبور استفاده نمی کند که در نمودار قابل مشاهده است. روی آن می توانید ستون را ببینید نشانهبا توکن های مجاور ستون token_validity. توکن به محض اتصال کاربر به سیستم تنظیم می شود و ایمیل خود را برای ارسال پیام تنظیم می کند (در بلوک بعدی کمی بیشتر در مورد این موضوع توضیح دهید). ستون token_validityزمان را 10 دقیقه بعد تنظیم می کند و پس از آن رمز دیگر معتبر نیست.


طرح جدولی که تعداد تلاش‌های مجوز را شمارش می‌کند.

در هر دو جدول، آدرس IP به صورت پردازش شده با استفاده از تابع ip2long در یک فیلد عدد صحیح ذخیره می شود.

حالا می توانیم مقداری کد PHP بنویسیم. عملکرد اصلی سیستم به کلاس اختصاص داده شده است user.class.phpکه در زیر می توانید مشاهده کنید.

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

user.class.php

Class User(// Private ORM case private $orm; /** * یافتن کاربر بر اساس نشانه. فقط نشانه های معتبر در نظر گرفته می شوند. رمز فقط به مدت 10 دقیقه از لحظه ایجاد آن ایجاد می شود * @param string $token این همان رمزی است که به دنبال رمز هستید * @return User. مقدار تابع کاربر */ تابع استاتیک عمومی findByToken($token)( // رمز را در پایگاه داده پیدا کنید و مطمئن شوید که مهر زمانی صحیح تنظیم شده است $ result = ORM::for_table("reg_users") ->where ("token", $token) ->where_raw("token_validity > NOW()") ->find_one(); if(!$result)( return false; ) بازگشت کاربر جدید ($result); ) /** * مجوز یا ثبت نام یک کاربر * @param string $email. آدرس ایمیل کاربر * @return کاربر */ عملکرد ثابت عمومی loginOrRegister($email)( // اگر چنین کاربری وجود دارد از قبل موجود است، مقدار تابع User را از آدرس ایمیل مشخص شده ذخیره شده در پایگاه داده برگردانید if(User::exists($email))( return new User($email); ) // در غیر این صورت، یک کاربر جدید ایجاد کنید tel در پایگاه داده و مقدار تابع User::create را از ایمیل مشخص شده بازگردانید User::create($email); ) /** * یک کاربر جدید ایجاد کنید و در پایگاه داده ذخیره کنید * @param string $email. آدرس ایمیل کاربر * @return کاربر */ تابع ثابت خصوصی create($email)( // یک کاربر جدید ثبت کنید و نتیجه تابع کاربر را از این مقادیر برگردانید $result = ORM::for_table("reg_users")- >create(); $result->email = $email؛ $result->save(); return new User($result); ) /** * بررسی کنید که آیا چنین کاربری در پایگاه داده وجود دارد و مقدار بولی متغیر * @param string $email. آدرس ایمیل کاربر * @return boolean */ تابع ثابت عمومی وجود دارد($email)( // آیا کاربر در پایگاه داده وجود دارد؟ $result = ORM::for_table("reg_users") ->where("email", $email ) ->count(); return $result == 1;) /** * یک شی کاربر جدید ایجاد کنید * @param instance $param ORM، شناسه، ایمیل یا 0 * @return User */ تابع عمومی __construct($param = null) ( if($param instanceof ORM)( // چک ORM پاس شد $this->orm = $param; ) other if(is_string($param))( // چک ایمیل پاس شد $this->orm = ORM:: for_table ("reg_users") ->where("email", $param) ->find_one(); ) else($id = 0; if(is_numeric($param))( // مقدار متغیر $param است به شناسه کاربر منتقل شد $id = $param; ) else if(isset($_SESSION["loginid"]))( // در غیر این صورت جلسه $id = $_SESSION["loginid"] را ببینید؛ ) $this->orm = ORM::for_table( "reg_users") ->where("id", $id) ->find_one(); ) ) /** * یک توکن مجوز جدید SHA1 ایجاد کنید، می نویسد به پایگاه داده و مقدار آن را برمی گرداند * @return string */ function public generateToken()( // یک توکن برای یک کاربر مجاز تولید کنید و آن را در پایگاه داده ذخیره کنید $token = sha1($this->email.time().rand (0, 1000000 )); // توکن را در پایگاه داده ذخیره کنید // و علامت گذاری کنید که فقط برای 10 دقیقه آینده معتبر باشد $this->orm->set("token", $token); $this->orm->set_expr("token_validity", "ADDTIME(NOW(),"0:10")"); $this->orm->save(); بازگشت $token; ) /** * مجوز دادن به کاربر * @return void */ عملکرد عمومی login()( // علامت گذاری کاربر به عنوان وارد شده در $_SESSION["loginid"] = $this->orm->id؛ // مقدار را به روز کنید از فیلد پایگاه داده last_login $this->orm->set_expr("last_login", "NOW()"); $this->orm->save(); ) /** * جلسه را نابود کنید و کاربر را از سیستم خارج کنید * @return void */ عملکرد عمومی خروج از سیستم ()($_SESSION = آرایه(); unset($_SESSION); ) /** * بررسی کنید آیا کاربر وارد شده است * @return boolean */ عملکرد عمومی logedIn()( بازگشت isset($ this->orm->id) && $_SESSION["loginid"] == $this->orm->id; ) /** * بررسی کنید آیا کاربر مدیر است * @return boolean */ عملکرد عمومی isAdmin() ( return $this->rank() = = "administrator"; ) /** * نوع کاربر را بیابید، می تواند مدیر یا معمولی باشد * @return string */ public function rank()( if($this->orm- >rank == 1)( return "administrator"; ) return "regular"; ) /** * روشی که به شما امکان می دهد اطلاعات خصوصی را دریافت کنید * به عنوان خصوصیات شی User * @param string $key نام خاصیتی که در حال دسترسی است * @return mixed */ public function __get($key)( if(isset($this->orm->$key)) )( بازگشت $this->orm->$key; ) null را برگرداند. ))

توکن ها با استفاده از الگوریتم SHA1 تولید و در پایگاه داده ذخیره می شوند. من از توابع زمانی MySQL برای تعیین محدودیت انقضای رمز 10 دقیقه ای استفاده می کنم.

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

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

به لطف این، دسترسی به اطلاعات ذخیره شده در پایگاه داده، به لطف ویژگی ها، امکان پذیر می شود $user->email، $user->tokenو غیره در قطعه کد زیر مثالی از نحوه استفاده از این کلاس ها می زنیم.


صفحه محافظت شده

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

functions.php

تابع send_email($from، $to، $subject، $message)( // راهنمای ارسال ایمیل $headers = "MIME-Version: 1.0". "\r\n"; $headers .= "نوع محتوا: متن /plain; charset=utf-8" . "\r\n"; $headers .= "From: ".$from. "\r\n"؛ بازگشت نامه ($to، $subject، $message، $headers ); ) تابع get_page_url()( // دریافت URL فایل PHP $url = "http".(empty($_SERVER["HTTPS"])?"":"s")."://".$_SERVER [ "SERVER_NAME"]; if(isset($_SERVER["REQUEST_URI"]) && $_SERVER["REQUEST_URI"] != "")($url.= $_SERVER["REQUEST_URI"]; ) other($url. = $_SERVER["PATH_INFO"]; ) بازگشت $url؛ ) تابع rate_limit($ip، $limit_hour = 20، $limit_10_min = 10)( // تعداد تلاش‌های ورود به سیستم در ساعت گذشته در این آدرس IP $count_hour = ORM: :for_table("reg_login_attempt") ->where("ip"، sprintf("%u"، ip2long($ip))) ->where_raw("ts > SUBTIME(NOW()،"1:00")") ->count(); // تعداد تلاش‌های ورود به سیستم در 10 دقیقه گذشته در این آدرس IP $count_10_min = ORM::for_table("reg_login_attempt") ->where("ip", sprint f("%u"، ip2long($ip))) ->where_raw("ts > SUBTIME(NOW(),"0:10")") ->count(); if($count_hour > $limit_hour || $count_10_min > $limit_10_min)( new Exception("تعداد زیادی برای ورود به سیستم!") ) تابع rate_limit_tick($ip, $email)( // یک ورودی جدید در جدول ایجاد کنید شمارش تعداد تلاش‌های ورود به سیستم $login_attempt = ORM::for_table("reg_login_attempt")->create()؛ $login_attempt->email = $email؛ $login_attempt->ip = sprintf("%u", ip2long($ip) )؛ $login_attempt->save(); ) تابع redirect($url)( header("مکان: $url"); exit; )

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

کد زیر از فایل گرفته شده است index.phpو ارسال فرم را مدیریت می کند. این یک پاسخ JSON را برمی گرداند که به نوبه خود توسط jQuery در یک فایل پردازش می شود assets/js/script.jsکه قبلاً در مورد آن صحبت کردیم.

index.php

امتحان کنید( if(!empty($_POST) && isset($_SERVER["HTTP_X_REQUESTED_WITH"]))( // خروجی سرصفحه JSON ("Content-type: application/json"); // آیا این آدرس ایمیل معتبر است اگر (!isset($_POST["email"]) || !filter_var($_POST["email"], FILTER_VALIDATE_EMAIL))(exception new ("لطفا یک ایمیل معتبر وارد کنید.")) // بررسی کنید. کاربر مجاز به ورود است، آیا از تعداد اتصالات مجاز فراتر رفته است؟ (فایل functions.php برای اطلاعات بیشتر) rate_limit($_SERVER["REMOTE_ADDR"])؛ // این تلاش برای ورود به سیستم را ثبت کنید rate_limit_tick($_SERVER["REMOTE_ADDR"] , $ _POST["email"])؛ // ارسال یک ایمیل به کاربر $message = ""؛ $email = $_POST["email"]؛ $subject = "پیوند ورود شما"؛ if(!User:: وجود دارد($email) )( $subject = "از ثبت نام شما متشکرم!"; $message = "از اینکه در سایت ما ثبت نام کردید متشکریم!\n\n"؛ ) // تلاش برای مجوز دادن یا ثبت نام کاربر $user = کاربر ::loginOrRegister($_POST[ "email"]); $message.= "شما می توانید از این URL وارد شوید:\n" ; $message.= get_page_url()."?tkn=".$user->generateToken()."\n\n"; $message.= "پیوند به طور خودکار پس از 10 دقیقه منقضی می شود."; $result = send_email($fromEmail، $_POST["email"]، $subject، $message); if(!$result)( throw new Exception("خطایی در ارسال ایمیل شما وجود داشت. لطفا دوباره امتحان کنید."); ) die(json_encode(array("message" => "متشکرم! ما یک پیوند ارسال کردیم. به صندوق ورودی خود. پوشه اسپم خود را نیز بررسی کنید.")))); ) ) catch(Exception $e)( die(json_encode(array("error"=>1, "message" => $e->getMessage( )))))))

پس از تأیید / ثبت نام موفقیت آمیز، کد بالا یک پیوند برای مجوز برای کاربر ارسال می کند. رمز در دسترس می شود زیرا به عنوان یک متغیر در لینک تولید شده توسط متد ارسال می شود $_GETبا نشانگر tkn

index.php

If(isset($_GET["tkn"]))( // آیا این نشانه برای مجوز معتبر است؟ $user = کاربر::findByToken($_GET["tkn"]); if($user)( // بله، است. هدایت به صفحه محافظت شده $user->login(); redirect("protected.php"); ) // خیر، نشانه معتبر نیست. به صفحه با فرم ورود/ثبت redirect("index. php ");)

$user->login()

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

به طور مشابه، پردازش تابع برای خروج از سیستم مرتب شده است.

index.php

If(isset($_GET["logout"]))($user = new user(); if($user->loggedIn())($user->logout(); ) redirect("index.php") ;)

در پایان کد، من دوباره به index.php تغییر مسیر دادم، بنابراین پارامتر ?logout=1ارسال شده توسط URL مورد نیاز نیست.

پرونده ما index.phpاضافی نیاز دارد حفاظت - ما نمی خواهیم افرادی که تا به حال وارد سیستم شده اند دوباره فرم ثبت نام را ببینند. برای این منظور از روش استفاده می کنیم $user->loggedIn().

index.php

$user = کاربر جدید(); if($user->loggedIn())( redirect("protected.php"); )

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

محافظت شده.php

// برای ایمن کردن هر صفحه در سایت خود، یک فایل // main.php اضافه کنید و یک شی User جدید ایجاد کنید. به همین راحتی! require_once "includes/main.php"; $user = کاربر جدید(); if(!$user->loggedIn())( redirect("index.php"); )

پس از این بررسی، می توانید مطمئن شوید که کاربر با موفقیت مجاز شده است. همچنین می توانید با استفاده از ویژگی های شیء به اطلاعات ذخیره شده در پایگاه داده دسترسی داشته باشید $user. برای نمایش ایمیل و وضعیت کاربر از این کد استفاده کنید:

echo "ایمیل شما: ".$user->email; echo "رتبه شما: ".$user->rank();

روش رتبه ()در اینجا استفاده می شود زیرا اعداد معمولاً در پایگاه داده ذخیره می شوند (0 برای یک کاربر معمولی، 1 برای یک مدیر) و ما باید این داده ها را به وضعیت هایی تبدیل کنیم که به آنها تعلق دارند، که این روش به ما کمک می کند.

برای اینکه یک کاربر معمولی را به عنوان مدیر تبدیل کنید، کافی است ورودی کاربر را از طریق phpMyAdmin (یا هر برنامه دیگری که به شما امکان مدیریت پایگاه داده ها را می دهد) ویرایش کنید. وضعیت مدیر هیچ امتیازی نمی دهد، در این مثال، صفحه نشان می دهد که شما یک مدیر هستید - و تمام.

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

انجام شد!

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

مطالب توسط Denis Malyshok به طور خاص برای سایت سایت تهیه شده است

P.S.آیا می خواهید در تسلط بر PHP و OOP بیشتر حرکت کنید؟ نگاهی به آموزش های برتر در مورد جنبه های مختلف ساخت وب سایت، از جمله برنامه نویسی PHP، و همچنین یک دوره رایگان در مورد ساختن سیستم PHP CMS از ابتدا با استفاده از OOP بیندازید:

مطالب را دوست داشتید و می خواهید تشکر کنید؟
فقط با دوستان و همکاران خود به اشتراک بگذارید!


امروز ما به بهره برداری از یک آسیب پذیری حیاتی 1 روزه در CMS محبوب جوملا می پردازیم که در پایان اکتبر در اینترنت منفجر شد. در مورد آسیب پذیری ها با اعداد صحبت خواهیم کرد CVE-2016-8869, CVE-2016-8870و CVE-2016-9081. هر سه از یک تکه کد می‌آیند که برای پنج سال طولانی در اعماق فریم‌ورک مرده بود و منتظر بود تا آزاد شود و هرج‌ومرج، سایت‌های هک شده و اشک‌های کاربران بی‌گناه این جوملا را به ارمغان آورد. فقط شجاع ترین و شجاع ترین توسعه دهندگان که چشمانشان از نور مانیتور قرمز شده است و صفحه کلیدها پر از خرده نان است، توانستند ارواح شیطانی خشمگین را به چالش بکشند و سر خود را بر قربانگاه اصلاحات بگذارند.

هشدار

تمام اطلاعات فقط برای مقاصد اطلاعاتی ارائه شده است. نه ویراستاران و نه نویسنده مسئول هیچ گونه آسیب احتمالی ناشی از مطالب این مقاله نیستند.

چگونه همه چیز شروع شد

در 6 اکتبر 2016، دمیس پالما موضوعی را در Stack Exchange ایجاد کرد که در آن پرسید: چرا در واقع در جوملا نسخه 3.6، دو روش برای ثبت نام کاربران با همان نام register() وجود دارد؟ اولی در کنترلر UsersControllerRegistration و دومی در UsersControllerUser است. Damis می خواست بداند که آیا متد UsersControllerUser::register () در جایی استفاده می شود یا اینکه این فقط یک نابهنگاری تکاملی است که از منطق قدیمی باقی مانده است. او نگران این بود که حتی اگر این روش توسط هیچ دیدگاهی استفاده نشود، می توان آن را با یک درخواست تولید شده فراخوانی کرد. که من پاسخی از توسعه دهنده تحت نام مستعار itoctopus دریافت کردم، که تایید کرد که مشکل واقعا وجود دارد. و یک گزارش برای توسعه دهندگان جوملا ارسال کرد.

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

پس از آن، Davide Tampellini باگ را به حالت ثبت نام یک کاربر ساده، بلکه یک مدیر می چرخاند. و در حال حاضر در 21 اکتبر، یک مورد جدید به تیم امنیتی جوملا می رسد. قبلاً در مورد افزایش امتیازات صحبت می کند. در همان روز، اطلاعیه ای در وب سایت جوملا ظاهر می شود که در روز سه شنبه، 25 اکتبر، نسخه بعدی با شماره سریال 3.6.3 منتشر می شود که یک آسیب پذیری بحرانی در هسته سیستم را برطرف می کند.

در 25 اکتبر، تیم حمله امنیتی جوملا آخرین مشکل ایجاد شده توسط یک قطعه کد کشف شده توسط Damis را پیدا کرد. سپس، یک commit از 21 اکتبر با نام نامشخص Prepare 3.6.4 Stable Release به شعبه اصلی مخزن رسمی جوملا فرستاده می شود که باگ تاسف بار را برطرف می کند.

پس از انتشار این خبر، افراد زیادی علاقه مند به گروه توسعه دهندگان می پیوندند - آنها شروع به چرخش آسیب پذیری و آماده سازی sploit می کنند.

در 27 اکتبر، محقق هری رابرتز یک اکسپلویت آماده را در مخزن Xiphos Research آپلود می کند که می تواند یک فایل PHP را روی سروری با CMS آسیب پذیر آپلود کند.

جزئیات

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

به لطف یافته Damis Palma، می دانیم که دو روش وجود دارد که ثبت کاربر را در سیستم انجام می دهد. اولین مورد توسط CMS استفاده می شود و در فایل /components/com_users/controllers/registration.php:108 قرار دارد. دومی (کسی که باید آن را فراخوانی کنیم) در /components/com_users/controllers/user.php:293 زندگی می کند. بیایید نگاهی دقیق تر به آن بیندازیم.

286: /** 287: * روش ثبت نام کاربر. 288: * 289: * @return boolean 290: * 291: * @since 1.6 292: */ 293: public function register() 294: ( 295: JSession::checkToken("post") یا jexit(JText::_ ("JINVALID_TOKEN"))؛ ... 300: // داده های فرم را دریافت کنید. 301: $data = $this->input->post->get("user", array(), "array"); . .. 315: $return = $model->validate($form, $data)؛ 316: 317: // خطاهای 318 را بررسی کنید: if ($return === false) 319: ( ... 345: / / ثبت نام را تمام کنید.346: $return = $model->register($data);

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

بیایید بفهمیم که در طول ثبت نام کاربر عادی چه اتفاقی می افتد: چه داده هایی ارسال می شوند و چگونه پردازش می شوند. اگر ثبت نام کاربر در تنظیمات فعال باشد، می توانید فرم را در http://joomla.local/index.php/component/users/?view=registration پیدا کنید.


درخواست ثبت نام کاربر قانونی مانند تصویر زیر است.


کامپوننت com_users مسئولیت کار با کاربران را بر عهده دارد. به پارامتر وظیفه در درخواست توجه کنید. فرمت $controller.$method را دارد. بیایید به ساختار فایل نگاه کنیم.

نام اسکریپت در پوشه کنترل کننده هانام کنترل کننده های فراخوانی شده را مطابقت دهید. از آنجایی که درخواست ما اکنون $controller = "registration" دارد، فایل فراخوانی می شود register.phpو متد register() آن.

توجه، سوال این است: چگونه پردازش ثبت نام را به یک مکان آسیب پذیر در کد منتقل کنیم؟ احتمالاً قبلاً حدس زده اید. نام متدهای آسیب پذیر و واقعی یکسان است (رجیستر)، بنابراین فقط باید نام کنترلر فراخوانی شده را تغییر دهیم. و کنترل کننده آسیب پذیر کجاست؟ درست است، در پرونده user.php. معلوم می شود $controller = "user" . با کنار هم گذاشتن همه، task = user.register دریافت می کنیم. اکنون درخواست ثبت نام با روشی که ما نیاز داریم پردازش می شود.


دومین کاری که باید انجام دهیم این است که داده ها را با فرمت صحیح ارسال کنیم. اینجا همه چیز ساده است. register() قانونی آرایه ای به نام jform را از ما انتظار دارد که در آن داده هایی را برای ثبت نام ارسال می کنیم - نام، ورود به سیستم، رمز عبور، نامه (به تصویر صفحه با درخواست مراجعه کنید).

  • /components/com_users/controllers/registration.php: 124: // داده های کاربر را دریافت کنید. 125: $requestData = $this->input->post->get("jform", array(), "array");

فرزند ما این داده ها را از آرایه ای به نام کاربر دریافت می کند.

  • /components/com_users/controllers/user.php: 301: // داده های فرم را دریافت کنید. 302: $data = $this->input->post->get("user", array(), "array");

بنابراین، نام تمام پارامترهای موجود در درخواست را از jfrom به user تغییر می دهیم.

مرحله سوم ما یافتن یک رمز CSRF معتبر است، زیرا بدون آن هیچ ثبت نامی وجود نخواهد داشت.

  • /components/com_users/controllers/user.php: 296: JSession::checkToken("post") یا jexit(JText::_("JINVALID_TOKEN"));

به نظر می رسد یک هش MD5 است و می توانید آن را برای مثال از فرم مجوز در سایت /index.php/component/users/?view=login .


اکنون می توانید از طریق روش دلخواه کاربر ایجاد کنید. اگر همه چیز درست شد، به شما تبریک می گویم - شما فقط از یک آسیب پذیری سوء استفاده کردید CVE-2016-8870"بررسی مجوز از دست رفته برای ثبت نام کاربران جدید."

در روش "working" register() از کنترلر UsersControllerRegistration به شکل زیر است:

  • /components/com_users/controllers/registration.php: 113: // اگر ثبت نام غیرفعال است - به صفحه ورود هدایت شوید. 114: اگر (JComponentHelper::getParams("com_users")->get("allowUserRegistration") == 0) 115: ( 116: $this->setRedirect(JRoute::_("index.php?option=com_users&view= ورود، نادرست))؛ 117: 118: بازگشت نادرست؛ 119: )

و به این ترتیب در اقشار آسیب پذیر:

  • /components/com_users/controllers/user.php:

بله، به هیچ وجه

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

ادامه فقط برای اعضا در دسترس است

گزینه 1. برای خواندن تمام مطالب سایت به انجمن "سایت" بپیوندید

عضویت در انجمن در طول دوره مشخص شده به شما امکان می دهد به همه مطالب هکر دسترسی داشته باشید، تخفیف انباشته شخصی خود را افزایش دهید و به شما امکان می دهد امتیاز حرفه ای Xakep را جمع آوری کنید!

زنگ

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